Compare commits

...

3 commits
v0.3.2 ... main

Author SHA1 Message Date
e7b2326521 Synchronize local branch after publishing
Some checks are pending
Validate Decky / web-client (push) Waiting to run
2026-07-20 09:35:51 -07:00
a0b46497c1 Add Decky agent guidance
Some checks are pending
Validate Decky / web-client (push) Waiting to run
2026-07-20 09:33:34 -07:00
134a0ea05b chore(release): publish Decky 0.3.2 updater metadata
Some checks are pending
Validate Decky / web-client (push) Waiting to run
2026-07-20 09:16:08 -07:00
4 changed files with 105 additions and 16 deletions

54
AGENTS.md Normal file
View file

@ -0,0 +1,54 @@
# Decky agent notes
## Project
- The active app is `app/`: Tauri 2 + Svelte 5 + TypeScript. The older .NET
projects under `src/` and `tests/` are reference code, not the product.
- Decky is a compact, Nextcloud-inspired desktop client for Nextcloud Deck.
Preserve its dark native title bar, horizontal/vertical views, drag-and-drop,
compact cards, collapsible sidebar, and footer-free layout.
- Background sync begins after 10 seconds idle and repeats every 30 seconds. It
must pause during edits, drags, loading, modals, and while the window is hidden.
- Never store or commit Nextcloud credentials. Use an app password and the OS
credential store. Live-instance tests require the user to enter credentials.
## Nextcloud API compatibility
- Client code and tests are in `app/src/lib/deck-api.ts` and
`app/src/lib/deck-api.test.ts`.
- Support both documented `index.php/apps/deck/api/v1.0/` and rewrite-friendly
`apps/deck/api/v1.0/` paths.
- Preserve complete card fields on updates, including color and object/string
owner handling. Keep the tested cross-stack card-move fallback.
- Stack reorder uses Deck's OCS reorder endpoint and verifies persisted order.
- Respect board permissions before exposing edit/manage/delete controls.
## Validation
From `app/`, run `npm ci`, `npm run check`, `npm test`, and `npm run build`.
Build Windows installers on this Windows machine; the Unraid Forgejo Docker
runner only validates the web client via `.forgejo/workflows/validate.yml`.
## Versions and releases
- Installed apps update from signed Forgejo Release assets, never from Git.
- A released version/tag is immutable. Always increment the semantic version;
never republish or replace assets for an existing version.
- Use `scripts/Set-Version.ps1` to synchronize npm, Cargo, Tauri, and the browser
fallback. Commit and push source to `main` before publishing the release.
- Build/sign with `scripts/Prepare-Release.ps1`. Generated files live under
`artifacts/release/vX.Y.Z/` and stay out of Git.
- Publish by double-clicking `scripts/Publish-DeckyRelease.cmd` or by invoking
`scripts/Publish-ForgejoRelease.ps1`. The publisher creates the tag/release,
uploads the installer/signature, commits `releases/latest.json` to `main`, and
automatically fast-forwards the local checkout to that metadata commit.
- The publisher requires a clean `main` that exactly matches `origin/main`, so
commit and push source first. LF-to-CRLF messages on Windows are warnings,
not failures.
- Forgejo: `https://git.elijahkuntz.com/Elijah/Decky`. A publishing PAT needs
`write:repository`; never commit or print it.
- The permanent Tauri updater key is outside the repository at
`%USERPROFILE%\.tauri\decky.key` with its password beside it. Never expose,
replace, or regenerate this key after releases have shipped.
See `app/UPDATES.md` for the complete release procedure.

View file

