@sigitcode-old / sigit / commits / 9eacfd4
Fork 1

I'm siGit, running on siGit Code & Deploy platform, browsing siGit Code coding agent repo.

Move the npm, PyPI and NuGet wrappers under packaging/

Each distribution channel now has its own directory under packaging/, next to aur/, winget/, windows/ and assurance-runner/, and nfpm.yaml moves into packaging/linux/ with the rest of the Linux build. The repo root is left with crates/, docs/ and examples/. The issue suggested dist/. packaging/ already existed, and dist/ is where maturin and dotnet pack write their output and what the stock Node and Python .gitignore templates ignore, so it would look like build output. Paths updated in the release workflows, pyproject's manifest-path, AGENTS.md and the release skill. The render scripts and csproj only use paths relative to their own directory, so they move as they are. Closes #251 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

foodandtravel committed Oct 29, 2026 at 21:58 UTC 9eacfd42916bac7e62ed7f82656e51ffb47d1c1b
24 files changed +42 -37
.agents/AGENTS.md
+9 -4
@@ -545,8 +545,13 @@ mutating tools; the escape hatch for clients without permission-request support)
545 Version lives in `[workspace.package]` in the root `Cargo.toml`. Update `CHANGELOG.md` for releases.
546
547 Publishing splits into two groups. **Language registries** each get their own tag-triggered
548 -workflow: `release-crates`, `release-npm`, `release-nuget`, `release-pypi`. The `npm/`, `nuget/`,
549 -and `pypi/` dirs hold their wrapper-package templates.
548 +workflow: `release-crates`, `release-npm`, `release-nuget`, `release-pypi`. Everything that isn't
549 +the Rust crates themselves lives under `packaging/`, one directory per channel: `npm/`, `nuget/`
550 +and `pypi/` hold the wrapper packages, `aur/` and `winget/` the manifest templates, `linux/` the
551 +manylinux build, glibc check and nfpm config, `windows/` the static-CRT check, and
552 +`assurance-runner/` the Code Assurance image. It's `packaging/` and not `dist/` because `dist/` is
553 +build output almost everywhere (maturin's and `dotnet pack`'s `--out dist`, and the stock Node and
554 +Python `.gitignore` templates) and would read as something safe to delete.
555
556 npm and NuGet authenticate with OIDC (Trusted Publishing), so neither needs a stored token. On
557 npm that is configured per package, not per org: all seven `@getsigit/*` names carry a trusted
@@ -593,7 +598,7 @@ actions' Node needs glibc 2.28, which CentOS 7 lacks).
598 Every release asset now carries a `.sha256` sidecar, not just the macOS Homebrew tarball. Scoop,
599 winget, and the AUR PKGBUILD each need one, and they consume the raw binaries rather than the
600 tarball. `release-github` also builds a `.deb` and `.rpm` per Linux target with nfpm
596 -(`packaging/nfpm.yaml`), packaging the already-built binary rather than re-invoking cargo.
601 +(`packaging/linux/nfpm.yaml`), packaging the already-built binary rather than re-invoking cargo.
602
603 Re-pushing a tag fires every release workflow a second time, so each one is grouped by tag in a
604 `concurrency` block with `cancel-in-progress: false` — the duplicate queues behind the original
@@ -635,7 +640,7 @@ just a nicety. See the NuGet note below.
640
641 The NuGet package (`SiGit.Code`, installed with `dotnet tool install --global SiGit.Code`) is the
642 odd one out among the language registries: npm and PyPI publish one artifact per platform, but a
638 -.NET tool is a single package, so `nuget/sigit/` bundles all six binaries under
643 +.NET tool is a single package, so `packaging/nuget/sigit/` bundles all six binaries under
644 `native/<os>-<arch>/` and a small managed shim (`Program.cs`) execs the right one. That shim leaves
645 stdin/stdout/stderr unredirected on purpose, since siGit Code chooses TUI or ACP mode by testing
646 whether stdin is a TTY. It also sets `RollForward=Major`: it targets `net8.0`, and without that a
.agents/skills/sigit-code-release/SKILL.md
+13 -13
@@ -27,13 +27,13 @@ Use this skill when preparing a release for this repository.
27 - Bump `[workspace.package].version` in the root `Cargo.toml`; every workspace crate inherits it.
28 - Update the root `sigit` package entry in `Cargo.lock` when the crate version changes.
29 - Add or update the top changelog entry in `CHANGELOG.md` for the release being cut.
30 -- Do not treat `npm/sigit/package.json` `0.0.0-dev` as a bug by default. The npm release workflow rewrites it at publish time using `npm/scripts/render-main-package.cjs` and the release tag.
30 +- Do not treat `packaging/npm/sigit/package.json` `0.0.0-dev` as a bug by default. The npm release workflow rewrites it at publish time using `packaging/npm/scripts/render-main-package.cjs` and the release tag.
31 - Every npm package publishes twice, under `@getsigit` and under `@smbcloud`. `@smbcloud` is the pre-1.5.5 name, mirrored so an install predating the rename keeps updating; `@getsigit` is canonical and is what the README, the Homebrew tap, and the ACP registry entry point at. All fourteen names (two base packages, twelve platform packages) publish over OIDC and each needs its own Trusted Publisher on npm pointing at `release-npm.yml`.
32 -- The scope is a render-time argument, not a second copy of the packaging: `render-platform-package.cjs` takes it as a fifth argument, and the base package picks it up from `package-main.json.tmpl` versus `package-compat.json.tmpl`. `npm/sigit/src/index.ts` is built once and shipped under both names — it reads its own `package.json` at runtime to decide which scope to resolve the platform binary from, and prints the migration notice only when it finds itself running as `@smbcloud/sigit`.
33 -- Do not add a hardcoded version to `pypi/pyproject.toml` for normal releases. PyPI uses `maturin` with `dynamic = ["version"]` and derives the published package version from `crates/cli/Cargo.toml`, which inherits the workspace version.
32 +- The scope is a render-time argument, not a second copy of the packaging: `render-platform-package.cjs` takes it as a fifth argument, and the base package picks it up from `package-main.json.tmpl` versus `package-compat.json.tmpl`. `packaging/npm/sigit/src/index.ts` is built once and shipped under both names — it reads its own `package.json` at runtime to decide which scope to resolve the platform binary from, and prints the migration notice only when it finds itself running as `@smbcloud/sigit`.
33 +- Do not add a hardcoded version to `packaging/pypi/pyproject.toml` for normal releases. PyPI uses `maturin` with `dynamic = ["version"]` and derives the published package version from `crates/cli/Cargo.toml`, which inherits the workspace version.
34 - Release workflows are tag-driven. `release-github.yml`, `release-npm.yml`, `release-pypi.yml`, `release-crates.yml`, `release-homebrew.yml`, and `release-nuget.yml` all derive `RELEASE_VERSION` from a `v*.*.*` tag or a manually supplied tag input.
35 - The crate is published to crates.io (`release-crates.yml`) and the Homebrew tap is updated (`release-homebrew.yml`) as part of the tag-driven flow. Per the siGit release flow, Homebrew is auto-triggered — do not dispatch it manually.
36 -- `release-github.yml` builds the binaries, attaches them (plus a `.deb`/`.rpm` per Linux target built with nfpm from `packaging/nfpm.yaml`) to the GitHub release, then dispatches `release-homebrew`, `release-scoop`, `release-winget`, and `release-aur`. A dispatch failure in any one of those four is logged as a warning, not a hard failure — an unconfigured channel doesn't block the rest of the release. `release-nuget.yml`, by contrast, is tag-triggered directly like the other language-registry workflows, not dispatched from `release-github.yml`. `release-aur.yml` exists but its dispatch line in `release-github.yml` is commented out (`// New AUR account registration is temporarily closed`), so AUR does not update on a normal release — an absent AUR bump is expected, not a failure.
36 +- `release-github.yml` builds the binaries, attaches them (plus a `.deb`/`.rpm` per Linux target built with nfpm from `packaging/linux/nfpm.yaml`) to the GitHub release, then dispatches `release-homebrew`, `release-scoop`, `release-winget`, and `release-aur`. A dispatch failure in any one of those four is logged as a warning, not a hard failure — an unconfigured channel doesn't block the rest of the release. `release-nuget.yml`, by contrast, is tag-triggered directly like the other language-registry workflows, not dispatched from `release-github.yml`. `release-aur.yml` exists but its dispatch line in `release-github.yml` is commented out (`// New AUR account registration is temporarily closed`), so AUR does not update on a normal release — an absent AUR bump is expected, not a failure.
37 - Every release asset carries a `.sha256` sidecar (not just the macOS Homebrew tarball). Scoop, winget, and the AUR PKGBUILD each consume the raw binaries plus their sidecar checksum, rather than the tarball.
38 - The GitHub release body is generated, not hand-written: `release-github.yml`'s release job checks out the tag, awk-extracts the `## <version>` section from `CHANGELOG.md` (a missing section is a hard failure), appends a full-changelog link and a `sigit.si/code` footnote, and publishes it via `body_path: release_notes.md`. The only file a release-prep change needs to touch is `CHANGELOG.md` — never edit release notes in the GitHub UI, because the next tag push would overwrite them.
39 - npm and NuGet publish via OIDC trusted publishing — neither has a stored token in the repo. On npm this is configured per package (each `@getsigit/*` name has a trusted publisher pointing at `release-npm.yml`), so a new package needs the same setup before its first publish will work. OIDC requires npm >= 11.5.1 and Node >= 22.14.0.
@@ -95,13 +95,13 @@ flows start from different base commits and are not interchangeable.
95 - `Cargo.lock`
96 - `CHANGELOG.md`
97 - `README.md`
98 -- `npm/sigit/package.json`
99 -- `npm/package-main.json.tmpl`, `npm/package-compat.json.tmpl`, `npm/package.json.tmpl` (publish-time package metadata for both scopes)
100 -- `npm/scripts/render-main-package.cjs`
101 -- `npm/`
102 -- `pypi/`
103 -- `nuget/sigit/` (bundled-binary `.NET` tool packaging)
104 -- `packaging/` (`nfpm.yaml` for `.deb`/`.rpm`, plus `aur/` and `winget/` templates)
98 +- `packaging/npm/sigit/package.json`
99 +- `packaging/npm/package-main.json.tmpl`, `packaging/npm/package-compat.json.tmpl`, `packaging/npm/package.json.tmpl` (publish-time package metadata for both scopes)
100 +- `packaging/npm/scripts/render-main-package.cjs`
101 +- `packaging/npm/`
102 +- `packaging/pypi/`
103 +- `packaging/nuget/sigit/` (bundled-binary `.NET` tool packaging)
104 +- `packaging/linux/nfpm.yaml` (`.deb`/`.rpm`), plus the `packaging/aur/` and `packaging/winget/` templates
105 - `.github/workflows/` (`release-github.yml`, `release-npm.yml`, `release-pypi.yml`, `release-crates.yml`, `release-homebrew.yml`, `release-scoop.yml`, `release-winget.yml`, `release-aur.yml`, `release-nuget.yml`) — there is deliberately no `release-mcp-registry.yml`; the MCP Registry listing lives in `getsigit/si`
106
107 ## Release checklist
@@ -109,8 +109,8 @@ flows start from different base commits and are not interchangeable.
109 - Version bump is applied everywhere it needs to be.
110 - `Cargo.toml` and the root crate entry in `Cargo.lock` match.
111 - `CHANGELOG.md` has a correct top entry for the new release.
112 -- `npm/sigit/package.json` is left at `0.0.0-dev` unless the packaging flow itself changed.
113 -- `pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
112 +- `packaging/npm/sigit/package.json` is left at `0.0.0-dev` unless the packaging flow itself changed.
113 +- `packaging/pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
114 - Release workflows still derive their version from the tag as expected.
115 - Correct git flow for the release type followed, with `v<version>` tagged on the `main` merge commit either way:
116 - **Full release:** bump committed on `release/v<version>` (off `development`), merged back to `development`, then `development` merged into `main`.
.github/workflows/release-github.yml
+1 -1
@@ -194,7 +194,7 @@ jobs:
194 fi
195
196 envsubst '${PKG_ARCH} ${PKG_VERSION} ${PKG_BINARY}' \
197 - < packaging/nfpm.yaml > /tmp/nfpm.rendered.yaml
197 + < packaging/linux/nfpm.yaml > /tmp/nfpm.rendered.yaml
198
199 /tmp/nfpm package --config /tmp/nfpm.rendered.yaml --packager deb --target ./release/
200 /tmp/nfpm package --config /tmp/nfpm.rendered.yaml --packager rpm --target ./release/
.github/workflows/release-npm.yml
+3 -3
@@ -136,7 +136,7 @@ jobs:
136 - name: Publish platform package to NPM
137 shell: bash
138 run: |
139 - cd npm
139 + cd packaging/npm
140
141 # Binary name from Cargo.toml
142 cargo_bin="sigit"
@@ -169,7 +169,7 @@ jobs:
169 cargo_bin="${cargo_bin}.exe"
170 fi
171
172 - cp "../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
172 + cp "../../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
173
174 # One binary, published under both scopes: re-render package.json and
175 # README for each, from the same directory.
@@ -237,7 +237,7 @@ jobs:
237 - name: Publish base packages to NPM
238 shell: bash
239 run: |
240 - cd npm/sigit
240 + cd packaging/npm/sigit
241
242 npm_package_version="${{ env.RELEASE_VERSION }}"
243
.github/workflows/release-nuget.yml
+11 -11
@@ -148,7 +148,7 @@ jobs:
148 uses: actions/download-artifact@v4
149 with:
150 pattern: nuget-native-*
151 - path: nuget/sigit/native
151 + path: packaging/nuget/sigit/native
152 merge-multiple: true
153
154 - name: Setup .NET SDK
@@ -159,9 +159,9 @@ jobs:
159 - name: Pack .NET tool
160 shell: bash
161 run: |
162 - dotnet pack nuget/sigit/SiGit.Code.csproj \
162 + dotnet pack packaging/nuget/sigit/SiGit.Code.csproj \
163 --configuration Release \
164 - --output nuget/dist \
164 + --output packaging/nuget/dist \
165 -p:PackageVersion=${RELEASE_VERSION}
166
167 # All six binaries ship in one package, so this sits closer to nuget.org's
@@ -171,7 +171,7 @@ jobs:
171 - name: Check package size against the NuGet limit
172 shell: bash
173 run: |
174 - package="$(ls nuget/dist/*.nupkg | head -n 1)"
174 + package="$(ls packaging/nuget/dist/*.nupkg | head -n 1)"
175 size_bytes="$(wc -c < "${package}")"
176 limit_bytes=$((250 * 1024 * 1024))
177
@@ -187,7 +187,7 @@ jobs:
187 uses: actions/upload-artifact@v4
188 with:
189 name: nuget-package
190 - path: nuget/dist/*.nupkg
190 + path: packaging/nuget/dist/*.nupkg
191
192 smoke-test:
193 name: Smoke test (${{ matrix.os }})
@@ -221,7 +221,7 @@ jobs:
221 uses: actions/download-artifact@v4
222 with:
223 name: nuget-package
224 - path: nuget/dist
224 + path: packaging/nuget/dist
225
226 - name: Setup .NET SDK
227 uses: actions/setup-dotnet@v4
@@ -231,7 +231,7 @@ jobs:
231 - name: Install tool from local package
232 shell: pwsh
233 run: |
234 - $packageSource = (Resolve-Path "nuget/dist").Path
234 + $packageSource = (Resolve-Path "packaging/nuget/dist").Path
235 @"
236 <?xml version="1.0" encoding="utf-8"?>
237 <configuration>
@@ -240,11 +240,11 @@ jobs:
240 <add key="local" value="$packageSource" />
241 </packageSources>
242 </configuration>
243 - "@ | Set-Content -Path "nuget/NuGet.Config"
243 + "@ | Set-Content -Path "packaging/nuget/NuGet.Config"
244
245 dotnet tool install `
246 --tool-path ".tool" `
247 - --configfile "nuget/NuGet.Config" `
247 + --configfile "packaging/nuget/NuGet.Config" `
248 --version "$env:RELEASE_VERSION" `
249 "$env:NUGET_PACKAGE_ID"
250
@@ -297,7 +297,7 @@ jobs:
297 uses: actions/download-artifact@v4
298 with:
299 name: nuget-package
300 - path: nuget/dist
300 + path: packaging/nuget/dist
301
302 - name: Setup .NET SDK
303 uses: actions/setup-dotnet@v4
@@ -353,7 +353,7 @@ jobs:
353 if: steps.nuget-check.outputs.exists != 'true'
354 shell: bash
355 run: |
356 - dotnet nuget push nuget/dist/*.nupkg \
356 + dotnet nuget push packaging/nuget/dist/*.nupkg \
357 --api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}" \
358 --source https://api.nuget.org/v3/index.json \
359 --skip-duplicate
.github/workflows/release-pypi.yml
+4 -4
@@ -100,7 +100,7 @@ jobs:
100 with:
101 target: ${{ matrix.build.TARGET }}
102 manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
103 - working-directory: pypi
103 + working-directory: packaging/pypi
104 args: --release --locked --compatibility pypi --out dist
105 before-script-linux: yum install -y perl-core
106
@@ -108,7 +108,7 @@ jobs:
108 uses: actions/upload-artifact@v4
109 with:
110 name: wheels-${{ matrix.build.NAME }}
111 - path: pypi/dist/*
111 + path: packaging/pypi/dist/*
112
113 build-sdist:
114 name: Build source distribution
@@ -138,14 +138,14 @@ jobs:
138 uses: PyO3/maturin-action@v1
139 with:
140 command: sdist
141 - working-directory: pypi
141 + working-directory: packaging/pypi
142 args: --out dist
143
144 - name: Upload sdist artifact
145 uses: actions/upload-artifact@v4
146 with:
147 name: sdist
148 - path: pypi/dist/*
148 + path: packaging/pypi/dist/*
149
150 publish-pypi:
151 name: Publish to PyPI
packaging/linux/nfpm.yaml renamed
packaging/npm/README.md.tmpl renamed
packaging/npm/package-compat.json.tmpl renamed
packaging/npm/package-main.json.tmpl renamed
packaging/npm/package.json.tmpl renamed
packaging/npm/scripts/render-main-package.cjs renamed
packaging/npm/scripts/render-platform-package.cjs renamed
packaging/npm/sigit/.gitignore renamed
packaging/npm/sigit/README.md renamed
packaging/npm/sigit/package.json renamed
packaging/npm/sigit/src/index.ts renamed
packaging/npm/sigit/tsconfig.json renamed
packaging/nuget/.gitignore renamed
packaging/nuget/sigit/Program.cs renamed
packaging/nuget/sigit/README.md renamed
packaging/nuget/sigit/SiGit.Code.csproj renamed
packaging/pypi/README.md renamed
packaging/pypi/pyproject.toml renamed
+1 -1
@@ -37,6 +37,6 @@ Repository = "https://github.com/getsigit/sigit"
37 Issues = "https://github.com/getsigit/sigit/issues"
38
39 [tool.maturin]
40 -manifest-path = "../crates/cli/Cargo.toml"
40 +manifest-path = "../../crates/cli/Cargo.toml"
41 bindings = "bin"
42 strip = true