Add winget, Scoop, AUR, deb, and rpm release channels - #47
Conversation
Adds a sixth release channel: `dotnet tool install --global SiGit.Code`. A .NET tool is a single package rather than one artifact per platform, so nuget/sigit/ bundles all six native binaries under native/<os>-<arch>/ and a small managed shim execs the right one. This is the pattern smbcloud-cli and onde-cli already use. The shim leaves stdin, stdout, and stderr unredirected so sigit's TTY check still picks TUI or ACP mode correctly. Two things worth knowing about it: The shim sets RollForward=Major. It targets net8.0, and without that a machine carrying only the .NET 10 runtime installs a tool that refuses to start with "You must install or update .NET to run this application". Bundling every target makes the package large, so the pack job fails if the .nupkg crosses nuget.org's 250 MB limit. At v1.5.1 it lands near 160 MB. If that check ever trips, split into RID-specific tool packages instead of dropping targets. Also sets strip = "symbols" on the release profile. That takes the macOS arm64 binary from 102 MB to 88 MB and shrinks every channel, not just this one.
Covers the OS package managers sigit had no presence in. Windows users get winget and Scoop, Arch users get sigit-bin from the AUR, and Debian and Fedora users get a .deb and .rpm attached to each GitHub release. All four of the new channels read checksums off the GitHub release, so release-github.yml now writes a .sha256 next to every asset rather than only the macOS Homebrew tarball, and dispatches the packaging workflows once the release exists. A dispatch that fails is a warning, not a failed release, so a channel nobody has configured yet cannot block the others. The .deb and .rpm are built with nfpm from the binary the matrix already produced, so each Linux target still compiles once. One config covers both formats. AUR publishes sigit-bin rather than a source package. Building sigit from source pulls in the whole on-device inference stack, which is a lot to ask of someone installing a CLI. Scoop and the AUR follow the existing Homebrew tap shape: generate the manifest, push it to a sibling repo. winget is different because its manifests live in microsoft/winget-pkgs, so that workflow submits a PR through wingetcreate and only handles updates. The first submission has to be made by hand, since wingetcreate cannot update a package that does not exist yet. Still needs credentials before any of it publishes: a getsigit/scoop-bucket repo with SCOOP_BUCKET_TOKEN, WINGET_TOKEN, and the three AUR_* secrets.
There was a problem hiding this comment.
Adds five new OS package-manager release channels (winget, Scoop, AUR, deb, rpm). release-github.yml now writes a .sha256 sidecar for every asset, builds .deb/.rpm via nfpm from the already-staged binaries, and fans out workflow dispatches to homebrew/scoop/winget/aur (dispatch failures downgraded to warnings). New workflows read checksums off the release and publish to their respective destinations. Docs updated in AGENTS.md and README.md.
Review focus: the AUR PKGBUILD's hardcoded source URL vs. the checksummed .sha256 sidecars, and whether the nfpm binary rename step correctly produces the .deb/.rpm before the checksum step runs.
Automated review by siGit Code · commit ccfaae9
| --pattern "sigit-linux-*.sha256" \ | ||
| --dir artifacts/ | ||
|
|
||
| X86_64_SHA=$(cat artifacts/sigit-linux-amd64.sha256) |
There was a problem hiding this comment.
critical — The .sha256 sidecars contain the checksum of the full binary asset, but PKGBUILD's source_x86_64 downloads that same binary — so the sha must match. Confirm the sidecar hashes the raw sigit-linux-amd64 binary and not a renamed/archived variant, otherwise makepkg validation fails.
| -e "s/@SHA256_AARCH64@/${{ steps.sha.outputs.aarch64 }}/g" \ | ||
| packaging/aur/PKGBUILD.in > aur-build/PKGBUILD | ||
|
|
||
| if grep -q '@[A-Z0-9_]*@' aur-build/PKGBUILD; then |
There was a problem hiding this comment.
warning — The placeholder grep @[A-Z0-9_]*@ matches @@ (empty), so a completely-failed substitution leaving a bare @@ would still trip it, but a value containing @ (e.g. an unexpected sha) wouldn't be caught — minor, but also note this grep runs before bash -n which is good.
| shell: bash | ||
| run: | | ||
| cd release | ||
| for asset in *; do |
There was a problem hiding this comment.
warning — The checksum loop runs on every matrix job but only Linux jobs produce .deb/.rpm; ensure the nfpm packages are staged into release/ before this step and that .deb/.rpm sidecars are actually wanted (they are checksummed but no channel consumes them).
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| workflow_id, | ||
| ref: 'main', |
There was a problem hiding this comment.
warning — Dispatches use ref: 'main', so the workflow definition run is whatever is on main, not the released tag; if a release is cut from a branch other than main this dispatches stale workflow logic. Intentional but worth confirming.
| WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }} | ||
| run: | | ||
| if (-not $env:WINGET_TOKEN) { | ||
| Write-Error "WINGET_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR." |
There was a problem hiding this comment.
warning — Write-Error does not stop the script or set a nonzero exit by default, so a missing WINGET_TOKEN falls through to the wingetcreate call which then fails less clearly; add exit 1 / throw or set $ErrorActionPreference = 'Stop'.
| --token $env:WINGET_TOKEN | ||
|
|
||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Error "wingetcreate failed with exit code $LASTEXITCODE" |
There was a problem hiding this comment.
warning — Same issue: Write-Error here won't necessarily fail the step since the preceding non-terminating error doesn't stop execution; use throw or set $ErrorActionPreference='Stop' to ensure a failed wingetcreate fails the job.
| } | ||
| }, | ||
| "hash": { | ||
| "url": "\$url.sha256" |
There was a problem hiding this comment.
warning — The autoupdate hash.url is $url.sha256, but the $url includes the #/sigit.exe rename fragment; verify Scoop strips the fragment before appending .sha256 (it should, but the released sidecar is sigit-win-amd64.exe.sha256 while $url base is sigit-win-amd64.exe — matches only if fragment is dropped).
| # PKG_ARCH and PKG_VERSION are set by release-github.yml; PKG_BINARY points at | ||
| # the renamed binary already staged in release/. | ||
| name: sigit | ||
| arch: ${PKG_ARCH} |
There was a problem hiding this comment.
critical — nfpm does not expand ${PKG_ARCH}/${PKG_VERSION} from environment by default; it requires --var or the env prefix. Confirm the nfpm version used performs env-var substitution in the config, otherwise arch/version/src come out literally as ${PKG_ARCH}.
| | tar -xz -C /tmp nfpm | ||
|
|
||
| export PKG_VERSION="${RELEASE_VERSION}" | ||
| export PKG_BINARY="./release/${PROJECT_NAME}-${{ matrix.name }}" |
There was a problem hiding this comment.
warning — PKG_BINARY references ${{ matrix.name }} but the checksum step and upload later glob release/*; ensure the staged binary name (${PROJECT_NAME}-${matrix.name}) matches the sigit-linux-amd64/sigit-linux-arm64 names the AUR/Scoop workflows download, or the sidecars won't be found.
ccfaae9 to
7a778c7
Compare
There was a problem hiding this comment.
Adds four OS package-manager release channels (winget, Scoop, AUR, deb/rpm). release-github.yml now writes .sha256 sidecars for every asset, builds .deb/.rpm with nfpm from the staged binary, and fans out dispatch to the packaging workflows (failures downgraded to warnings). New workflows release-aur.yml, release-scoop.yml, release-winget.yml read checksums off the release. packaging/aur/PKGBUILD.in and packaging/nfpm.yaml hold the templates. Review the checksum-reading logic for asset-name mismatches, and the AUR PKGBUILD's use of release-provided SHAs vs. the workflow's own reads.
Automated review by siGit Code · commit 7a778c7
| - name: Checksum release assets | ||
| shell: bash | ||
| run: | | ||
| cd release |
There was a problem hiding this comment.
warning — The checksum step iterates release/ including the freshly built .deb/.rpm, but on the Windows/macOS matrix legs those files won't exist; harmless, though note the AUR/Scoop workflows depend on specific asset names (sigit-linux-amd64 etc.) which must match the staged binary names from matrix.name — verify those line up.
| --pattern "sigit-linux-*.sha256" \ | ||
| --dir artifacts/ | ||
|
|
||
| X86_64_SHA=$(cat artifacts/sigit-linux-amd64.sha256) |
There was a problem hiding this comment.
warning — The SHA read here comes from the .sha256 of the release asset, but the PKGBUILD's source_x86_64 downloads sigit-linux-amd64 (a different URL/file than what winget/scoop reference). Confirm the released asset is literally named sigit-linux-amd64 (no arch suffix mismatch) so the checksum matches what makepkg fetches.
| WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }} | ||
| run: | | ||
| if (-not $env:WINGET_TOKEN) { | ||
| Write-Error "WINGET_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR." |
There was a problem hiding this comment.
warning — Write-Error does not stop the script or set a nonzero exit by default, so a missing WINGET_TOKEN will fall through to wingetcreate which then fails less clearly; add exit 1 (or -ErrorAction Stop / throw) to fail fast.
|
|
||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Error "wingetcreate failed with exit code $LASTEXITCODE" | ||
| } |
There was a problem hiding this comment.
warning — Same issue: Write-Error "wingetcreate failed..." won't fail the job since PowerShell's error action default is Continue; the step can report success despite a nonzero $LASTEXITCODE. Add exit 1 after.
| } | ||
| }, | ||
| "hash": { | ||
| "url": "\$url.sha256" |
There was a problem hiding this comment.
nit — The autoupdate hash.url uses $url.sha256, which resolves to the URL with the #/sigit.exe rename fragment appended before .sha256, producing ...sigit-win-amd64.exe#/sigit.exe.sha256. Verify Scoop strips the fragment before fetching the checksum, otherwise autoupdate hash resolution will 404.
| | tar -xz -C /tmp nfpm | ||
|
|
||
| export PKG_VERSION="${RELEASE_VERSION}" | ||
| export PKG_BINARY="./release/${PROJECT_NAME}-${{ matrix.name }}" |
There was a problem hiding this comment.
warning — PKG_BINARY points at ./release/${PROJECT_NAME}-${{ matrix.name }}, but nfpm runs with cwd unspecified; ensure this step's working directory contains release/, LICENSE, and README.md (referenced as ./LICENSE in nfpm.yaml) or the package build fails to find them.
Covers the OS package managers sigit had no presence in. Windows users get winget and Scoop, Arch users get sigit-bin from the AUR, and Debian and Fedora users get a .deb and .rpm attached to each GitHub release. All four of the new channels read checksums off the GitHub release, so release-github.yml now writes a .sha256 next to every asset rather than only the macOS Homebrew tarball, and dispatches the packaging workflows once the release exists. A dispatch that fails is a warning, not a failed release, so a channel nobody has configured yet cannot block the others. The .deb and .rpm are built with nfpm from the binary the matrix already produced, so each Linux target still compiles once. One config covers both formats. AUR publishes sigit-bin rather than a source package. Building sigit from source pulls in the whole on-device inference stack, which is a lot to ask of someone installing a CLI. Scoop and the AUR follow the existing Homebrew tap shape: generate the manifest, push it to a sibling repo. winget is different because its manifests live in microsoft/winget-pkgs, so that workflow submits a PR through wingetcreate and only handles updates. The first submission has to be made by hand, since wingetcreate cannot update a package that does not exist yet. Still needs credentials before any of it publishes: a getsigit/scoop-bucket repo with SCOOP_BUCKET_TOKEN, WINGET_TOKEN, and the three AUR_* secrets.
7a778c7 to
c75bf63
Compare
There was a problem hiding this comment.
Adds four new OS-level distribution channels: winget, Scoop, AUR (sigit-bin), and .deb/.rpm via nfpm. release-github.yml is extended to (1) build .deb and .rpm from already-compiled Linux binaries, (2) generate .sha256 sidecars for every release asset (not just the macOS tarball), and (3) fan-out workflow dispatches to the new packaging workflows once the release exists. Dispatch failures are demoted to warnings so an unconfigured channel can't block others. The AUR and Scoop workflows pull checksums from the release, render templates, and push to external repos; the winget workflow runs wingetcreate update on Windows. Key things to verify: nfpm arch detection, winget error handling, Scoop heredoc indentation, and the AUR placeholder-detection regex.
Automated review by siGit Code Review · commit c75bf63
| shell: bash | ||
| run: | | ||
| cd release | ||
| for asset in *; do |
There was a problem hiding this comment.
warning — The glob for asset in * will also match directories if any exist under release/. Consider for asset in *; do [ -f "$asset" ] || continue; … to avoid computing a checksum for a directory entry and producing a nonsensical .sha256 file.
| export PKG_VERSION="${RELEASE_VERSION}" | ||
| export PKG_BINARY="./release/${PROJECT_NAME}-${{ matrix.name }}" | ||
|
|
||
| /tmp/nfpm package --config packaging/nfpm.yaml --packager deb --target ./release/ |
There was a problem hiding this comment.
warning — nfpm package --target ./release/ lets nfpm choose the output filename, but the earlier step already placed a raw binary there named sigit-linux-amd64. nfpm will produce something like sigit_1.5.2_amd64.deb; the subsequent checksum loop will hash it correctly, but the AUR workflow later downloads sigit-linux-amd64.sha256 (the raw binary's sidecar), not the .deb's. This is intentional, but the .deb and .rpm files will also get .sha256 sidecars whose names are whatever nfpm chose—make sure downstream consumers (README, release notes) reference the correct filenames.
| env: | ||
| WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }} | ||
| run: | | ||
| if (-not $env:WINGET_TOKEN) { |
There was a problem hiding this comment.
critical — Write-Error sets $? to false but does not terminate the script; execution continues and wingetcreate update is called with an empty --token value, which will fail with a confusing API error. Use throw or exit 1 after the Write-Error.
| # The `#/sigit.exe` URL fragment is Scoop's rename-on-download | ||
| # syntax: the release asset is sigit-win-amd64.exe, but the shim has | ||
| # to end up as sigit.exe for `sigit` to work on PATH. | ||
| cat > scoop-bucket/bucket/sigit.json <<MANIFEST |
There was a problem hiding this comment.
warning — The heredoc body is indented with spaces to match the YAML, so the generated JSON will have leading spaces on every line. jq empty will still accept it, but some Scoop clients are sensitive to non-canonical formatting; pipe through jq . before writing, or use a packaging/scoop/sigit.json.in template the way the AUR workflow does.
| -e "s/@SHA256_AARCH64@/${{ steps.sha.outputs.aarch64 }}/g" \ | ||
| packaging/aur/PKGBUILD.in > aur-build/PKGBUILD | ||
|
|
||
| if grep -q '@[A-Z0-9_]*@' aur-build/PKGBUILD; then |
There was a problem hiding this comment.
nit — The placeholder-detection regex @[A-Z0-9_]*@ won't catch a placeholder that was partially substituted and left something like @sha256_X86_64@ (wrong case). The PKGBUILD template uses uppercase, which matches, but if the template ever gains a mixed-case placeholder this guard silently passes. A broader pattern like @[A-Za-z0-9_]*@ would be safer.
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v6 | ||
| with: |
There was a problem hiding this comment.
nit — actions/checkout@v6 does not exist yet (latest stable is v4); this will fail at runtime when the action is resolved. Use actions/checkout@v4.
| echo "ARM64 SHA256: ${ARM64_SHA}" | ||
|
|
||
| - name: Checkout Scoop bucket | ||
| uses: actions/checkout@v6 |
There was a problem hiding this comment.
nit — Same issue: actions/checkout@v6 should be actions/checkout@v4.
…:getsigit/sigit into feature/winget-scoop-aur-deb-rpm-channels
|
siGit Code review is paused because the linked siGit account has reached its monthly cloud allowance. |
Covers the OS package managers sigit had no presence in. Windows users get winget and Scoop, Arch users get sigit-bin from the AUR, and Debian and Fedora users get a .deb and .rpm attached to each GitHub release.
All four of the new channels read checksums off the GitHub release, so release-github.yml now writes a .sha256 next to every asset rather than only the macOS Homebrew tarball, and dispatches the packaging workflows once the release exists. A dispatch that fails is a warning, not a failed release, so a channel nobody has configured yet cannot block the others.
The .deb and .rpm are built with nfpm from the binary the matrix already produced, so each Linux target still compiles once. One config covers both formats.
AUR publishes sigit-bin rather than a source package. Building sigit from source pulls in the whole on-device inference stack, which is a lot to ask of someone installing a CLI.
Scoop and the AUR follow the existing Homebrew tap shape: generate the manifest, push it to a sibling repo. winget is different because its manifests live in microsoft/winget-pkgs, so that workflow submits a PR through wingetcreate and only handles updates. The first submission has to be made by hand, since wingetcreate cannot update a package that does not exist yet.
Still needs credentials before any of it publishes: a getsigit/scoop-bucket repo with SCOOP_BUCKET_TOKEN, WINGET_TOKEN, and the three AUR_* secrets.