@ -73,7 +73,6 @@ current PowerShell process and run:
$env:FORGEJO_PAT = 'paste-token-for-this-session'
powershell -ExecutionPolicy Bypass -File .\scripts\Publish-ForgejoRelease.ps1 -Version 0.3.0 -Notes "Board and stack management"
Remove-Item Env:FORGEJO_PAT
git pull --ff-only
```
For an interactive, double-clickable option, run:
@ -86,11 +85,12 @@ It bypasses PowerShell's script policy only for the publisher process, prompts
for the version and a hidden personal access token, and leaves the window open
so any error can be read. The token is not saved.
The publisher creates the `v0.3.0` Forgejo release/tag at `main`, uploads the
installer, signature, and metadata, then commits the tracked
`releases/latest.json` through the Forgejo API. The final pull synchronizes that
small metadata commit locally. Existing Decky installations then discover the
release through Settings.
The publisher first verifies that the working tree is clean and local `main`
exactly matches `origin/main`. It then creates the `v0.3.0` Forgejo release/tag,
uploads the installer, signature, and metadata, and commits the tracked
`releases/latest.json` through the Forgejo API. Finally, it automatically
fast-forwards local `main` to that metadata commit. Existing Decky installations
then discover the release through Settings.
## Forgejo Actions

View file

@ -1,11 +1,11 @@
{
"version": "0.3.1",
"notes": "Automatic idle-aware background refresh for boards, stacks, and cards.",
"pub_date": "2026-07-20T15:55:49.5091194+00:00",
"version": "0.3.2",
"notes": "Removed the bottom status bar, moved the updated time beside Refresh, and cleaned malformed text encoding.",
"pub_date": "2026-07-20T16:13:33.7170490+00:00",
"platforms": {
"windows-x86_64": {
"signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTSHZBY0NPTW9uREdMTkg2RWVNeU53anpNRy9SYy9LS3RnS3I5a0FSVzJrRVZ5Y1NjdHlId2VaRi9YcnNyZnF3YjRIT3VuRVVNOGt2Zk8wWmZObGpYWmFJc2xpRENVOEFnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg0NTYyOTQ4CWZpbGU6RGVja3lfMC4zLjFfeDY0LXNldHVwLmV4ZQpDeEphcVV0T2hkc09kYUJxak14UnU1N1h6L3dJTWhDV2Rqa3Nhc21sTWxuS0VYWW5scEhYakx5MDJ5bVdmbmRkTnphWjdib3BHTCtYVm5yMGZldHdCQT09Cg==",
"url": "https://git.elijahkuntz.com/Elijah/Decky/releases/download/v0.3.1/Decky_0.3.1_x64-setup.exe"
"signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVTSHZBY0NPTW9uREMyYUlZNUJnYzhqRHRlTE1qeDZCYlZtVXRGRDZtZER5V2p1V3ZBdXprVndkZ3FqNURzQitoUG1ZWFdFQytxRFFzQ1BMNnJnVE10ZlhCYm5UQk9NTFFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg0NTY0MDEyCWZpbGU6RGVja3lfMC4zLjJfeDY0LXNldHVwLmV4ZQpLOGZ4TXp6V0xYalp6czNDbitleVhBSVlrZHNLT0ZQSmhiTjFGeXlNTUVEYy8vSS9JdlZwQUdiNWdOL0NvcXVFcTVJWDhXWXZwQnhlUnh2Z0xER3dEdz09Cg==",
"url": "https://git.elijahkuntz.com/Elijah/Decky/releases/download/v0.3.2/Decky_0.3.2_x64-setup.exe"
}
}
}

View file

@ -12,6 +12,35 @@ param(
)
$ErrorActionPreference = 'Stop'
$repositoryRoot = Split-Path -Parent $PSScriptRoot
$releaseDirectory = Join-Path $repositoryRoot "artifacts\release\v$Version"
$latestJsonPath = Join-Path $releaseDirectory 'latest.json'
if (-not (Test-Path -LiteralPath $latestJsonPath)) { throw "Run Prepare-Release.ps1 first: $latestJsonPath is missing." }
function Invoke-GitCommand {
param([Parameter(Mandatory)][string[]]$ArgumentList)
$output = @(& git -C $repositoryRoot @ArgumentList 2>&1)
if ($LASTEXITCODE) {
throw "git $($ArgumentList -join ' ') failed: $($output -join [Environment]::NewLine)"
}
return $output
}
$branch = ((Invoke-GitCommand @('rev-parse', '--abbrev-ref', 'HEAD')) | Select-Object -Last 1).Trim()
if ($branch -ne 'main') { throw "Releases must be published from main; the current branch is '$branch'." }
$workingChanges = @(Invoke-GitCommand @('status', '--porcelain'))
if ($workingChanges.Count) {
throw "Commit or discard all source changes before publishing:`n$($workingChanges -join [Environment]::NewLine)"
}
Invoke-GitCommand @('fetch', 'origin', 'main') | Out-Null
$localHead = ((Invoke-GitCommand @('rev-parse', 'HEAD')) | Select-Object -Last 1).Trim()
$remoteHead = ((Invoke-GitCommand @('rev-parse', 'origin/main')) | Select-Object -Last 1).Trim()
if ($localHead -ne $remoteHead) {
throw 'Local main does not exactly match origin/main. Pull/rebase or push the source before publishing.'
}
if (-not $Token) {
Write-Host 'A Forgejo personal access token is required to create the release.' -ForegroundColor Cyan
Write-Host 'The token is used only by this process and is not saved by Decky.' -ForegroundColor DarkGray
@ -20,11 +49,6 @@ if (-not $Token) {
}
if (-not $Token) { throw 'No Forgejo personal access token was entered.' }
$repositoryRoot = Split-Path -Parent $PSScriptRoot
$releaseDirectory = Join-Path $repositoryRoot "artifacts\release\v$Version"
$latestJsonPath = Join-Path $releaseDirectory 'latest.json'
if (-not (Test-Path -LiteralPath $latestJsonPath)) { throw "Run Prepare-Release.ps1 first: $latestJsonPath is missing." }
$headers = @{ Authorization = "token $Token"; Accept = 'application/json' }
$apiRoot = "$($ForgejoBaseUrl.TrimEnd('/'))/api/v1/repos/$Repository"
$tag = "v$Version"
@ -82,3 +106,14 @@ $contentBody = @{
if ($sha) { $contentBody.sha = $sha }
Invoke-RestMethod -Method Put -Uri "$apiRoot/contents/releases/latest.json" -Headers $headers -ContentType 'application/json' -Body ($contentBody | ConvertTo-Json) | Out-Null
Write-Host "Published Decky $Version and updated releases/latest.json."
Invoke-GitCommand @('fetch', 'origin', 'main') | Out-Null
$publishedHead = ((Invoke-GitCommand @('rev-parse', 'origin/main')) | Select-Object -Last 1).Trim()
if ($publishedHead -ne $localHead) {
$mergeBase = ((Invoke-GitCommand @('merge-base', $localHead, $publishedHead)) | Select-Object -Last 1).Trim()
if ($mergeBase -ne $localHead) {
throw 'The release was published, but origin/main also changed independently. Fetch and reconcile it manually.'
}
Invoke-GitCommand @('merge', '--ff-only', 'origin/main') | Out-Null
}
Write-Host 'Local main is synchronized with the Forgejo release metadata commit.'