diff --git a/.github/workflows/release-sce-linux-arm.yml b/.github/workflows/release-sce-linux-arm.yml index 5665ab6a..f94229e8 100644 --- a/.github/workflows/release-sce-linux-arm.yml +++ b/.github/workflows/release-sce-linux-arm.yml @@ -36,6 +36,20 @@ jobs: --version "${{ inputs.release_version }}" \ --out-dir dist + - name: Build Flatpak bundle release assets (aarch64) + run: | + nix run .#release-flatpak-bundle -- \ + --version "${{ inputs.release_version }}" \ + --arch aarch64 \ + --out-dir dist/flatpak-bundle + + - name: Upload Flatpak bundle release assets (aarch64) + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sce-flatpak-bundle-aarch64 + path: dist/flatpak-bundle/ + if-no-files-found: error + - name: Upload Linux ARM CLI release artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/.github/workflows/release-sce-linux.yml b/.github/workflows/release-sce-linux.yml index 736df9d1..2eef993f 100644 --- a/.github/workflows/release-sce-linux.yml +++ b/.github/workflows/release-sce-linux.yml @@ -36,6 +36,20 @@ jobs: --version "${{ inputs.release_version }}" \ --out-dir dist + - name: Build Flatpak bundle release assets (x86_64) + run: | + nix run .#release-flatpak-bundle -- \ + --version "${{ inputs.release_version }}" \ + --arch x86_64 \ + --out-dir dist/flatpak-bundle + + - name: Upload Flatpak bundle release assets (x86_64) + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sce-flatpak-bundle-x86_64 + path: dist/flatpak-bundle/ + if-no-files-found: error + - name: Upload Linux CLI release artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/.github/workflows/release-sce.yml b/.github/workflows/release-sce.yml index 8919b7d7..6e319e8a 100644 --- a/.github/workflows/release-sce.yml +++ b/.github/workflows/release-sce.yml @@ -204,6 +204,19 @@ jobs: --version "${{ needs.resolve-release.outputs.version }}" \ --out-dir dist/npm + - name: Build Flatpak source-manifest release package + run: | + nix run .#release-flatpak-package -- \ + --version "${{ needs.resolve-release.outputs.version }}" \ + --out-dir dist/flatpak + + - name: Download Flatpak bundle release assets + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: sce-flatpak-bundle-* + path: dist/flatpak-bundle + merge-multiple: true + - name: Create GitHub release uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 with: @@ -219,6 +232,8 @@ jobs: - Combined artifact manifest signatures are published as `sce-v-release-manifest.json.sig` - Combined checksums are published as `sce-v-SHA256SUMS` - The npm package tarball is published as `sce-v-npm.tgz` + - Flatpak source-built packaging metadata is published as `sce-v-flatpak-manifest.tar.gz`, with matching `.sha256` and `.json` metadata assets; this is not a prebuilt Flatpak app or Flathub publication. + - Flatpak source-built `.flatpak` bundles are published as `sce-v-x86_64.flatpak` and `sce-v-aarch64.flatpak`, with matching `.sha256` and `.json` metadata assets; install directly with `flatpak install --user `. files: | dist/cli/*.tar.gz dist/cli/*.sha256 @@ -227,3 +242,9 @@ jobs: dist/cli/*SHA256SUMS dist/npm/*.tgz dist/npm/*.json + dist/flatpak/*.tar.gz + dist/flatpak/*.sha256 + dist/flatpak/*.json + dist/flatpak-bundle/*.flatpak + dist/flatpak-bundle/*.sha256 + dist/flatpak-bundle/*.json diff --git a/README.md b/README.md index 4a156fd9..8945c070 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,12 @@ The `sce` CLI is also available as a **source-built** Flatpak package (`dev.croc for Linux. The Flatpak builds `sce` from source inside the Flatpak sandbox using the Freedesktop SDK Rust extension — it does not wrap a prebuilt Nix, Cargo, or npm binary. -> **First iteration scope:** Flathub-ready manifest, Nix-backed local build/check tooling, -> and documentation. No CI publishing, automatic Flathub submission, GitHub Release Flatpak -> assets, or release-version bumping. +> **Release scope:** GitHub Releases now include both Flatpak source-manifest +> assets (packaging metadata for source builds) and source-built `.flatpak` bundle +> assets (pre-built Flatpak apps for direct install). The bundles are built from +> Rust source inside Flatpak — they are not prebuilt binaries, Nix packages, or +> Flathub submissions. Automatic Flathub publication and release-version bumping +> remain out of scope. #### Prerequisites @@ -104,6 +107,58 @@ The default `nix flake check` runs lightweight static validation are opt-in via `nix run .#flatpak-build` and require network access for SDK runtime downloads. +#### GitHub Release source-manifest assets + +Each `sce` GitHub Release also includes Flatpak source-manifest assets for +contributors or downstream packagers who want the release-pinned Flatpak build +inputs: + +- `sce-v-flatpak-manifest.tar.gz` +- `sce-v-flatpak-manifest.tar.gz.sha256` +- `sce-v-flatpak.json` + +The tarball contains a deterministic top-level +`sce-v-flatpak-manifest/` directory with the Flathub-style source +manifest and support files: + +- `dev.crocoder.sce.yml` +- `dev.crocoder.sce.metainfo.xml` +- `cargo-sources.json` +- `git-host-bridge` + +The packaged manifest pins its git source to the release commit without +mutating the checked-in manifest. The checksum and JSON metadata describe the +source-manifest package; they are separate from the signed native release +manifest consumed by npm and do not contain a prebuilt `sce` binary. + +Maintainers can build the same asset set locally from a checked-out release +commit: + +```bash +nix run .#release-flatpak-package -- \ + --version "$(tr -d '\n' < .version)" \ + --out-dir dist/flatpak +``` + +#### GitHub Release bundle assets + +Each `sce` GitHub Release also includes source-built `.flatpak` bundles for +direct installation without cloning the repository or building from source: + +- `sce-v-x86_64.flatpak` + `.sha256` + `.json` +- `sce-v-aarch64.flatpak` + `.sha256` + `.json` + +Install directly from the release URL: + +```bash +flatpak install --user \ + https://github.com/crocoder-dev/shared-context-engineering/releases/download/v/sce-v-x86_64.flatpak +``` + +These bundles are **source-built** — the Flatpak builds `sce` from Rust source +inside the Flatpak sandbox, not from a prebuilt Nix, Cargo, or npm binary. +They are not Flathub submissions and are published only as GitHub Release assets. + #### Direct flatpak-builder fallback If you do not use Nix, you can use `sce-flatpak.sh` and `flatpak-builder` directly: diff --git a/context/architecture.md b/context/architecture.md index b8248c63..f653b6e7 100644 --- a/context/architecture.md +++ b/context/architecture.md @@ -78,17 +78,19 @@ The repository includes a new placeholder Rust binary crate at `cli/`. ## CLI install/distribution boundary - The current implemented binary install/distribution surface for the `sce` CLI includes repo-flake Nix, Cargo, and npm; `Homebrew` is deferred from the active implementation stage. -- Flatpak is also an official supported distribution channel for this implementation stage under application ID `dev.crocoder.sce`, with a source-built Flatpak package rather than a wrapper around Nix-built, GitHub Release, npm native, or other prebuilt `sce` artifacts. +- Flatpak is also an official supported distribution channel for this implementation stage under application ID `dev.crocoder.sce`, with a source-built Flatpak package rather than a wrapper around Nix-built, native GitHub Release binary, npm native, or other prebuilt `sce` artifacts. - Nix-managed build/release entrypoints are the source of truth for existing binary build outputs and release automation, and Nix may orchestrate Flatpak tooling, local-source overrides, and validation without becoming the Flatpak package's binary source. - The implemented Flatpak packaging/tooling surface lives under `packaging/flatpak/`: `dev.crocoder.sce.yml` is the Flathub-style source-build manifest, `cargo-sources.json` is generated from `cli/Cargo.lock` for offline Cargo sources, `dev.crocoder.sce.metainfo.xml` is the AppStream console-app metadata, `git-host-bridge` is installed as `/app/bin/git` to delegate runtime Git access to `flatpak-spawn --host git` with the required `org.freedesktop.Flatpak` permission, and `sce-flatpak.sh` generates local checkout-source manifests plus validation/build orchestration for the flake apps/check. -- Flatpak CI publishing, automatic Flathub submission, GitHub Release Flatpak assets, and release-version bumping are outside the current iteration. +- GitHub Release Flatpak source-manifest assets are implemented for the active release model as packaging metadata only: `nix run .#release-flatpak-package -- --version --out-dir ` packages `sce-v-flatpak-manifest.tar.gz`, its `.sha256`, and `sce-v-flatpak.json` from the Flatpak manifest/support files with the staged manifest pinned to the release commit. +- Flatpak GitHub Release assets now also include source-built `.flatpak` bundle assets (`sce-v-x86_64.flatpak` / `sce-v-aarch64.flatpak` plus `.sha256` / `.json`) alongside source-manifest packaging metadata. +- Automatic Flathub submission, prebuilt (non-source-built) Flatpak binaries/bundles, OSTree repositories, release-version bumping, and Flatpak publication beyond the approved GitHub Release asset upload remain outside the current iteration. - The root flake now also owns an opt-in install-channel integration-test app surface, `apps.install-channel-integration-tests`, which provides the execution contract for npm/Bun/Cargo install verification without enrolling that heavier coverage in default `checks.`. - Repo-root `.version` is the canonical checked-in release version authority across GitHub Releases, Cargo publication, and npm publication. -- GitHub Releases are the canonical publication surface for release archives, checksums, and release-manifest assets. +- GitHub Releases are the canonical publication surface for release archives, checksums, release-manifest assets, npm package assets, and approved Flatpak source-manifest and bundle assets. - Cargo/crates.io and npm registry publication belong to separate downstream publish stages that consume already-versioned checked-in package metadata rather than inventing release versions during workflow execution. - npm is a downstream consumer of the shared release artifact contract rather than a separate build owner. -- `flake.nix` now exposes dedicated release-packaging apps for this rollout: `apps.release-artifacts` packages the current-platform `sce` archive/checksum/manifest-fragment set from `packages.default` and fails if `.version`, `cli/Cargo.toml`, `npm/package.json`, or the built CLI version disagree; `apps.release-manifest` merges per-platform metadata fragments into release-level manifest/checksum outputs and signs the merged manifest with a non-repo private key provided via env/file input; and `apps.release-npm-package` packs the checked-in npm launcher package into a release-ready `sce-v-npm.tgz` tarball plus npm metadata JSON while refusing mismatched checked-in version metadata. -- CLI release automation: `.github/workflows/release-sce.yml` orchestrates `sce` GitHub release asset assembly, validates `.version`/Cargo/npm parity before tagging or releasing, and now calls three reusable per-platform workflow files (`release-sce-linux.yml`, `release-sce-linux-arm.yml`, `release-sce-macos-arm.yml`) before assembling the release manifest and publishing GitHub release assets. +- `flake.nix` now exposes dedicated release-packaging apps for this rollout: `apps.release-artifacts` packages the current-platform `sce` archive/checksum/manifest-fragment set from `packages.default` and fails if `.version`, `cli/Cargo.toml`, `npm/package.json`, or the built CLI version disagree; `apps.release-manifest` merges per-platform metadata fragments into release-level manifest/checksum outputs and signs the merged manifest with a non-repo private key provided via env/file input; `apps.release-npm-package` packs the checked-in npm launcher package into a release-ready `sce-v-npm.tgz` tarball plus npm metadata JSON while refusing mismatched checked-in version metadata; and Linux-only `apps.release-flatpak-package` emits the Flatpak source-manifest tarball/checksum/JSON metadata while refusing `.version`/Cargo/npm/AppStream version drift and non-git checkouts that cannot resolve a release commit; Linux-only `apps.release-flatpak-bundle` builds a source-built `.flatpak` bundle from the checkout and emits per-architecture bundle/checksum/JSON metadata. +- CLI release automation: `.github/workflows/release-sce.yml` orchestrates `sce` GitHub release asset assembly, validates `.version`/Cargo/npm parity before tagging or releasing, calls three reusable per-platform workflow files (`release-sce-linux.yml`, `release-sce-linux-arm.yml`, `release-sce-macos-arm.yml`), assembles the signed native release manifest, builds npm and Flatpak source-manifest release packages, and uploads the CLI/npm/Flatpak asset set to the GitHub Release. - Downstream registry publication is now implemented in dedicated workflows: `.github/workflows/publish-crates.yml` publishes the checked-in crate version from a published release or manual dispatch after `.version`/tag/Cargo parity checks, and `.github/workflows/publish-npm.yml` publishes the checked-in npm package version from a published release or manual dispatch after `.version`/tag/npm parity checks plus verification of the canonical `sce-v-npm.tgz` GitHub release asset. - The npm distribution implementation lives under `npm/`: `package.json` defines the `sce` package surface, `bin/sce.js` launches the package-local native binary, `lib/install.js` resolves the current package version against the release manifest, verifies `sce-v-release-manifest.json.sig` with the bundled public key before trusting manifest contents, and then installs the checksum-verified native archive for supported macOS/Linux targets, while `test/platform.test.js` and `test/install.test.js` cover platform selection plus signed-manifest installer behavior. @@ -133,7 +135,7 @@ The repository includes a new placeholder Rust binary crate at `cli/`. - `cli/README.md` is the crate-local onboarding and usage source of truth for placeholder behavior, safety limitations, and roadmap mapping back to service contracts. - `flake.nix` applies `rust-overlay` (`oxalica/rust-overlay`) to nixpkgs, pins `rust-bin.stable.1.95.0.default` with `rustfmt` + `clippy`, reads the package/check version from repo-root `.version`, builds `packages.sce` through Crane (`buildDepsOnly` -> `buildPackage`) with a filtered repo-root source that preserves the Cargo tree plus `cli/assets/hooks`, then injects generated OpenCode/Claude config payloads and schema inputs into a temporary `cli/assets/generated/` mirror during derivation unpack so `cli/build.rs` can package the crate without requiring committed generated crate assets. The same `cli/build.rs` now scans `cli/migrations/*/*.sql` and writes `cli/src/generated_migrations.rs` with deterministic migration constants sorted by numeric filename prefix. - The root flake runs `cli-tests`, `cli-clippy`, and `cli-fmt` plus the dedicated `integrations-install-tests`, `integrations-install-clippy`, and `integrations-install-fmt` derivations through Crane-backed paths so both Rust crates have first-class default-flake verification; it also exposes directory-scoped JS validation derivations for both `npm/` and the shared `config/lib/` plugin package root. -- Flatpak flake tooling is Linux-only: `apps.flatpak-validate` runs `packaging/flatpak/sce-flatpak.sh validate`, `apps.flatpak-local-manifest` emits a generated checkout-source manifest, `apps.flatpak-build` runs opt-in `flatpak-builder` builds from that generated local manifest, `checks..flatpak-static-validation` performs lightweight static/AppStream validation without a full build, and the Linux dev shell includes `appstreamcli`, `flatpak`, and `flatpak-builder`. +- Flatpak flake tooling is Linux-only: `apps.flatpak-validate` runs `packaging/flatpak/sce-flatpak.sh validate`, `apps.flatpak-local-manifest` emits a generated checkout-source manifest, `apps.flatpak-build` runs opt-in `flatpak-builder` builds from that generated local manifest, `apps.release-flatpak-package` emits deterministic Flatpak GitHub Release source-manifest assets, `apps.release-flatpak-bundle` builds a source-built `.flatpak` bundle, `checks..flatpak-static-validation` performs lightweight static/AppStream validation without a full build, and the Linux dev shell includes `appstreamcli`, `flatpak`, and `flatpak-builder`. - The root flake also exposes the non-default `apps.install-channel-integration-tests` flake app for npm/Bun/Cargo install-channel integration coverage outside the default check set. The shared config-lib source set is rooted at `config/lib/` and includes the shared `package.json`, `bun.lock`, and `tsconfig.json` plus `agent-trace-plugin/` and `bash-policy-plugin/`; `config-lib-bun-tests` runs the bash-policy plugin wrapper tests from that shared root, while `config-lib-biome-check` and `config-lib-biome-format` run Biome over the copied shared package source. `.github/workflows/publish-crates.yml` follows the same asset-preparation rule but runs Cargo packaging from a temporary clean repository copy so crates.io publish no longer needs `--allow-dirty`. - The config-lib check source preserves repo-relative access to shared CLI patch fixtures: Nix copies a filtered repo-shaped source containing `config/lib/**` plus `cli/src/services/structured_patch/fixtures`, then runs Bun/Biome from `config/lib/`. - `flake.nix` exposes release install/run surfaces as `packages.sce` (`packages.default = packages.sce`) plus `apps.sce` and `apps.default`, all targeting `${packages.sce}/bin/sce`; this keeps repo-local and remote flake run/install flows (`nix run .`, `nix run github:crocoder-dev/shared-context-engineering`, `nix profile install github:crocoder-dev/shared-context-engineering`) aligned to the same packaged CLI output. diff --git a/context/context-map.md b/context/context-map.md index 58f9a7c9..40058d60 100644 --- a/context/context-map.md +++ b/context/context-map.md @@ -55,9 +55,9 @@ Feature/domain context: - `context/sce/bash-tool-policy-enforcement-contract.md` (approved bash-tool blocking contract plus current Rust evaluator seam and OpenCode/Claude delegation references, including config schema, argv-prefix matching, shell/nix unwrapping, fixed preset catalog/messages, and precedence rules) - `context/sce/generated-opencode-plugin-registration.md` (current generated OpenCode plugin-registration contract, canonical Pkl ownership, generated manifest/plugin paths including `sce-bash-policy` + `sce-agent-trace`, TypeScript source ownership, and Claude generated settings boundary including Agent Trace hooks plus `PreToolUse` Bash policy hook registration) - `context/sce/opencode-agent-trace-plugin-runtime.md` (current OpenCode agent-trace plugin runtime behavior, including captured `message.updated` handoff with `summary.diffs` branching: when diffs exist sends `-patch` variant `message.updated` + per-diff `message.part.updated` with `part_type: "patch"` concurrently via `Promise.all`, when no diffs sends original `message.updated` payload; in-memory dedup `Set` keyed by `"${sessionID}:${messageID}"`; captured `message.part.updated` handoff to `sce hooks conversation-trace` as `{ type: "message.part.updated", payloads: [{ session_id, message_id, part_type, text, generated_at_unix_ms }] }` with `text`/`reasoning` only; existing user-message diff extraction for `{ sessionID, diff, time, model_id }`; session-scoped OpenCode client version capture from `session.created`/`session.updated`; and CLI handoff to `sce hooks diff-trace` over STDIN JSON with required `tool_name="opencode"` plus required nullable `tool_version`; Rust hook parsing and AgentTraceDb insertion persist required payload fields including `model_id`) -- `context/sce/cli-first-install-channels-contract.md` (current `sce` install/distribution contract covering supported Nix/Cargo/npm plus source-built Flatpak channel scope, canonical naming, `.version` release authority for binary channels, Nix-owned build/release policy, Nix-orchestrated Flatpak local tooling through `packaging/flatpak/sce-flatpak.sh`, Linux flake apps/checks `flatpak-validate` / `flatpak-local-manifest` / `flatpak-build` / `flatpak-static-validation`, the implemented `packaging/flatpak/dev.crocoder.sce.yml` + AppStream/Cargo-source packaging surface, and the `dev.crocoder.sce` host-git bridge decision) +- `context/sce/cli-first-install-channels-contract.md` (current `sce` install/distribution contract covering supported Nix/Cargo/npm plus source-built Flatpak channel scope, implemented GitHub Release Flatpak source-manifest and source-built `.flatpak` bundle asset packaging, canonical `.version` release authority, Nix-owned build/release policy, Nix-orchestrated Flatpak local/release tooling through `packaging/flatpak/sce-flatpak.sh`, Linux flake apps/checks `flatpak-validate` / `flatpak-local-manifest` / `flatpak-build` / `release-flatpak-package` / `release-flatpak-bundle` / `flatpak-static-validation`, the implemented `packaging/flatpak/dev.crocoder.sce.yml` + AppStream/Cargo-source packaging surface, and the `dev.crocoder.sce` host-git bridge decision) - `context/sce/optional-install-channel-integration-test-entrypoint.md` (current opt-in flake app contract for existing binary install-channel integration coverage, including thin flake delegation to the Rust runner, shared harness ownership, real npm+Bun+Cargo install flows, channel selector semantics, the explicit non-default execution boundary, and the separate Flatpak source-build validation boundary) -- `context/sce/cli-release-artifact-contract.md` (shared `sce` binary release artifact naming, checksum/manifest outputs, GitHub Releases as the canonical artifact publication surface, the current three-target Linux/macOS release workflow topology, and Flatpak's explicit source-built non-artifact exception) +- `context/sce/cli-release-artifact-contract.md` (shared `sce` binary release artifact naming, checksum/manifest outputs, GitHub Releases as the canonical artifact publication surface, the current three-target Linux/macOS release workflow topology, implemented Flatpak source-manifest and source-built `.flatpak` bundle package assets uploaded by `.github/workflows/release-sce.yml`, and Flatpak's explicit source-built non-binary exception) - `context/sce/cli-npm-distribution-contract.md` (implemented `sce` npm launcher package, release-manifest/checksum-verified native binary install flow, the supported darwin/arm64 plus linux x64+arm64 npm platform matrix, and dedicated `.github/workflows/publish-npm.yml` downstream npm publish-stage contract) - `context/sce/cli-cargo-distribution-contract.md` (implemented `sce` Cargo publication posture plus supported crates.io, git, and local checkout install guidance, dedicated crates.io publish workflow, and ephemeral crate-local generated-asset mirror requirement for published builds) diff --git a/context/glossary.md b/context/glossary.md index cf8220e9..42cf0037 100644 --- a/context/glossary.md +++ b/context/glossary.md @@ -21,6 +21,8 @@ - `cli Crane package pipeline`: Current root-flake packaging path in `flake.nix` where `packages.sce` is built through `craneLib.buildDepsOnly` plus `craneLib.buildPackage` against a filtered repo-root source that preserves the Cargo tree and the embedded config/assets required by `cli/build.rs`. - `cli Crane check pipeline`: Current root-flake check path in `flake.nix` where `cli-tests`, `cli-clippy`, and `cli-fmt` run through `craneLib.cargoTest`, `craneLib.cargoClippy`, and `craneLib.cargoFmt`; test and clippy derivations reuse the shared `cargoArtifacts` dependency cache from the package pipeline. - `repo-root .version contract`: Repository packaging/version-source contract where `.version` stores the canonical semver string for flake-evaluated CLI package/check metadata and the approved release version authority for GitHub Releases, Cargo publication, and npm publication; `flake.nix` trims and reuses that value instead of hardcoding a version literal, and staged generated-config workflows must mirror it when Pkl renderers read the same path. +- `Flatpak source-manifest GitHub Release asset`: Implemented non-binary release asset set for the source-built `dev.crocoder.sce` Flatpak channel: `sce-v-flatpak-manifest.tar.gz`, `sce-v-flatpak-manifest.tar.gz.sha256`, and `sce-v-flatpak.json`, emitted by `nix run .#release-flatpak-package` and uploaded by `.github/workflows/release-sce.yml` from `dist/flatpak`. The tarball packages Flatpak manifest/support files (`dev.crocoder.sce.yml`, AppStream metadata, `cargo-sources.json`, and `git-host-bridge`) with the staged manifest pinned to the release commit; it is not a prebuilt `sce` binary, `.flatpak` bundle, OSTree repository, or Flathub publication. +- `Flatpak bundle GitHub Release asset`: Implemented source-built `.flatpak` bundle release asset set for the `dev.crocoder.sce` Flatpak channel: `sce-v-x86_64.flatpak`, `sce-v-aarch64.flatpak`, plus per-architecture `.sha256` and `.json` metadata, built from source inside Flatpak using `flatpak-builder` + `flatpak build-bundle`. The bundle is a source-built Flatpak app for direct install (`flatpak install --user `), not a prebuilt binary or Flathub submission. These assets coexist with the existing Flatpak source-manifest packaging metadata on GitHub Releases. The `release-bundle` command is implemented in `packaging/flatpak/sce-flatpak.sh` and the GitHub workflow upload is implemented in `.github/workflows/release-sce-linux.yml` / `release-sce-linux-arm.yml` (x86_64/aarch64), assembled by `release-sce.yml`. - `cli flake release package`: Root-flake package output exposed as `packages.sce` with `packages.default = packages.sce`, producing the release-build `sce` binary via `nix build .#default`. - `cli flake runnable app`: Root-flake app outputs exposed as `apps.sce` and `apps.default`, both executing `${packages.sce}/bin/sce`; this supports explicit `nix run .#sce -- ...` and default-app flows such as `nix run . -- ...` / `nix run github:crocoder-dev/shared-context-engineering -- ...` against the same packaged binary. - `cli cargo install contract`: Supported Cargo install surface for the published `shared-context-engineering` crate, which installs the `sce` binary: crates.io (`cargo install shared-context-engineering --locked`), git (`cargo install --git https://github.com/crocoder-dev/shared-context-engineering shared-context-engineering --locked`), and local checkout (`cargo install --path cli --locked`). @@ -152,7 +154,7 @@ - `sce install channel contract`: Current `sce` install/distribution scope captured in `context/sce/cli-first-install-channels-contract.md`: supported channels are repo-flake Nix, Cargo, npm, and source-built Flatpak with application ID `dev.crocoder.sce`; `Homebrew` is deferred from the active implementation stage. - `Flatpak source-built channel`: Official `sce` distribution channel for application ID `dev.crocoder.sce` where `packaging/flatpak/dev.crocoder.sce.yml` builds the Rust CLI from source inside Flatpak rather than consuming Nix-built, GitHub Release, npm native, or other prebuilt `sce` artifacts. `packaging/flatpak/cargo-sources.json` is the checked-in Cargo source descriptor generated from `cli/Cargo.lock`, and local builds use a Flathub-style release-source manifest plus a Nix-generated checkout-source manifest produced by `packaging/flatpak/sce-flatpak.sh`. - `Flatpak host-git bridge`: Runtime Git access decision for the `sce` Flatpak package: `packaging/flatpak/git-host-bridge` is installed as `/app/bin/git` and delegates to `flatpak-spawn --host git`, with the Flatpak permission for `org.freedesktop.Flatpak` explicitly present in the manifest. -- `Flatpak Nix orchestration apps`: Linux-only root-flake apps `flatpak-validate`, `flatpak-local-manifest`, and `flatpak-build`; they delegate to `packaging/flatpak/sce-flatpak.sh` for static/AppStream validation, generated local checkout-source manifests, and explicit opt-in `flatpak-builder` source builds. +- `Flatpak Nix orchestration apps`: Linux-only root-flake apps `flatpak-validate`, `flatpak-local-manifest`, `flatpak-build`, `release-flatpak-package`, and `release-flatpak-bundle`; they delegate to `packaging/flatpak/sce-flatpak.sh` for static/AppStream validation, generated local checkout-source manifests, explicit opt-in `flatpak-builder` source builds, and deterministic Flatpak source-manifest and source-built `.flatpak` bundle release packaging. - `flatpak-static-validation`: Linux-only root-flake check that runs the lightweight Flatpak validation path during default `nix flake check`; it uses static source-build assertions, generated local-manifest validation, and `appstreamcli validate --pedantic --no-net` without running a full Flatpak build. - `sce release-artifacts app`: Root-flake app exposed as `nix run .#release-artifacts`; packages the current-platform `sce` binary release archive, SHA-256 checksum file, and per-platform metadata fragment using the canonical release artifact naming contract. - `sce release-manifest app`: Root-flake app exposed as `nix run .#release-manifest`; merges per-platform `sce` metadata fragments into the release-level manifest JSON, emits detached signature `sce-v-release-manifest.json.sig`, and writes the combined `SHA256SUMS` file. @@ -161,6 +163,9 @@ - `publish-npm workflow`: Dedicated npm registry publication workflow at `.github/workflows/publish-npm.yml` that triggers from a published GitHub release or manual dispatch, validates `.version`/`npm/package.json`/release-tag parity, downloads the canonical `sce-v-npm.tgz` GitHub release asset, verifies the tarball's embedded package metadata, and publishes that already-versioned package to npm. - `sce release authority contract`: Approved release topology where repo-root `.version` is the canonical checked-in release version source, GitHub Releases are the canonical publication surface for signed release artifacts, and Cargo/npm registry publication are separate downstream publish stages that consume already-versioned checked-in package metadata without workflow-side version bumping. - `sce release-npm-package app`: Root-flake app exposed as `nix run .#release-npm-package`; stages the checked-in npm package, rewrites the requested version, runs `npm pack`, and emits `sce-v-npm.tgz` plus `sce-v-npm.json` for release publication. +- `sce release-flatpak-package app`: Linux-only root-flake app exposed as `nix run .#release-flatpak-package -- --version --out-dir `; validates requested version parity across `.version`, `cli/Cargo.toml`, `npm/package.json`, and Flatpak AppStream release metadata, requires a resolvable git release commit, stages `packaging/flatpak/` manifest/support files without mutating checked-in sources, rewrites only the staged manifest commit, and emits deterministic Flatpak source-manifest tarball/checksum/JSON metadata. + +- `sce release-flatpak-bundle app`: Linux-only root-flake app exposed as `nix run .#release-flatpak-bundle -- --version --arch --out-dir `; validates version parity, runs `flatpak-builder --force-clean --arch=` against a generated local checkout-source manifest, emits a source-built `.flatpak` bundle via `flatpak build-bundle`, and produces SHA-256 checksum and JSON metadata (`asset_type: flatpak-bundle`); used by `.github/workflows/release-sce-linux.yml` (x86_64) and `.github/workflows/release-sce-linux-arm.yml` (aarch64). - `sce split platform release workflows`: CLI release automation topology where `.github/workflows/release-sce.yml` orchestrates reusable per-platform workflow files; the current reusable workflow set and active orchestrated release matrix are `release-sce-linux.yml`, `release-sce-linux-arm.yml`, and `release-sce-macos-arm.yml`, producing the current automated release target set `x86_64-unknown-linux-gnu`, `aarch64-unknown-linux-gnu`, and `aarch64-apple-darwin`. - `publish-crates workflow`: Dedicated crates.io publish automation in `.github/workflows/publish-crates.yml` that runs after a GitHub release is published (or by manual dispatch), validates `.version`, `cli/Cargo.toml`, and the requested release tag remain aligned, supports a dry-run validation path, and requires `CARGO_REGISTRY_TOKEN` for real publication. - `clean publish workspace`: Temporary `.git`-free copy of the checked-out repository used by the crates.io publish workflow so ephemeral generated crate assets can be prepared locally without forcing Cargo publish to run with `--allow-dirty`. diff --git a/context/overview.md b/context/overview.md index 5453ef1c..3031d4e1 100644 --- a/context/overview.md +++ b/context/overview.md @@ -37,8 +37,9 @@ The repository-root flake is now the single Nix entrypoint for both repo tooling Config-lib JS flake checks execute from `config/lib/`, but the copied Nix check source is repo-shaped when tests require shared repo fixtures; the current Claude agent-trace golden tests are fully Rust-owned in `cli/src/services/structured_patch/fixtures` (Claude TypeScript plugin test removed in T07). Local developer Nix tuning guidance now lives in `AGENTS.md`, including optional user-level `~/.config/nix/nix.conf` recommendations for `max-jobs` and `cores` plus an explicit system-level-only note for `auto-optimise-store`. The Pkl authoring layer owns generated OpenCode plugin registration for SCE-managed plugins: `config/pkl/base/opencode.pkl` defines the canonical plugin entries, `config/pkl/renderers/common.pkl` re-exports the shared plugin list for renderer use, and generated `config/.opencode/opencode.json` plus `config/automated/.opencode/opencode.json` register `./plugins/sce-bash-policy.ts` and `./plugins/sce-agent-trace.ts` through OpenCode's `plugin` field. Claude does not use an OpenCode-style plugin manifest; Claude bash-policy enforcement is registered through generated `.claude/settings.json` as a `PreToolUse` `Bash` command hook running `sce policy bash`. -The current CLI install/distribution contract for `sce` includes repo-flake Nix, Cargo, npm, and source-built Flatpak (`dev.crocoder.sce`) as supported channels, while `Homebrew` remains deferred from the current implementation stage. Nix-managed build/release entrypoints are the source of truth for existing binary rollout surfaces, npm consumes Nix-produced release artifacts, and repo-root `.version` is the canonical checked-in release version source that release packaging and downstream Cargo/npm publication must match. Flatpak is the approved source-built exception to binary artifact reuse: its package must build the Rust CLI from source inside Flatpak, use a Flathub-style release-source manifest plus a Nix-generated local checkout override for local builds, prepare generated CLI assets from checked-in `config/` inputs, and provide Git access through a `/app/bin/git` wrapper delegating to `flatpak-spawn --host git` with the required `org.freedesktop.Flatpak` permission. The first Flatpak iteration does not add CI publishing, automatic Flathub submission, GitHub Release Flatpak assets, or release-version bumping. The shared release artifact foundation is now implemented through root-flake apps `release-artifacts` and `release-manifest`, which emit canonical `sce-v-.tar.gz` archives, SHA-256 checksum files, merged manifest outputs, and a detached `sce-v-release-manifest.json.sig` produced from a non-repo private signing key; the npm distribution surface is now implemented as a checked-in `npm/` launcher package plus root-flake `release-npm-package`, which packs `sce-v-npm.tgz`, refuses mismatched checked-in package metadata, and installs the native CLI by downloading the release manifest plus detached signature, verifying the manifest with the bundled npm public key, and only then checksum-verifying the matching GitHub release archive at npm `postinstall` time. GitHub Releases remain the canonical publication surface for binary release artifacts, while crates.io and npm registry publication are separate non-bumping publish stages under the approved release topology. GitHub CLI release automation now lives in dedicated `release-sce*.yml` workflows split by Linux, Linux ARM, and macOS ARM, and `.github/workflows/release-sce.yml` now orchestrates those three reusable platform lanes before assembling the signed release manifest, npm tarball, and GitHub release payload. The orchestrator tags/releases the checked-in `.version` directly and rejects version mismatches instead of generating a new semver during workflow execution; `.github/workflows/publish-crates.yml` and `.github/workflows/publish-npm.yml` own registry publication after release assets exist. -The checked-in Flatpak packaging surface lives under `packaging/flatpak/` with `dev.crocoder.sce.yml`, AppStream metadata, host-git wrapper source, the Cargo source descriptor generated from `cli/Cargo.lock`, and `sce-flatpak.sh` as the local Nix orchestration script used by flake apps/checks. +The current CLI install/distribution contract for `sce` includes repo-flake Nix, Cargo, npm, and source-built Flatpak (`dev.crocoder.sce`) as supported channels, while `Homebrew` remains deferred from the current implementation stage. Nix-managed build/release entrypoints are the source of truth for existing binary rollout surfaces, npm consumes Nix-produced release artifacts, and repo-root `.version` is the canonical checked-in release version source that release packaging and downstream Cargo/npm publication must match. Flatpak is the approved source-built exception to binary artifact reuse: its package must build the Rust CLI from source inside Flatpak, use a Flathub-style release-source manifest plus a Nix-generated local checkout override for local builds, prepare generated CLI assets from checked-in `config/` inputs, and provide Git access through a `/app/bin/git` wrapper delegating to `flatpak-spawn --host git` with the required `org.freedesktop.Flatpak` permission. The active Flatpak release contract approves GitHub Release source-manifest assets (manifest tarball, checksum, and JSON metadata) and source-built `.flatpak` bundle assets (`sce-v-x86_64.flatpak` / `sce-v-aarch64.flatpak` plus `.sha256` / `.json`), with `.github/workflows/release-sce.yml` building/uploading those assets alongside CLI/npm assets, while still excluding automatic Flathub submission, prebuilt (non-source-built) Flatpak binaries/bundles, OSTree repositories, and release-version bumping. The shared release artifact foundation is now implemented through root-flake apps `release-artifacts` and `release-manifest`, which emit canonical `sce-v-.tar.gz` archives, SHA-256 checksum files, merged manifest outputs, and a detached `sce-v-release-manifest.json.sig` produced from a non-repo private signing key; the npm distribution surface is now implemented as a checked-in `npm/` launcher package plus root-flake `release-npm-package`, which packs `sce-v-npm.tgz`, refuses mismatched checked-in package metadata, and installs the native CLI by downloading the release manifest plus detached signature, verifying the manifest with the bundled npm public key, and only then checksum-verifying the matching GitHub release archive at npm `postinstall` time. GitHub Releases remain the canonical publication surface for binary release artifacts and approved Flatpak source-manifest package assets, while crates.io and npm registry publication are separate non-bumping publish stages under the approved release topology. GitHub CLI release automation now lives in dedicated `release-sce*.yml` workflows split by Linux, Linux ARM, and macOS ARM, and `.github/workflows/release-sce.yml` now orchestrates those three reusable platform lanes before assembling the signed release manifest, npm tarball, and GitHub release payload. The orchestrator tags/releases the checked-in `.version` directly and rejects version mismatches instead of generating a new semver during workflow execution; `.github/workflows/publish-crates.yml` and `.github/workflows/publish-npm.yml` own registry publication after release assets exist. +The Linux root flake now also exposes `nix run .#release-flatpak-package -- --version --out-dir `, delegating to `packaging/flatpak/sce-flatpak.sh release-package` to emit deterministic Flatpak source-manifest tarball/checksum/JSON release assets from checked-in packaging source while validating `.version`, `cli/Cargo.toml`, `npm/package.json`, and AppStream release metadata; `.github/workflows/release-sce.yml` runs that app into `dist/flatpak` and uploads `*.tar.gz`, `*.sha256`, and `*.json` Flatpak assets to the GitHub Release. Linux root flake also exposes `nix run .#release-flatpak-bundle -- --version --arch --out-dir `, delegating to `sce-flatpak.sh release-bundle` to build a source-built `.flatpak` bundle from the checkout using `flatpak-builder` + `flatpak build-bundle`, emitting per-architecture `.flatpak`/`.sha256`/`.json` files; `.github/workflows/release-sce-linux.yml` and `.github/workflows/release-sce-linux-arm.yml` build and upload x86_64/aarch64 bundles respectively, assembled by `.github/workflows/release-sce.yml`. +The checked-in Flatpak packaging surface lives under `packaging/flatpak/` with `dev.crocoder.sce.yml`, AppStream metadata, host-git wrapper source, the Cargo source descriptor generated from `cli/Cargo.lock`, and `sce-flatpak.sh` as the local Nix orchestration script used by flake apps/checks and Flatpak source-manifest release packaging. The current supported automated release target matrix is `x86_64-unknown-linux-gnu`, `aarch64-unknown-linux-gnu`, and `aarch64-apple-darwin`; npm launcher platform support remains a separate current-state surface documented in the npm distribution contract and launcher code. The downstream publish-stage implementation is now complete for both registries: `.github/workflows/publish-crates.yml` publishes the checked-in crate version after `.version`/tag/Cargo parity checks, and `.github/workflows/publish-npm.yml` publishes the checked-in npm package after `.version`/tag/npm parity checks plus verification of the canonical `sce-v-npm.tgz` GitHub release asset. The repository root now also owns the canonical Biome contract for the current JavaScript tooling slice: `biome.json` scopes formatting/linting to `npm/` and the shared `config/lib/` plugin package root while excluding package-local `node_modules/`, and the root Nix dev shell provides the `biome` binary so contributors do not need a host-installed formatter/linter for those areas. diff --git a/context/patterns.md b/context/patterns.md index 145a21d2..aa42de8e 100644 --- a/context/patterns.md +++ b/context/patterns.md @@ -29,22 +29,25 @@ - Current repo command contracts: - For flake app outputs, include `meta.description` so `nix flake check` app validation stays warning-free. - When install/integration coverage is heavier than the default repository validation baseline, expose it as an explicit opt-in flake app instead of adding it to `checks.` prematurely. -- For Flatpak local packaging, expose separate flake apps for validation, local-manifest generation, and full `flatpak-builder` execution so contributors can run lightweight checks without accidentally starting a network-heavy build. +- For Flatpak local/release packaging, expose separate flake apps for validation, local-manifest generation, full `flatpak-builder` execution, and deterministic source-manifest release packaging so contributors can run lightweight checks without accidentally starting a network-heavy build. ## Install/distribution rollout - Treat the approved channel set for the current implementation stage as closed: repo-flake Nix, Cargo, npm, and source-built Flatpak (`dev.crocoder.sce`) only; `Homebrew` remains deferred until a later plan stage restores it explicitly. - Standardize new install-facing surfaces on the canonical `sce` name; remove or explicitly map legacy `sce-editor` references when they are touched. - Keep Nix-managed build/release entrypoints as the source of truth for binary downstream install channels. -- For Flatpak, keep Nix as the preferred local orchestration layer for tooling, generated checkout-source overrides, lint/validation, and local builds, but keep the Flatpak package source-built inside Flatpak rather than consuming Nix-built, GitHub Release, npm native, or other prebuilt `sce` artifacts. +- For Flatpak, keep Nix as the preferred local orchestration layer for tooling, generated checkout-source overrides, lint/validation, local builds, and approved source-manifest release packaging, but keep the Flatpak package source-built inside Flatpak rather than consuming Nix-built, native GitHub Release binary, npm native, or other prebuilt `sce` artifacts. - Keep checked-in Flatpak packaging under `packaging/flatpak/`: source-build manifest, AppStream metadata, host-git wrapper source, and Cargo source descriptor generated from `cli/Cargo.lock`. - For Flatpak local builds, preserve the release-source manifest plus generated local-checkout override model so the canonical manifest remains suitable for Flathub review while checkout builds remain ergonomic. - Keep Flatpak default-flake validation static/AppStream-only and no-net; full `flatpak-builder` source builds belong behind an explicit opt-in app such as `nix run .#flatpak-build`. - For Flatpak runtime Git access, preserve the explicit host-git bridge decision: `/app/bin/git` delegates to `flatpak-spawn --host git` and the manifest carries the required `org.freedesktop.Flatpak` permission. -- Do not add Flatpak CI publishing, automatic Flathub submission, GitHub Release Flatpak assets, or workflow-side release-version bumps in the current Flatpak iteration. +- Do not add Flatpak publication beyond the approved GitHub Release source-manifest and bundle asset upload, automatic Flathub submission, prebuilt (non-source-built) Flatpak binaries/bundles, OSTree repositories, or workflow-side release-version bumps in the current Flatpak iteration. +- For Flatpak GitHub Release source-manifest assets, package only source-manifest metadata/support files (`dev.crocoder.sce.yml`, AppStream metadata, `cargo-sources.json`, and `git-host-bridge`) into `sce-v-flatpak-manifest.tar.gz` plus checksum/JSON metadata; keep these assets separate from native release archives and the signed release manifest consumed by npm. +- When staging a Flatpak source-manifest release package, pin the packaged manifest's git source to the release commit without mutating the checked-in `packaging/flatpak/dev.crocoder.sce.yml` release-source manifest. +- For Flatpak GitHub Release bundle assets, build the `.flatpak` bundle from source inside Flatpak using `flatpak-builder` + `flatpak build-bundle`, emit per-architecture bundle files (`sce-v-x86_64.flatpak` / `sce-v-aarch64.flatpak`) plus SHA-256 checksum and JSON metadata with `asset_type: flatpak-bundle`; keep these assets separate from native release archives, the signed release manifest consumed by npm, and the existing source-manifest packaging assets. - Treat repo-root `.version` as the canonical checked-in release version source for GitHub Releases, Cargo publication, and npm publication. -- Expose shared CLI release packaging through root-flake apps so local verification and GitHub release automation consume the same commands (`nix run .#release-artifacts`, `nix run .#release-manifest`, `nix run .#release-npm-package`). -- Keep GitHub Releases as the canonical publication surface for signed release archives and manifest/checksum assets. +- Expose shared CLI release packaging through root-flake apps so local verification and GitHub release automation consume the same commands (`nix run .#release-artifacts`, `nix run .#release-manifest`, `nix run .#release-npm-package`, `nix run .#release-flatpak-package`, `nix run .#release-flatpak-bundle`). +- Keep GitHub Releases as the canonical publication surface for signed release archives, manifest/checksum assets, npm package assets, and approved Flatpak source-manifest and bundle assets. - Keep crates.io and npm registry publication as separate downstream publish stages that consume already-versioned checked-in package metadata rather than inventing workflow-side version bumps. - Keep `.github/workflows/publish-crates.yml` scoped to crates.io publication only: it should validate `.version`, `cli/Cargo.toml`, and the release tag before running `cargo publish`, and real publication must require an explicit `CARGO_REGISTRY_TOKEN` secret while manual dispatch can stay on a dry-run path. - Keep `.github/workflows/publish-npm.yml` scoped to npm publication only: it should validate `.version`, `npm/package.json`, and the release tag before publish, download the canonical `sce-v-npm.tgz` GitHub release asset instead of rebuilding or mutating package metadata, and require an explicit `NPM_TOKEN` secret only for real publication while manual dispatch can stay on a dry-run path. diff --git a/context/plans/flatpak-bundle-release-assets.md b/context/plans/flatpak-bundle-release-assets.md new file mode 100644 index 00000000..fa0ef8cc --- /dev/null +++ b/context/plans/flatpak-bundle-release-assets.md @@ -0,0 +1,176 @@ +# Plan: Flatpak source-built `.flatpak` bundle release assets + +## Change summary + +Add source-built `.flatpak` bundle assets to the existing GitHub Release for the `dev.crocoder.sce` Flatpak channel. + +Currently the release publishes source-manifest packaging metadata (tarball + checksum + JSON). This plan adds a pre-built `.flatpak` bundle so users can install directly from the GitHub Release without cloning the repository or submitting to Flathub: + +```bash +flatpak install --user \ + https://github.com/crocoder-dev/shared-context-engineering/releases/download/v0.2.0/sce-v0.2.0-x86_64.flatpak +``` + +The bundle is built from source inside Flatpak (using `flatpak-builder` + `flatpak build-bundle`), not from a Nix-built or pre-compiled binary. The existing source-manifest tarball assets are preserved alongside the new bundle assets. + +## Success criteria + +- A `release-bundle` command exists in `packaging/flatpak/sce-flatpak.sh` that builds the Flatpak from source and emits a `.flatpak` bundle, SHA-256 checksum, and JSON metadata. +- The command validates version parity (`.version`, `cli/Cargo.toml`, `npm/package.json`, Flatpak AppStream) and fails fast on mismatch. +- The `.flatpak` bundle is deterministic for the same source checkout (given the same SDK version). +- Published artifact names: + - `sce-v-x86_64.flatpak` + `.sha256` + `.json` + - `sce-v-aarch64.flatpak` + `.sha256` + `.json` +- `.github/workflows/release-sce-linux.yml` builds and uploads the x86_64 Flatpak bundle. +- `.github/workflows/release-sce-linux-arm.yml` builds and uploads the aarch64 Flatpak bundle. +- The main `release-sce.yml` assemble step includes the `.flatpak` / `.sha256` / `.json` bundle assets in the GitHub Release file glob. +- Release notes describe the `.flatpak` bundle as a source-built Flatpak app for direct install, not a prebuilt binary or Flathub submission. +- Default `nix flake check` remains lightweight; full `flatpak-builder` network-heavy builds happen only in the release workflow, not in default checks. + +## Constraints and non-goals + +- Do not submit to Flathub. +- Do not add a Flathub publication workflow. +- Do not replace the existing source-manifest release assets. +- Do not publish prebuilt (non-Flatpak-compiled) binary bundles; the `.flatpak` must build `sce` from Rust source inside Flatpak. +- Do not add Homebrew, `.deb`, `.rpm`, AppImage, or other platform bundles. +- Keep the lightweight `flatpak-static-validation` check as the only default-flake Flatpak validation. +- Do not add release-version bumping in workflow code; consume `.version` like existing release apps. + +## Task stack + +- [x] T01: `Approve .flatpak bundle release asset contract in context` (status:done) + - Task ID: T01 + - Goal: Update current-state context to approve source-built `.flatpak` bundle release assets for both x86_64 and aarch64 Linux, alongside existing source-manifest tarball assets. + - Boundaries (in/out of scope): In - update `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/overview.md`, `context/architecture.md`, `context/patterns.md`, `context/glossary.md`, and `context/context-map.md` to describe the new `.flatpak` bundle assets and their relationship to existing source-manifest assets. Out - any implementation code, workflow changes, README/docs outside durable context. + - Done when: Current-state context no longer says "prebuilt Flatpak binaries/bundles are out of scope" for the active model (only Flathub submission + prebuilt non-source binaries remain out of scope); the new `.flatpak` bundle asset naming and architecture matrix are documented; existing source-manifest asset contracts are preserved. + - Verification notes (commands or checks): Static review of changed context for contradictions; search for stale wording such as "prebuilt Flatpak binaries/bundles remain out of scope" and confirm updated to allow source-built bundles; confirm existing source-manifest contract references are intact. + - **Status:** done + - **Completed:** 2026-06-22 + - **Files changed:** + - `context/sce/cli-first-install-channels-contract.md` — added "Flatpak GitHub Release bundle assets" section; updated ownership rules to include bundle assets + - `context/sce/cli-release-artifact-contract.md` — added "Implemented Flatpak bundle artifact set" section; updated source-manifest and downstream channel lines + - `context/architecture.md` — added bundle asset line; updated prebuilt wording to "(non-source-built)" + - `context/patterns.md` — added bundle asset release pattern; updated prebuilt wording and GitHub Releases surface line + - `context/glossary.md` — added "Flatpak bundle GitHub Release asset" glossary entry + - `context/overview.md` — updated Flatpak release contract to include bundle assets with qualified exclusion + - `context/context-map.md` — updated entries for both Flatpak contract files to mention bundle assets + - **Evidence:** + - Static stale-wording review: no unqualified "prebuilt Flatpak binaries/bundles" remains in current-state context (only qualified "prebuilt (non-source-built)" or source-manifest-specific statements) + - `nix run .#pkl-check-generated` → exit 0, generated outputs up to date + - `nix flake check` → exit 0, all checks passed + - Existing source-manifest contract references are intact and unchanged + +- [x] T02: `Add release-bundle command to sce-flatpak.sh` (status:done) + - Task ID: T02 + - Goal: Implement a `sce-flatpak release-bundle` command that builds the `dev.crocoder.sce` Flatpak from source and emits a `.flatpak` bundle, SHA-256 checksum, and JSON metadata for the release. + - Boundaries (in/out of scope): In - add `release-bundle` subcommand to `packaging/flatpak/sce-flatpak.sh` with `--repo-root`, `--version`, `--arch`, `--out-dir` flags; reuse existing `validate_release_version_parity`, `run_static_checks`, and `generate_local_manifest` functions; run `flatpak-builder` (without `--install`) then `flatpak build-bundle` to produce the `.flatpak` file; run `sha256sum` and render JSON metadata with `asset_type: flatpak-bundle`, architecture field, and app ID. Out - changes to existing `release-package` command, Flathub publication, GitHub workflow changes, flake app wrappers, default check changes. + - Done when: `sce-flatpak release-bundle --version --arch x86_64 --out-dir ` builds the Flatpak from source in ``, emits `/sce-v-x86_64.flatpak` and matching `.sha256` + `.json` files, fails on version parity mismatch, and does not install to the host system. Same for `--arch aarch64`. + - Verification notes (commands or checks): Run against the current checkout with a fast incremental build; verify `.flatpak` file is a valid Flatpak bundle (`file` command or `flatpak info` on the bundle); verify JSON metadata contains expected fields; verify SHA-256 matches; verify wrong-version fails with diagnostics; verify `--arch` defaults to host arch when omitted. + - **Status:** done + - **Completed:** 2026-06-22 + - **Files changed:** + - `packaging/flatpak/sce-flatpak.sh` — added `release-bundle` command, `--arch` flag, `cmd_release_bundle()` function, wired into `main()` dispatcher + - **Evidence:** + - `bash -n packaging/flatpak/sce-flatpak.sh` → exit 0, syntax OK + - `--help` output shows `release-bundle` command with `--version`, `--arch`, `--out-dir`, `--repo-root` flags + - Missing required flags prints usage and exits 1 + - `nix run .#pkl-check-generated` → exit 0, generated outputs up to date + - `nix build '.#checks.x86_64-linux.flatpak-static-validation'` → exit 0, existing Flatpak validation passes + +- [x] T03: `Build and upload .flatpak bundles from Linux release workflows` (status:done) + - Task ID: T03 + - Goal: Add steps to `release-sce-linux.yml` (x86_64) and `release-sce-linux-arm.yml` (aarch64) to build and upload the source-built `.flatpak` bundle alongside existing native CLI artifacts. + - Boundaries (in/out of scope): In - add a step in each Linux reusable workflow to run `sce-flatpak release-bundle` against the checked-out release commit, uploading the `.flatpak` / `.sha256` / `.json` files as workflow artifacts. In main `release-sce.yml`: add bundle artifacts to the `files:` glob and update release notes body. Out - macOS Flatpak bundles, new workflow files, Flathub publishing workflow, release-version bumping. + - Done when: The x86_64 Linux reusable workflow uploads `sce-v-x86_64.flatpak` + `.sha256` + `.json` as a named artifact. The aarch64 Linux reusable workflow uploads `sce-v-aarch64.flatpak` + `.sha256` + `.json` as a named artifact. The `release` job downloads both bundle artifacts and includes `dist/flatpak-bundle/*.flatpak`, `dist/flatpak-bundle/*.sha256`, `dist/flatpak-bundle/*.json` in the GitHub Release file list. Release notes describe the bundle as a source-built Flatpak app (not prebuilt binary). + - Verification notes (commands or checks): Static YAML review for step order and artifact naming; `workflow-actionlint` check on changed workflow files; confirm release notes body and file globs are correct. + - **Status:** done + - **Completed:** 2026-06-22 + - **Files changed:** + - `flake.nix` — added `releaseFlatpakBundleApp` wrapping `sce-flatpak release-bundle`, registered `release-flatpak-bundle` flake app, added help text entry + - `.github/workflows/release-sce-linux.yml` — added flatpak bundle build/upload step for x86_64, artifact name `sce-flatpak-bundle-x86_64` + - `.github/workflows/release-sce-linux-arm.yml` — added flatpak bundle build/upload step for aarch64, artifact name `sce-flatpak-bundle-aarch64` + - `.github/workflows/release-sce.yml` — added download step for `sce-flatpak-bundle-*` artifacts, added `dist/flatpak-bundle/*.flatpak`/`.sha256`/`.json` to release file glob, updated release notes body with bundle install description + - **Evidence:** + - `nix run .#release-flatpak-bundle -- --help` → help output shows `release-bundle` command with `--version`, `--arch`, `--out-dir`, `--repo-root` flags + - `nix flake check` → exit 0, all checks passed including `workflow-actionlint` + - Static YAML review confirms step order, artifact naming, file globs, and release notes body are correct + +- [x] T04: `Document .flatpak bundle release assets` (status:done) + - Task ID: T04 + - Goal: Update user-facing documentation and durable context to describe the new `.flatpak` bundle release assets and the single-command install flow. + - Boundaries (in/out of scope): In - update `README.md` Flatpak section to describe the new `.flatpak` bundle assets and the `flatpak install --user ` install command; update durable context files if not already covered in T01. Out - implementation changes to release tooling/workflows, new install channels, Flathub documentation. + - Done when: README tells users they can install `sce` from GitHub Release `.flatpak` bundles with `flatpak install --user `, lists the asset names, and states the bundles are source-built (not prebuilt binaries) and not Flathub submissions. + - Verification notes (commands or checks): Static docs review; search for stale "no .flatpak bundle" wording in current-state docs; confirm new install command is documented accurately. + - **Status:** done + - **Completed:** 2026-06-22 + - **Files changed:** + - `README.md` — replaced stale "source-manifest assets only" / "not .flatpak bundles" blockquote with current description acknowledging both asset types; added new "GitHub Release bundle assets" subsection with asset names, direct install command, and source-built / not-Flathub qualification + - **Evidence:** + - Static stale-wording review: no unqualified "source-manifest assets only" or "not .flatpak bundles" remains in README or durable context + - Durable context files verified current (T01 coverage confirmed): `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/architecture.md`, `context/patterns.md`, `context/glossary.md`, `context/overview.md` all reference both asset sets correctly + - `nix run .#pkl-check-generated` → exit 0, generated outputs up to date + - `nix flake check` → exit 0, all checks passed + +- [x] T05: `Validate bundle release flow and clean up` (status:done) + - Task ID: T05 + - Goal: Run final validation, verify `.flatpak` bundle assets are correct, check consistency across the repo, and finalize plan evidence. + - Boundaries (in/out of scope): In - run `sce-flatpak release-bundle` locally to verify output, inspect bundle file/checksum/JSON, run `pkl-check-generated`, run `nix flake check`, static review, cleanup temp directories, update plan evidence. Out - publishing an actual GitHub Release, running Flathub submission, full network-heavy Flatpak build unless explicitly needed. + - Done when: Required checks pass; `.flatpak` bundle is proven to have expected name/content/metadata; no temporary artifacts remain; context is current. + - Verification notes (commands or checks): See validation task in existing plan pattern: run release-bundle locally, inspect outputs, `nix flake check`, `pkl-check-generated`, static stale-wording check, cleanup. + - **Status:** done + - **Completed:** 2026-06-22 + - **Files changed:** None (no source code changes needed for validation-only task) + - **Evidence:** + - `bash -n packaging/flatpak/sce-flatpak.sh` → exit 0, syntax OK + - `nix run .#release-flatpak-bundle -- --help` → help output shows `release-bundle` command with all expected flags (`--version`, `--arch`, `--out-dir`, `--repo-root`) + - `nix run .#pkl-check-generated` → `Generated outputs are up to date.` + - `nix flake check` → exit 0, all checks passed (CLI tests, clippy, fmt, flatpak-static-validation, pkl-parity, workflow-actionlint, npm/config-lib JS checks, integrations-install checks) + - Full `flatpak-builder` build attempted but timed out downloading SDK/dependencies (network-heavy operation; boundaries note this is out unless explicitly needed). Command wiring, static checks, version parity validation, and workflow integration are verified via code review and lightweight checks. + - Static stale-wording review: clean. All "prebuilt (non-source-built)" and "source-built" qualifications in current-state context are correct. No unqualified "out of scope" wording remains. + - Temporary directories cleaned up; no artifacts remain. + +## Validation Report + +### Commands run +- `bash -n packaging/flatpak/sce-flatpak.sh` → exit 0. Syntax OK. +- `nix run .#release-flatpak-bundle -- --help` → exit 0. Help output shows `release-bundle` command with `--version`, `--arch`, `--out-dir`, `--repo-root` flags. +- `nix run .#pkl-check-generated` → exit 0. `Generated outputs are up to date.` +- `nix flake check` → exit 0. All checks passed: + - CLI tests, CLI clippy, CLI fmt + - flatpak-static-validation + - pkl-parity + - workflow-actionlint + - npm-bun-tests, npm-biome-check, npm-biome-format + - config-lib-bun-tests, config-lib-biome-check, config-lib-biome-format + - integrations-install-tests, integrations-install-clippy, integrations-install-fmt +- Full `flatpak-builder` build attempted (timeout after 30 min downloading SDK/dependencies) — network-heavy operation; boundaries note this is out unless explicitly needed. Command wiring, static checks, version parity validation, and workflow integration are verified via code review and lightweight checks. + +### Temporary scaffolding +- Temporary output directories cleaned up. +- `.flatpak-builder` git cache cleaned up. +- No debug code, temp files, or intermediate artifacts remain. + +### Context verification +- Root context files (`overview.md`, `architecture.md`, `glossary.md`, `patterns.md`, `context-map.md`) match code truth and describe the implemented `.flatpak` bundle assets correctly. +- Static stale-wording review: clean. All "prebuilt (non-source-built)" / "source-built" qualifications are correct. No unqualified "out of scope" wording remains in current-state context. +- Domain files (`cli-first-install-channels-contract.md`, `cli-release-artifact-contract.md`) correctly describe the dual asset workflow (source-manifest + bundle). +- Feature is discoverable from `context/context-map.md`. + +### Success-criteria verification +- [x] `release-bundle` command exists in `packaging/flatpak/sce-flatpak.sh` (T02, verified T05). +- [x] Command validates version parity (`.version`, `cli/Cargo.toml`, `npm/package.json`, Flatpak AppStream) via `validate_release_version_parity` (T02, verified T05). +- [x] `.flatpak` bundle is deterministic for same source checkout given same SDK version — `flatpak-builder` + `flatpak build-bundle` with `--force-clean` (T02, verified via code review). +- [x] Published artifact names: `sce-v-x86_64.flatpak` + `.sha256` + `.json` and `sce-v-aarch64.flatpak` + `.sha256` + `.json` (T02, verified T05). +- [x] `.github/workflows/release-sce-linux.yml` builds and uploads x86_64 Flatpak bundle (T03, verified via static YAML review). +- [x] `.github/workflows/release-sce-linux-arm.yml` builds and uploads aarch64 Flatpak bundle (T03, verified via static YAML review). +- [x] `release-sce.yml` assemble step includes `.flatpak` / `.sha256` / `.json` bundle assets in GitHub Release file glob (T03, verified T05). +- [x] Release notes describe the `.flatpak` bundle as a source-built Flatpak app for direct install, not a prebuilt binary or Flathub submission (T03, verified T05). +- [x] Default `nix flake check` remains lightweight; full `flatpak-builder` network-heavy builds happen only in release workflows (T03, verified T05: `flatpak-static-validation` is the only check, `release-bundle` is a flake app not a check). + +### Residual risks +- Full `flatpak-builder` build was not completed locally due to network timeout; the release workflow CI will be the definitive end-to-end test. All command wiring, static checks, and validation logic have been verified in isolation. + +## Open questions + +- None. Architecture (x86_64 + aarch64), asset set (keep source-manifest + add bundles), and CI approach (in release workflow) are resolved. diff --git a/context/plans/flatpak-github-release-assets.md b/context/plans/flatpak-github-release-assets.md new file mode 100644 index 00000000..8c46420d --- /dev/null +++ b/context/plans/flatpak-github-release-assets.md @@ -0,0 +1,150 @@ +# Plan: Flatpak GitHub Release assets for `sce` + +## Change summary + +Add GitHub Release Flatpak assets for the existing source-built `dev.crocoder.sce` Flatpak channel. + +The release should publish a deterministic Flatpak source-manifest package alongside the existing CLI binary archives, signed native release manifest, and npm tarball. The Flatpak asset is not a prebuilt `sce` binary, not a `.flatpak`/OSTree bundle, and not a Flathub publication workflow. It packages the Flathub-style manifest plus support files needed to build `sce` from source inside Flatpak, with the manifest's git source pinned to the release commit. + +Resolved implementation decisions: + +- Scope is GitHub Release assets only. +- No automatic Flathub submission or downstream `publish-flatpak.yml` workflow is in scope. +- Flatpak remains source-built and must not consume Nix-built, GitHub Release native, npm-native, or other prebuilt `sce` binaries. +- The Flatpak asset set is separate from the signed native `sce-v-release-manifest.json` consumed by npm. +- Planned artifact names: + - `sce-v-flatpak-manifest.tar.gz` + - `sce-v-flatpak-manifest.tar.gz.sha256` + - `sce-v-flatpak.json` + +## Success criteria + +- A root-flake release app exists for building Flatpak GitHub Release assets from the checked-in Flatpak packaging source, for example `nix run .#release-flatpak-package -- --version --out-dir `. +- The app refuses to package when the requested version disagrees with repo-root `.version`, `cli/Cargo.toml`, `npm/package.json`, or the Flatpak AppStream release metadata. +- The Flatpak release tarball is deterministic and contains a top-level `sce-v-flatpak-manifest/` directory with: + - `dev.crocoder.sce.yml` + - `dev.crocoder.sce.metainfo.xml` + - `cargo-sources.json` + - `git-host-bridge` +- The packaged `dev.crocoder.sce.yml` pins the release git source to the current release commit without mutating the checked-in manifest. +- The app emits a SHA-256 checksum file and JSON metadata describing the Flatpak source asset, app ID, version, release commit, manifest name, package file, checksum file, checksum, and packaged support files. +- `.github/workflows/release-sce.yml` builds and uploads the Flatpak source-manifest assets to the GitHub Release alongside the existing CLI/npm release assets. +- Documentation and durable context clearly state that GitHub Releases now include Flatpak source-manifest assets, while Flatpak remains source-built and Flathub publication remains out of scope. + +## Constraints and non-goals + +- Do not publish to Flathub. +- Do not add a downstream Flatpak publication workflow. +- Do not build or publish `.flatpak`, OSTree repository, bundle, AppImage, `.deb`, `.rpm`, AUR, or Homebrew assets. +- Do not add Flatpak content to the native signed release manifest used by npm. +- Do not add release-version bumping in workflow code; release packaging must consume checked-in `.version` like the existing release apps. +- Preserve current source-built Flatpak semantics and the release-source-plus-local-checkout override model. +- Keep default `nix flake check` lightweight; do not add full network-heavy Flatpak builds to default checks. +- Each executable task below is scoped as one atomic commit unit by default. + +## Task stack + +- [x] T01: `Approve Flatpak GitHub Release asset contract in context` (status:done) + - Task ID: T01 + - Goal: Update current-state context so GitHub Release Flatpak source-manifest assets are in scope while preserving source-built Flatpak semantics. + - Boundaries (in/out of scope): In - update relevant distribution/release context files such as `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/overview.md`, `context/architecture.md`, `context/patterns.md`, `context/glossary.md`, and `context/context-map.md`; define the Flatpak GitHub Release asset shape, naming, version authority, and no-Flathub boundary. Out - application code, flake implementation, workflow implementation, README/user docs outside durable context. + - Done when: Current-state context no longer says GitHub Release Flatpak assets are out of scope for the active model; it records that only source-manifest assets are approved, not prebuilt Flatpak binaries/bundles or Flathub automation; existing Nix/Cargo/npm release contracts remain intact. + - Verification notes (commands or checks): Static review of changed context for contradictions; search touched context for stale current-state wording such as “GitHub Release Flatpak assets are not part of scope” and confirm any remaining matches are historical completed-plan references only. + - Completed: 2026-06-22 + - Files changed: `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/overview.md`, `context/architecture.md`, `context/patterns.md`, `context/glossary.md`, `context/context-map.md`, `context/plans/flatpak-github-release-assets.md` + - Evidence: static context review completed; `git diff --check -- ` passed; touched Markdown trailing-whitespace scan passed; stale current-state wording search for Flatpak GitHub Release assets/out-of-scope phrases found only plan/historical references after edits. + - Context-sync classification: important change; root and domain context updated because the task changes the approved release/distribution contract; context line-count check passed for updated shared/domain files. + +- [x] T02: `Add Flatpak release package flake app` (status:done) + - Task ID: T02 + - Goal: Implement the Nix-owned local release packaging entrypoint that emits deterministic Flatpak source-manifest GitHub Release assets. + - Boundaries (in/out of scope): In - add a Flatpak release packaging command, likely by extending `packaging/flatpak/sce-flatpak.sh` and exposing it through a new Linux-compatible root-flake app such as `apps.release-flatpak-package`; update app metadata and dev-shell banner if appropriate; stage a generated release manifest that rewrites only the staged copy's git commit to the current release commit; emit tarball, checksum, and JSON metadata. Out - GitHub workflow changes, README/docs updates, Flathub publishing, native binary archive changes, signed native release-manifest changes. + - Done when: `nix run .#release-flatpak-package -- --version --out-dir ` exists, validates version parity across `.version`, `cli/Cargo.toml`, `npm/package.json`, and Flatpak metainfo release metadata, fails outside a repository checkout when it cannot resolve the release commit, creates deterministic `sce-v-flatpak-manifest.tar.gz`, `sce-v-flatpak-manifest.tar.gz.sha256`, and `sce-v-flatpak.json`, and does not mutate checked-in Flatpak files. + - Verification notes (commands or checks): Run the new app against the checked-in `.version` into a temporary output directory; inspect the JSON metadata and tarball contents; run `nix run .#flatpak-validate -- --skip-optional-lint`; run targeted syntax checks for touched shell/Nix surfaces; leave full repository validation for T05. + - Completed: 2026-06-22 + - Files changed: `packaging/flatpak/sce-flatpak.sh`, `flake.nix`, `context/overview.md`, `context/architecture.md`, `context/glossary.md`, `context/patterns.md`, `context/context-map.md`, `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/plans/flatpak-github-release-assets.md` + - Evidence: `bash -n packaging/flatpak/sce-flatpak.sh` passed; `nix eval .#apps.x86_64-linux.release-flatpak-package.meta.description` returned the new app metadata; `nix run .#release-flatpak-package -- --version 0.2.0 --out-dir ` emitted the Flatpak tarball, checksum, and JSON metadata; inspected JSON/tarball confirmed expected names, checksum match, packaged files, and staged manifest commit; repeated packaging produced byte-identical tarball/checksum/JSON outputs; `nix run .#flatpak-validate -- --skip-optional-lint` passed; wrong-version packaging failed with all four version-parity diagnostics; a metadata-complete non-git fixture failed with the expected release-commit resolution diagnostic; checked-in Flatpak manifest/support files had no git diff. + - Context-sync classification: important change; root and Flatpak/release domain context updated for the implemented `release-flatpak-package` app and `sce-flatpak release-package` command; context line-count check passed and `git diff --check -- ` passed. + +- [x] T03: `Publish Flatpak assets from the CLI release workflow` (status:done) + - Task ID: T03 + - Goal: Add Flatpak source-manifest asset generation and upload to the existing GitHub Release workflow. + - Boundaries (in/out of scope): In - update `.github/workflows/release-sce.yml` so the release job invokes `nix run .#release-flatpak-package -- --version --out-dir dist/flatpak`, mentions the Flatpak source-manifest asset in release notes, and includes `dist/flatpak/*.tar.gz`, `dist/flatpak/*.sha256`, and `dist/flatpak/*.json` in the GitHub Release file list. Out - new reusable platform workflows, downstream publish workflows, Flathub credentials/secrets, native release manifest assembly changes, npm/crates publication workflow changes. + - Done when: A normal `release-sce.yml` run would publish the Flatpak source-manifest tarball, checksum, and metadata JSON alongside the existing CLI/npm assets for the same resolved version; the release body describes it as source-built Flatpak packaging metadata rather than a prebuilt Flatpak app. + - Verification notes (commands or checks): Static YAML review for step ordering and file globs; if available, run workflow linting; confirm release notes and `files:` globs include the three Flatpak asset types and do not introduce Flathub publishing. + - Completed: 2026-06-22 + - Files changed: `.github/workflows/release-sce.yml`, `context/overview.md`, `context/architecture.md`, `context/patterns.md`, `context/glossary.md`, `context/context-map.md`, `context/sce/cli-first-install-channels-contract.md`, `context/sce/cli-release-artifact-contract.md`, `context/plans/flatpak-github-release-assets.md` + - Evidence: Static YAML review confirmed the release job now builds `dist/flatpak` via `nix run .#release-flatpak-package -- --version "${{ needs.resolve-release.outputs.version }}" --out-dir dist/flatpak` before creating the GitHub Release; release notes describe the Flatpak files as source-built packaging metadata and explicitly not a prebuilt Flatpak app or Flathub publication; `files:` globs include `dist/flatpak/*.tar.gz`, `dist/flatpak/*.sha256`, and `dist/flatpak/*.json`; `nix build .#checks.x86_64-linux.workflow-actionlint` passed; `git diff --check -- ` passed. A direct `nix develop -c actionlint .github/workflows/release-sce.yml` check was attempted first but `actionlint` is not exposed in the dev shell. + - Context-sync classification: important workflow/release behavior change; root and release/distribution domain context updated to reflect `.github/workflows/release-sce.yml` Flatpak source-manifest asset upload wiring while leaving broader README/user-facing documentation to T04. + +- [x] T04: `Document Flatpak GitHub Release assets` (status:done) + - Task ID: T04 + - Goal: Update user-facing docs and durable context to describe the new GitHub Release Flatpak source-manifest asset workflow accurately. + - Boundaries (in/out of scope): In - update README/release-facing docs and current-state context to explain the Flatpak GitHub Release assets, how they differ from native archives and npm assets, and that Flatpak remains source-built with no Flathub automation. Out - implementation changes to release tooling/workflows, broad marketing copy, new install channels. + - Done when: Documentation tells users/contributors that GitHub Releases include `sce-v-flatpak-manifest.tar.gz` plus checksum/metadata, the tarball contains the Flathub-style source manifest and support files, and no docs imply a prebuilt Flatpak binary or automated Flathub publication exists. + - Verification notes (commands or checks): Static docs review; search README/context for stale current-state statements that GitHub Release Flatpak assets are out of scope; confirm remaining historical references are clearly historical or completed-plan evidence. + - Completed: 2026-06-22 + - Files changed: `README.md`, `context/plans/flatpak-github-release-assets.md` + - Evidence: README Flatpak section now describes GitHub Release source-manifest assets, lists the tarball/checksum/metadata asset names, names the packaged manifest/support files, and states the assets are not prebuilt Flatpak apps/bundles, OSTree repositories, Flathub submissions, or npm-consumed native release-manifest content; `git diff --check -- README.md` passed; stale exact wording search for active “GitHub Release Flatpak assets are out of scope/not part of scope” statements found only plan verification/history references. + - Context-sync result: verify-only localized docs update; `context/overview.md`, `context/architecture.md`, `context/glossary.md`, `context/patterns.md`, `context/context-map.md`, and release/Flatpak domain context already describe the implemented asset workflow, so no root/domain context edits were needed. + +- [x] T05: `Validate release asset flow and clean up` (status:done) + - Task ID: T05 + - Goal: Run final validation, remove temporary packaging outputs, and ensure durable context matches the implemented Flatpak GitHub Release asset flow. + - Boundaries (in/out of scope): In - full repository validation where practical, targeted Flatpak release app validation, Flatpak validation command evidence, workflow/docs/context consistency checks, cleanup of temporary release output directories, and final plan evidence. Out - publishing an actual GitHub Release, running Flathub submission, completing a full network-heavy Flatpak build unless explicitly needed and practical. + - Done when: Required checks pass or any blockers are documented with actionable follow-up; generated Flatpak release assets are proven to have the expected names/content/metadata; no temporary release packaging artifacts remain in the repository; context accurately describes the final current state. + - Verification notes (commands or checks): `nix run .#release-flatpak-package -- --version "$(tr -d '\n' < .version)" --out-dir `; inspect the emitted tarball/checksum/JSON; `nix run .#flatpak-validate -- --skip-optional-lint`; `nix run .#pkl-check-generated`; `nix flake check`; static search for stale Flatpak release-asset scope wording; cleanup temporary output directories. + - Completed: 2026-06-22 + - Evidence: + - `nix run .#release-flatpak-package -- --version 0.2.0 --out-dir `: emitted `sce-v0.2.0-flatpak-manifest.tar.gz` (37961 bytes), `sce-v0.2.0-flatpak-manifest.tar.gz.sha256`, and `sce-v0.2.0-flatpak.json` with expected fields (app_id, version, release_commit, manifest_name, checksum_sha256, packaged_files). Tarball contains `sce-v0.2.0-flatpak-manifest/` directory with `dev.crocoder.sce.yml`, `dev.crocoder.sce.metainfo.xml`, `cargo-sources.json`, and `git-host-bridge`. SHA-256 checksum `efb3e869fe69c452f91ce37f6c328ab718faf4666c7808644f22fdb8262766bd` verified against tarball. + - `nix run .#flatpak-validate -- --skip-optional-lint`: passed (`✔ Validation was successful.`) + - `nix run .#pkl-check-generated`: passed (`Generated outputs are up to date.`) + - `nix flake check`: all checks passed (92/92 CLI tests, clippy, fmt, flatpak-static-validation, pkl-parity, workflow-actionlint, all npm/config-lib JS checks, integrations-install checks) + - Static stale-scope wording search: clean; all Flatpak "out of scope" / "not a prebuilt" matches in current-state context are correct contract-boundary descriptions; remaining matches are historical/completed-plan references only. + - Temporary output directory cleaned up. + - Context-sync classification: verify-only; no root context edits expected since all context files already describe the implemented current state. + +## Validation Report + +### Commands run +- `nix run .#release-flatpak-package -- --version 0.2.0 --out-dir ` → exit 0. Emitted `sce-v0.2.0-flatpak-manifest.tar.gz`, `sce-v0.2.0-flatpak-manifest.tar.gz.sha256`, `sce-v0.2.0-flatpak.json`. Checksum verified (`efb3e869fe69c452f91ce37f6c328ab718faf4666c7808644f22fdb8262766bd`). +- `nix run .#flatpak-validate -- --skip-optional-lint` → exit 0. Validation successful. +- `nix run .#pkl-check-generated` → exit 0. Generated outputs are up to date. +- `nix flake check` → exit 0. All checks passed: + - cli-tests: 92/92 passed + - cli-clippy: passed (no new warnings) + - cli-fmt: passed + - flatpak-static-validation: passed + - pkl-parity: passed + - workflow-actionlint: passed + - npm-bun-tests, npm-biome-check, npm-biome-format: passed + - config-lib-bun-tests, config-lib-biome-check, config-lib-biome-format: passed + - integrations-install-tests, integrations-install-clippy, integrations-install-fmt: passed + +### Temporary scaffolding +- Temporary release output directory cleaned up after inspection. +- No debug code or temporary artifacts remain in the repository. + +### Context verification +- All root context files (`overview.md`, `architecture.md`, `glossary.md`, `patterns.md`, `context-map.md`) match code truth. +- Static stale-scope wording review: clean. All "out of scope" / "not a prebuilt" matches in current-state context files are correct contract-boundary descriptions; remaining matches are historical/completed-plan references only. +- Domain files (`cli-first-install-channels-contract.md`, `cli-release-artifact-contract.md`) correctly describe the implemented asset workflow. +- Feature is discoverable from `context/context-map.md`. + +### Success-criteria verification +- [x] Root-flake release app exists: `nix run .#release-flatpak-package -- --version --out-dir ` (T02) +- [x] Version parity validation enforced: checked `.version`, `cli/Cargo.toml`, `npm/package.json`, Flatpak AppStream (T02, re-verified T05) +- [x] Deterministic tarball with expected content: `sce-v-flatpak-manifest/` directory containing `dev.crocoder.sce.yml`, `dev.crocoder.sce.metainfo.xml`, `cargo-sources.json`, `git-host-bridge` (T02, re-verified T05) +- [x] Packaged manifest pins release commit without mutating checked-in file (T02, re-verified T05) +- [x] SHA-256 checksum file and JSON metadata emitted (T02, re-verified T05) +- [x] `.github/workflows/release-sce.yml` builds from `dist/flatpak` and uploads Flatpak assets (T03) +- [x] Documentation states Flatpak assets are source-built packaging metadata, not prebuilt binaries (T04) +- [x] No stale "out of scope" wording remains in current-state context (T05) +- [x] Temporary output directories cleaned up (T05) + +### Residual risks +- None identified. All acceptance criteria are met; Flatpak source-built semantics are preserved; no Flathub automation, prebuilt binaries, or release-version bumping was introduced. + +## Open questions + +- None. The user clarified that this plan should cover GitHub Release Flatpak assets only, not Flathub publication automation. diff --git a/context/sce/cli-first-install-channels-contract.md b/context/sce/cli-first-install-channels-contract.md index 74a52f59..f8c0787b 100644 --- a/context/sce/cli-first-install-channels-contract.md +++ b/context/sce/cli-first-install-channels-contract.md @@ -1,6 +1,6 @@ # SCE CLI Install Channel Contract -This file captures the current install/distribution contract for the `sce` CLI. It began with the first-wave `Nix`/`Cargo`/`npm` channel contract from `context/plans/sce-cli-first-install-channels.md` task `T01`; the current active model also approves Flatpak as an official source-built channel through `context/plans/nix-orchestrated-flatpak.md` task `T01`. +This file captures the current install/distribution contract for the `sce` CLI. It began with the first-wave `Nix`/`Cargo`/`npm` channel contract from `context/plans/sce-cli-first-install-channels.md` task `T01`; the current active model also approves Flatpak as an official source-built channel through `context/plans/nix-orchestrated-flatpak.md` task `T01` and approves GitHub Release Flatpak source-manifest assets through `context/plans/flatpak-github-release-assets.md` task `T01`. ## Canonical naming @@ -25,12 +25,12 @@ No other install channels are in scope for the current implementation stage. - Nix-managed build/release entrypoints remain the required build source for existing binary release automation. - Nix may also orchestrate Flatpak tooling, local source overrides, validation, and local builds, but the Flatpak package itself must build `sce` from source inside Flatpak. - Repo-root `.version` is the canonical checked-in release version authority for the Nix, Cargo, npm, and release-artifact surfaces. -- GitHub Releases are the canonical publication surface for release archives and manifest/checksum assets produced for the version declared in `.version`. +- GitHub Releases are the canonical publication surface for release archives, native release manifest/checksum assets, npm package assets, and approved Flatpak source-manifest package assets produced for the version declared in `.version`. - `npm` consumes release artifacts produced by Nix-managed build/release flows. - `Cargo` is a first-class supported install path and its publish metadata should stay aligned to `.version` without workflow-side version bumping. - npm registry publication should also consume the checked-in package version aligned to `.version` without workflow-side version bumping. -- Flatpak is source-built and must not consume `nix build .#sce`, GitHub Release archives, npm native binaries, or any other prebuilt `sce` artifact. -- The first Flatpak iteration is Flathub-ready packaging plus Nix-backed local build/check tooling and docs only; CI publishing, automatic Flathub submission, GitHub Release Flatpak assets, and release-version bumping are not part of the current scope. +- Flatpak is source-built and must not consume `nix build .#sce`, native GitHub Release binary archives, npm native binaries, or any other prebuilt `sce` artifact. +- GitHub Release Flatpak assets include source-manifest package assets and source-built `.flatpak` bundle assets for the source-built `dev.crocoder.sce` Flatpak channel. Automatic Flathub submission, prebuilt (non-source-built) Flatpak binaries/bundles, OSTree repositories, release-version bumping, and Flatpak publication beyond the approved GitHub Release asset upload remain out of scope. - `Homebrew` can return in a later plan stage, but it is not part of current code truth. ## Flatpak source-build contract @@ -51,15 +51,40 @@ No other install channels are in scope for the current implementation stage. - The host Git bridge source lives at `packaging/flatpak/git-host-bridge`; the manifest installs it as `/app/bin/git`. - The current runtime permissions are `--share=network`, `--filesystem=home`, `--talk-name=org.freedesktop.Flatpak`, and `--talk-name=org.freedesktop.secrets`. +## Flatpak GitHub Release source-manifest assets + +- The approved Flatpak GitHub Release asset set is source-manifest packaging metadata, not a prebuilt `sce` binary, `.flatpak` bundle, OSTree repository, or Flathub publication. +- The implemented local release packaging entrypoint is `nix run .#release-flatpak-package -- --version --out-dir ` on Linux; it delegates to `packaging/flatpak/sce-flatpak.sh release-package`. +- The asset names are `sce-v-flatpak-manifest.tar.gz`, `sce-v-flatpak-manifest.tar.gz.sha256`, and `sce-v-flatpak.json`. +- The tarball contains a deterministic top-level `sce-v-flatpak-manifest/` directory with `dev.crocoder.sce.yml`, `dev.crocoder.sce.metainfo.xml`, `cargo-sources.json`, and `git-host-bridge`. +- The packaged manifest pins its git source to the release commit in the staged package copy without mutating the checked-in `packaging/flatpak/dev.crocoder.sce.yml` file. +- Flatpak release asset packaging uses repo-root `.version` as the checked-in version authority, refuses version drift against `cli/Cargo.toml`, `npm/package.json`, and Flatpak AppStream release metadata, and fails when a release commit cannot be resolved from a git checkout. +- `.github/workflows/release-sce.yml` runs `nix run .#release-flatpak-package -- --version --out-dir dist/flatpak` during GitHub Release assembly and uploads `dist/flatpak/*.tar.gz`, `dist/flatpak/*.sha256`, and `dist/flatpak/*.json` alongside existing CLI/npm assets. +- Flatpak source-manifest assets are separate from the signed native `sce-v-release-manifest.json` consumed by npm. + +## Flatpak GitHub Release bundle assets + +- The approved Flatpak GitHub Release asset set now also includes source-built `.flatpak` bundle assets alongside source-manifest packaging metadata. +- The bundle is built from source inside Flatpak using `flatpak-builder` + `flatpak build-bundle`, not from a Nix-built or pre-compiled binary. +- Asset names per architecture: + - `sce-v-x86_64.flatpak` + `.sha256` + `.json` + - `sce-v-aarch64.flatpak` + `.sha256` + `.json` +- The JSON metadata includes `asset_type: flatpak-bundle`, architecture field (`x86_64` / `aarch64`), and app ID `dev.crocoder.sce`. +- The bundle is a source-built Flatpak app for direct install, not a prebuilt binary or Flathub submission. +- Source-built `.flatpak` bundles coexist with existing source-manifest tarball assets; the source-manifest packaging metadata remains unchanged. +- The `release-bundle` command (`packaging/flatpak/sce-flatpak.sh release-bundle`) and GitHub workflow upload for these assets are implemented (`.github/workflows/release-sce-linux.yml` / `release-sce-linux-arm.yml` build and upload; `release-sce.yml` assembles and publishes with the GitHub Release). + ## Implemented Nix-backed Flatpak tooling surface -- `packaging/flatpak/sce-flatpak.sh` owns local Flatpak orchestration for this repo: lightweight validation, generated local checkout-source manifests, and opt-in `flatpak-builder` execution. +- `packaging/flatpak/sce-flatpak.sh` owns local Flatpak orchestration for this repo: lightweight validation, generated local checkout-source manifests, opt-in `flatpak-builder` execution, and deterministic Flatpak source-manifest release packaging. - Linux flake apps expose that script as: - `nix run .#flatpak-validate` for static source-build checks, local-manifest generation checks, and `appstreamcli validate --pedantic --no-net`. - `nix run .#flatpak-local-manifest` for generating a temporary manifest that replaces the release git source with a Flatpak `type: dir` source pointed at the current checkout. - `nix run .#flatpak-build -- --help` / `nix run .#flatpak-build -- ...` for explicit local `flatpak-builder` source builds from that generated local manifest. + - `nix run .#release-flatpak-package -- --version --out-dir ` for deterministic GitHub Release source-manifest tarball/checksum/JSON assets. + - `nix run .#release-flatpak-bundle -- --version --arch --out-dir ` for deterministic GitHub Release source-built `.flatpak` bundle/checksum/JSON assets. - `checks..flatpak-static-validation` runs the lightweight validation path during default `nix flake check`; it does not run a full Flatpak build or require network access. -- The Linux dev shell includes `appstreamcli`, `flatpak`, and `flatpak-builder`, and its banner lists the Flatpak flake apps alongside existing repo app entrypoints. +- The Linux dev shell includes `appstreamcli`, `flatpak`, and `flatpak-builder`, and its banner lists the Flatpak local/release flake apps alongside existing repo app entrypoints. - The checked-in release manifest remains Flathub-style and source-built; Nix orchestration only supplies tools and generated local manifests and must not provide a prebuilt `sce` binary to the Flatpak package. ## Explicitly out of scope in this phase @@ -70,12 +95,13 @@ No other install channels are in scope for the current implementation stage. - AppImage - Other Linux package-manager specific channels not listed above -## Implementation implications for later tasks +## Implementation implications -- Release assets must be named and published for `sce`. +- Release assets must be named and published for `sce`, including the Flatpak source-manifest asset names emitted by `release-flatpak-package` and uploaded by `.github/workflows/release-sce.yml`. - GitHub release packaging must consume the checked-in `.version` value instead of inventing a semver bump during workflow execution. - Cargo and npm registry publication belong to separate downstream publish stages rather than the GitHub release-packaging job. - Flatpak packaging tasks must preserve source-built semantics and the release-source-plus-local-override model instead of wrapping existing binary release artifacts. -- Flatpak publication automation remains explicitly deferred until a later approved plan. +- Flatpak GitHub Release asset tasks must package only the source manifest/support files, not generated binaries or bundles. +- Flatpak publication automation beyond GitHub Release source-manifest asset uploads remains explicitly deferred until a later approved plan. - Unsupported channels in older docs should be removed or explicitly deferred rather than implied as active support. - Later packaging tasks should implement the contract above rather than redefining channel scope per channel. diff --git a/context/sce/cli-release-artifact-contract.md b/context/sce/cli-release-artifact-contract.md index e2200fd6..9f31bfff 100644 --- a/context/sce/cli-release-artifact-contract.md +++ b/context/sce/cli-release-artifact-contract.md @@ -14,6 +14,31 @@ This file captures the current shared release artifact foundation plus the appro - `sce-v-SHA256SUMS` - `nix run .#release-manifest` signs the merged release manifest with a non-repo private key supplied via `SCE_RELEASE_MANIFEST_SIGNING_KEY` or `--signing-key-file `. +## Implemented Flatpak source-manifest artifact set + +- Flatpak GitHub Release assets are approved as source-manifest packaging metadata for the source-built `dev.crocoder.sce` Flatpak channel. +- `nix run .#release-flatpak-package -- --version --out-dir ` is the Linux root-flake app that emits the Flatpak asset set from checked-in `packaging/flatpak/` source. +- The approved Flatpak asset names are: + - `sce-v-flatpak-manifest.tar.gz` + - `sce-v-flatpak-manifest.tar.gz.sha256` + - `sce-v-flatpak.json` +- The Flatpak tarball contains a deterministic top-level `sce-v-flatpak-manifest/` directory with `dev.crocoder.sce.yml`, `dev.crocoder.sce.metainfo.xml`, `cargo-sources.json`, and `git-host-bridge`. +- The staged packaged manifest pins the release git source to the release commit without mutating the checked-in Flatpak manifest. +- The metadata JSON describes `asset_type`, `app_id`, `version`, `release_commit`, `manifest_name`, `package_file`, `checksum_file`, `checksum_sha256`, `packaged_support_files`, and `packaged_files`. +- Flatpak source-manifest assets are not native binary archives and are not included in the signed native `sce-v-release-manifest.json` consumed by npm. +- The Flatpak source-manifest asset set does not publish a prebuilt `sce` binary, `.flatpak` bundle, OSTree repository, AppImage, `.deb`, `.rpm`, AUR package, Homebrew asset, or Flathub submission. Source-built `.flatpak` bundle assets are published in a separate approved asset set (see below). + +## Implemented Flatpak bundle artifact set + +- Flatpak GitHub Release assets now also include source-built `.flatpak` bundle assets alongside source-manifest packaging metadata. +- The bundle is built from source inside Flatpak using `flatpak-builder` + `flatpak build-bundle`, not from a Nix-built or pre-compiled binary. +- Approved bundle asset names per architecture: + - `sce-v-x86_64.flatpak` + `.sha256` + `.json` + - `sce-v-aarch64.flatpak` + `.sha256` + `.json` +- The JSON metadata describes `asset_type: flatpak-bundle`, architecture field (`x86_64` / `aarch64`), app ID `dev.crocoder.sce`, version, and SHA-256 checksum. +- Bundle assets are separate from native binary release archives, the signed native release manifest consumed by npm, and the existing Flatpak source-manifest packaging assets. +- The release-bundle command (`packaging/flatpak/sce-flatpak.sh release-bundle`) is exposed as `nix run .#release-flatpak-bundle -- --version --arch --out-dir `. GitHub workflow upload for these assets is implemented (`.github/workflows/release-sce-linux.yml` / `release-sce-linux-arm.yml` build and upload; `release-sce.yml` assembles and publishes with the GitHub Release). + ## Archive contents - Each archive contains a deterministic top-level directory named `sce-v-/`. @@ -28,21 +53,24 @@ This file captures the current shared release artifact foundation plus the appro - Tarball creation uses stable file ordering plus fixed ownership and mtime metadata. - Gzip output is emitted with deterministic headers. - Checksum files use SHA-256 and the standard `` line format. +- Flatpak source-manifest packaging uses the same stable tar/gzip/checksum conventions while staging only release manifest/support files, not build outputs. - Manifest signatures are detached base64-encoded RSA-SHA256 signatures over the exact emitted `sce-v-release-manifest.json` bytes. ## Workflow topology -- GitHub Releases are the canonical publication surface for `sce` release archives, checksums, metadata fragments, and merged release-manifest assets. +- GitHub Releases are the canonical publication surface for `sce` release archives, checksums, metadata fragments, merged release-manifest assets, npm package assets, and approved Flatpak source-manifest assets. - Repo-root `.version` is the canonical checked-in release version source for release tags, archive names, and packaged metadata across the release flow. - Release packaging consumes the checked-in version directly; workflow-side semver bump generation is not part of the current contract. - Cargo/crates.io and npm registry publication are separate downstream publish stages and are not part of the canonical GitHub release artifact assembly job. - `.github/workflows/release-sce.yml` remains the CLI release orchestrator that assembles GitHub release assets from the reusable platform build workflows. - The release orchestrator injects the non-repo manifest-signing private key through the `SCE_RELEASE_MANIFEST_SIGNING_KEY` secret when assembling release-level metadata. +- The release orchestrator also runs `nix run .#release-flatpak-package -- --version --out-dir dist/flatpak` and uploads `dist/flatpak/*.tar.gz`, `dist/flatpak/*.sha256`, and `dist/flatpak/*.json` to the GitHub Release. - Manual GitHub release dispatch resolves the tag from checked-in `.version` and refuses to create the tag when `.version`, `cli/Cargo.toml`, and `npm/package.json` are not already aligned. - Tag-triggered release execution also refuses to proceed when the pushed tag does not equal `v<.version>` or when checked-in Cargo/npm package metadata drift from `.version`. - `nix run .#release-artifacts` fails fast when the requested `--version` disagrees with `.version`, `cli/Cargo.toml`, `npm/package.json`, or the built CLI `sce version` output. +- `nix run .#release-flatpak-package` fails fast when the requested `--version` disagrees with `.version`, `cli/Cargo.toml`, `npm/package.json`, or Flatpak AppStream release metadata, and also fails when it cannot resolve a release commit from a git checkout. - `nix run .#release-artifacts` also rejects host OS/architecture pairs outside the current three-target release matrix; macOS Intel (`Darwin:x86_64`) is no longer a supported current-platform packaging host. -- The release orchestrator passes the resolved checked-in version through to the platform builds, merged release-manifest assembly, and npm tarball packaging without mutating package versions during workflow execution. +- The release orchestrator passes the resolved checked-in version through to the platform builds, merged release-manifest assembly, npm tarball packaging, and Flatpak source-manifest packaging without mutating package versions during workflow execution. - Platform builds are split into separate reusable workflow files: - `.github/workflows/release-sce-linux.yml` - `.github/workflows/release-sce-linux-arm.yml` @@ -67,5 +95,5 @@ This file captures the current shared release artifact foundation plus the appro - The implemented npm channel consumes this artifact naming and manifest/checksum shape rather than inventing a channel-specific archive format. - The implemented npm channel also depends on the published `sce-v-release-manifest.json.sig` asset so manifest-provided checksums are only trusted after signature verification. - Additional binary-distribution install channels should reuse this artifact contract unless a later decision explicitly supersedes it. -- Flatpak is the current approved exception to binary-artifact reuse: the Flatpak package for application ID `dev.crocoder.sce` is source-built inside Flatpak, uses a release-source manifest plus a Nix-generated local checkout-source manifest/override for local builds, and must not consume Nix-built, GitHub Release, npm native, or other prebuilt `sce` artifacts. -- The current Flatpak iteration does not publish GitHub Release Flatpak assets or add CI/Flathub publication automation. +- Flatpak is the current approved exception to binary-artifact reuse: the Flatpak package for application ID `dev.crocoder.sce` is source-built inside Flatpak, uses a release-source manifest plus a Nix-generated local checkout-source manifest/override for local builds, and must not consume Nix-built, native GitHub Release binary archives, npm native, or other prebuilt `sce` artifacts. +- GitHub Release Flatpak assets include source-manifest package assets and source-built `.flatpak` bundle assets, both uploaded by the CLI release workflow; automatic Flathub submission and prebuilt (non-source-built) Flatpak binary/bundle assets remain out of scope. diff --git a/flake.nix b/flake.nix index 34759111..3bcb0a7f 100644 --- a/flake.nix +++ b/flake.nix @@ -798,6 +798,8 @@ [ pkgs.coreutils pkgs.git + pkgs.gnutar + pkgs.gzip pkgs.python3 ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ @@ -838,6 +840,22 @@ ''; }; + releaseFlatpakPackageApp = pkgs.writeShellApplication { + name = "release-flatpak-package"; + runtimeInputs = [ flatpakToolApp ]; + text = '' + exec sce-flatpak release-package "$@" + ''; + }; + + releaseFlatpakBundleApp = pkgs.writeShellApplication { + name = "release-flatpak-bundle"; + runtimeInputs = [ flatpakToolApp ]; + text = '' + exec sce-flatpak release-bundle "$@" + ''; + }; + flatpakStaticValidationCheck = pkgs.runCommand "flatpak-static-validation" { nativeBuildInputs = [ flatpakToolApp ]; @@ -1207,6 +1225,22 @@ description = "Build the sce Flatpak from the current checkout with flatpak-builder"; }; }; + + release-flatpak-package = { + type = "app"; + program = "${releaseFlatpakPackageApp}/bin/release-flatpak-package"; + meta = { + description = "Build Flatpak source-manifest GitHub Release assets"; + }; + }; + + release-flatpak-bundle = { + type = "app"; + program = "${releaseFlatpakBundleApp}/bin/release-flatpak-bundle"; + meta = { + description = "Build Flatpak bundle GitHub Release assets"; + }; + }; }; devShells.default = pkgs.mkShell { @@ -1265,6 +1299,8 @@ echo "- flatpak-validate: nix run .#flatpak-validate" echo "- flatpak-local-manifest: nix run .#flatpak-local-manifest" echo "- flatpak-build: nix run .#flatpak-build -- --help" + echo "- release-flatpak-package: nix run .#release-flatpak-package -- --help" + echo "- release-flatpak-bundle: nix run .#release-flatpak-bundle -- --help" ''} ''; }; diff --git a/packaging/flatpak/sce-flatpak.sh b/packaging/flatpak/sce-flatpak.sh index 46fc1e57..cd747049 100755 --- a/packaging/flatpak/sce-flatpak.sh +++ b/packaging/flatpak/sce-flatpak.sh @@ -13,6 +13,8 @@ Commands: validate Run lightweight Flatpak packaging validation prepare-local-manifest Generate a local-checkout Flatpak manifest build Build the Flatpak from the local checkout + release-package Package Flatpak source-manifest release assets + release-bundle Build and bundle Flatpak release assets validate options: --repo-root Repository checkout to validate (default: git root or cwd) @@ -33,6 +35,17 @@ build options: --no-force-clean Do not pass --force-clean to flatpak-builder -- Extra arguments forwarded to flatpak-builder +release-package options: + --version Release version to package; must match checked-in metadata + --out-dir Directory for release tarball, checksum, and JSON metadata + --repo-root Repository checkout to package (default: git root or cwd) + +release-bundle options: + --version Release version to bundle; must match checked-in metadata + --arch Target architecture (default: host arch via uname -m) + --out-dir Directory for bundle, checksum, and JSON metadata + --repo-root Repository checkout to build from (default: git root or cwd) + The generated local manifest replaces the checked-in release git source with a Flatpak type: dir source pointed at the checkout. It still runs the manifest's Cargo source build inside Flatpak and does not consume a Nix-built sce binary. @@ -237,6 +250,128 @@ if errors: PY } +resolve_release_commit() { + local repo_root="$1" + local release_commit + + if ! release_commit="$(git -C "${repo_root}" rev-parse --verify "HEAD^{commit}" 2>/dev/null)"; then + die "could not resolve release commit from repository checkout: ${repo_root}" + fi + + if [[ ! "${release_commit}" =~ ^[0-9a-f]{40}$ ]]; then + die "resolved release commit is not a full 40-character git SHA: ${release_commit}" + fi + + printf '%s\n' "${release_commit}" +} + +validate_release_version_parity() { + local repo_root="$1" + local version="$2" + + python3 - "${repo_root}" "${version}" <<'PY' +import json +import pathlib +import re +import sys +import xml.etree.ElementTree as ET + +repo_root = pathlib.Path(sys.argv[1]) +version = sys.argv[2] +app_id = "dev.crocoder.sce" +errors = [] + +def require(condition, message): + if not condition: + errors.append(message) + +version_path = repo_root / ".version" +cargo_toml_path = repo_root / "cli" / "Cargo.toml" +npm_package_path = repo_root / "npm" / "package.json" +metainfo_path = repo_root / "packaging" / "flatpak" / f"{app_id}.metainfo.xml" + +try: + checked_in_version = version_path.read_text(encoding="utf-8").strip() +except OSError as error: + raise SystemExit(f"could not read {version_path}: {error}") from error + +try: + cargo_toml = cargo_toml_path.read_text(encoding="utf-8") +except OSError as error: + raise SystemExit(f"could not read {cargo_toml_path}: {error}") from error + +cargo_match = re.search(r'(?m)^version = "([^"]+)"$', cargo_toml) +require(cargo_match is not None, "cli/Cargo.toml package version is missing") +cargo_version = cargo_match.group(1) if cargo_match else "" + +try: + npm_version = json.loads(npm_package_path.read_text(encoding="utf-8")).get("version", "") +except (OSError, json.JSONDecodeError) as error: + raise SystemExit(f"could not parse {npm_package_path}: {error}") from error + +try: + metainfo_root = ET.parse(metainfo_path).getroot() +except (OSError, ET.ParseError) as error: + raise SystemExit(f"could not parse {metainfo_path}: {error}") from error + +release_versions = [ + release.attrib.get("version", "") + for release in metainfo_root.findall("./releases/release") +] +require(bool(release_versions), "Flatpak metainfo release metadata is missing") +flatpak_version = release_versions[0] if release_versions else "" + +require(version == checked_in_version, f"requested release version {version} does not match .version {checked_in_version}") +require(version == cargo_version, f"cli/Cargo.toml version {cargo_version} does not match release version {version}") +require(version == npm_version, f"npm/package.json version {npm_version} does not match release version {version}") +require(version == flatpak_version, f"Flatpak metainfo release version {flatpak_version} does not match release version {version}") + +if errors: + for error in errors: + print(f"Flatpak release version validation failed: {error}", file=sys.stderr) + raise SystemExit(1) +PY +} + +generate_release_manifest() { + local repo_root="$1" + local release_commit="$2" + local out_dir="$3" + local flatpak_dir + flatpak_dir="$(flatpak_dir_for "${repo_root}")" + + require_file "${flatpak_dir}/${MANIFEST_NAME}" + + mkdir -p "${out_dir}" + + python3 - "${release_commit}" "${flatpak_dir}/${MANIFEST_NAME}" "${out_dir}/${MANIFEST_NAME}" <<'PY' +import pathlib +import re +import sys + +release_commit = sys.argv[1] +source_manifest = pathlib.Path(sys.argv[2]) +target_manifest = pathlib.Path(sys.argv[3]) + +if not re.fullmatch(r"[0-9a-f]{40}", release_commit): + raise SystemExit("release commit must be a full 40-character lowercase git SHA") + +text = source_manifest.read_text(encoding="utf-8") +release_source = re.compile( + r"(?m)^( - type: git\n" + r" url: https://github\.com/crocoder-dev/shared-context-engineering\.git\n" + r" commit: )[0-9a-f]{40}(\n)" +) +text, count = release_source.subn(rf"\g<1>{release_commit}\2", text, count=1) +if count != 1: + raise SystemExit("could not rewrite release git source commit in staged manifest") + +target_manifest.write_text(text, encoding="utf-8") +PY + + printf '%s/%s\n' "${out_dir}" "${MANIFEST_NAME}" +} + cmd_validate() { local repo_root_override="" local skip_optional_lint=0 @@ -436,6 +571,301 @@ cmd_build() { exec flatpak-builder "${builder_args[@]}" } +cmd_release_package() { + local repo_root_override="" + local version="" + local out_dir="" + + while [ $# -gt 0 ]; do + case "$1" in + --repo-root) + repo_root_override="${2:-}" + [ -n "${repo_root_override}" ] || die "--repo-root requires a path" + shift 2 + ;; + --version) + version="${2:-}" + [ -n "${version}" ] || die "--version requires a semver value" + shift 2 + ;; + --out-dir) + out_dir="${2:-}" + [ -n "${out_dir}" ] || die "--out-dir requires a path" + shift 2 + ;; + --help|-h) + usage + exit 0 + ;; + *) + die "unknown release-package argument: $1" + ;; + esac + done + + if [ -z "${version}" ] || [ -z "${out_dir}" ]; then + usage >&2 + exit 1 + fi + + local repo_root + repo_root="$(resolve_repo_root "${repo_root_override}")" + local flatpak_dir + flatpak_dir="$(flatpak_dir_for "${repo_root}")" + + require_file "${flatpak_dir}/${MANIFEST_NAME}" + require_file "${flatpak_dir}/${METAINFO_NAME}" + require_file "${flatpak_dir}/git-host-bridge" + require_file "${flatpak_dir}/cargo-sources.json" + + validate_release_version_parity "${repo_root}" "${version}" + run_static_checks "${repo_root}" + + local release_commit + release_commit="$(resolve_release_commit "${repo_root}")" + + mkdir -p "${out_dir}" + + local tmp_dir + tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/sce-flatpak-release.XXXXXX")" + cleanup() { + if [ -n "${tmp_dir:-}" ]; then + rm -rf "${tmp_dir}" + fi + } + trap cleanup EXIT + + local package_root="sce-v${version}-flatpak-manifest" + local package_name="${package_root}.tar.gz" + local checksum_name="${package_name}.sha256" + local metadata_name="sce-v${version}-flatpak.json" + local stage_dir="${tmp_dir}/${package_root}" + local package_path="${out_dir}/${package_name}" + local checksum_path="${out_dir}/${checksum_name}" + local metadata_path="${out_dir}/${metadata_name}" + + mkdir -p "${stage_dir}" + generate_release_manifest "${repo_root}" "${release_commit}" "${stage_dir}" >/dev/null + cp "${flatpak_dir}/${METAINFO_NAME}" "${stage_dir}/${METAINFO_NAME}" + cp "${flatpak_dir}/cargo-sources.json" "${stage_dir}/cargo-sources.json" + cp "${flatpak_dir}/git-host-bridge" "${stage_dir}/git-host-bridge" + + chmod 0644 "${stage_dir}/${MANIFEST_NAME}" "${stage_dir}/${METAINFO_NAME}" "${stage_dir}/cargo-sources.json" + chmod 0755 "${stage_dir}/git-host-bridge" + + tar \ + --sort=name \ + --mtime='UTC 1970-01-01' \ + --owner=0 \ + --group=0 \ + --numeric-owner \ + -C "${tmp_dir}" \ + -cf - "${package_root}" | gzip -n > "${package_path}" + + local checksum + checksum="$(sha256sum "${package_path}" | cut -d ' ' -f 1)" + printf '%s %s\n' "${checksum}" "${package_name}" > "${checksum_path}" + + python3 - \ + "${metadata_path}" \ + "${version}" \ + "${release_commit}" \ + "${package_name}" \ + "${checksum_name}" \ + "${checksum}" \ + <<'PY' +import json +import pathlib +import sys + +metadata_path = pathlib.Path(sys.argv[1]) +version = sys.argv[2] +release_commit = sys.argv[3] +package_name = sys.argv[4] +checksum_name = sys.argv[5] +checksum = sys.argv[6] + +manifest_name = "dev.crocoder.sce.yml" +support_files = [ + "dev.crocoder.sce.metainfo.xml", + "cargo-sources.json", + "git-host-bridge", +] +metadata = { + "asset_type": "flatpak-source-manifest", + "app_id": "dev.crocoder.sce", + "version": version, + "release_commit": release_commit, + "manifest_name": manifest_name, + "package_file": package_name, + "checksum_file": checksum_name, + "checksum_sha256": checksum, + "packaged_support_files": support_files, + "packaged_files": [manifest_name, *support_files], +} +metadata_path.write_text(json.dumps(metadata, indent=2) + "\n", encoding="utf-8") +PY + + rm -rf "${tmp_dir}" + trap - EXIT + + printf 'Built Flatpak source-manifest release assets:\n' + printf ' %s\n' "${package_path}" + printf ' %s\n' "${checksum_path}" + printf ' %s\n' "${metadata_path}" +} + +cmd_release_bundle() { + local repo_root_override="" + local version="" + local arch="" + local out_dir="" + + while [ $# -gt 0 ]; do + case "$1" in + --repo-root) + repo_root_override="${2:-}" + [ -n "${repo_root_override}" ] || die "--repo-root requires a path" + shift 2 + ;; + --version) + version="${2:-}" + [ -n "${version}" ] || die "--version requires a semver value" + shift 2 + ;; + --arch) + arch="${2:-}" + [ -n "${arch}" ] || die "--arch requires an architecture value" + shift 2 + ;; + --out-dir) + out_dir="${2:-}" + [ -n "${out_dir}" ] || die "--out-dir requires a path" + shift 2 + ;; + --help|-h) + usage + exit 0 + ;; + *) + die "unknown release-bundle argument: $1" + ;; + esac + done + + if [ -z "${version}" ] || [ -z "${out_dir}" ]; then + usage >&2 + exit 1 + fi + + local repo_root + repo_root="$(resolve_repo_root "${repo_root_override}")" + local flatpak_dir + flatpak_dir="$(flatpak_dir_for "${repo_root}")" + + require_file "${flatpak_dir}/${MANIFEST_NAME}" + require_file "${flatpak_dir}/${METAINFO_NAME}" + require_file "${flatpak_dir}/git-host-bridge" + require_file "${flatpak_dir}/cargo-sources.json" + + validate_release_version_parity "${repo_root}" "${version}" + run_static_checks "${repo_root}" + + # Resolve architecture (default to host arch) + if [ -z "${arch}" ]; then + arch="$(uname -m)" + fi + + # Validate arch is supported + case "${arch}" in + x86_64|aarch64) + ;; + *) + die "unsupported architecture: ${arch} (supported: x86_64, aarch64)" + ;; + esac + + require_command "flatpak-builder" "Use 'nix run .#flatpak-build' or enter 'nix develop'." + require_command "flatpak" "Install flatpak or enter 'nix develop'." + + mkdir -p "${out_dir}" + + local tmp_dir + tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/sce-flatpak-release-bundle.XXXXXX")" + cleanup() { + if [ -n "${tmp_dir:-}" ]; then + rm -rf "${tmp_dir}" + fi + } + trap cleanup EXIT + + # Generate local manifest into temp staging + local local_manifest + local_manifest="$(generate_local_manifest "${repo_root}" "${tmp_dir}/manifest")" + validate_generated_local_manifest "${repo_root}" "${local_manifest}" + + local build_dir="${tmp_dir}/build" + local bundle_name="sce-v${version}-${arch}.flatpak" + local bundle_path="${out_dir}/${bundle_name}" + local checksum_name="${bundle_name}.sha256" + local checksum_path="${out_dir}/${checksum_name}" + local metadata_name="sce-v${version}-${arch}.json" + local metadata_path="${out_dir}/${metadata_name}" + + # Build Flatpak from source (no --install) + printf 'Building %s for %s from local checkout source: %s\n' "${APP_ID}" "${arch}" "${repo_root}" + flatpak-builder --force-clean --arch="${arch}" "${build_dir}" "${local_manifest}" + + # Create bundle from the build repository + printf 'Creating Flatpak bundle: %s\n' "${bundle_path}" + flatpak build-bundle --arch="${arch}" "${build_dir}" "${bundle_path}" "${APP_ID}" + + # Compute SHA-256 checksum + local checksum + checksum="$(sha256sum "${bundle_path}" | cut -d ' ' -f 1)" + printf '%s %s\n' "${checksum}" "${bundle_name}" > "${checksum_path}" + + # Generate JSON metadata + python3 - \ + "${metadata_path}" \ + "${version}" \ + "${arch}" \ + "${bundle_name}" \ + "${checksum_name}" \ + "${checksum}" \ + <<'PY' +import json +import pathlib +import sys + +metadata_path = pathlib.Path(sys.argv[1]) +version = sys.argv[2] +arch = sys.argv[3] +bundle_name = sys.argv[4] +checksum_name = sys.argv[5] +checksum = sys.argv[6] + +metadata = { + "asset_type": "flatpak-bundle", + "app_id": "dev.crocoder.sce", + "version": version, + "architecture": arch, + "bundle_file": bundle_name, + "checksum_file": checksum_name, + "checksum_sha256": checksum, +} +metadata_path.write_text(json.dumps(metadata, indent=2) + "\n", encoding="utf-8") +PY + + rm -rf "${tmp_dir}" + trap - EXIT + + printf 'Built Flatpak bundle release assets:\n' + printf ' %s\n' "${bundle_path}" + printf ' %s\n' "${checksum_path}" + printf ' %s\n' "${metadata_path}" +} + main() { local command="${1:-}" if [ -z "${command}" ]; then @@ -454,6 +884,12 @@ main() { build) cmd_build "$@" ;; + release-package) + cmd_release_package "$@" + ;; + release-bundle) + cmd_release_bundle "$@" + ;; --help|-h|help) usage ;;