Repository navigation
feat(cli): add DEB and RPM system packages for Linux - #54024
zetneteork wants to merge 1 commit into
Conversation
Add .deb and .rpm system packages for amd64 and arm64, built and published alongside existing release assets (npm, Homebrew, AUR). Uses nfpm to cross-build 4 Linux packages per release from the existing signed CLI binaries. Packages include the binary at /usr/bin/opencode with ripgrep as a recommended dependency. New files: - packages/cli/packaging/nfpm.yaml: nfpm config for DEB/RPM - packages/cli/packaging/distribution.xml: macOS productbuild descriptor (reserved for future macOS .pkg support) - packages/cli/packaging/scripts/postinstall: macOS pkg postinstall - packages/cli/packaging/validate.sh: CI validation script - packages/cli/script/publish-system-packages.ts: packaging script Modified files: - packages/cli/script/publish.ts: invoke system package publisher - .github/workflows/publish.yml: install nfpm, validate packages - README.md: add DEB/RPM install commands Packages are uploaded to R2 and registered with the update service. CI validates package metadata, contents, and architecture after build. Closes anomalyco#45767
|
The following comment was made by an LLM, it may be inaccurate: |
There was a problem hiding this comment.
As written, this would break every run of the publish job, so it needs fixes before it can go in. I checked the type check, ran nfpm 2.41.1 with this nfpm.yaml, and ran validate.sh on the packages it built. Package contents, ripgrep Recommends and architecture mapping look right. Blocking issues are inline: the nfpm download URL returns 404, UpdateArtifact.upload is called with the wrong shape (fails tsgo and would throw mid-release), and validation fails for every beta version.
Other points:
distribution.xmlandscripts/postinstallaren't used anywhere. Please drop them and add them with the macOS.pkgwork.- The README edits go beyond this feature: they move scoop/choco and rename the "YOLO" line. The README also says the packages are on the GitHub releases page, but they are only uploaded to R2 (
opencode.ai/files/bin/<version>/). Thedpkg -i opencode_*_amd64.deblines also don't say where to get the file. - The validation step runs after
publish.tshas already uploaded the packages, so it can't stop a bad upload. Validating insidepublish-system-packages.tsbefore uploading would. - Both this and the desktop app's Linux packages are named
opencodeuntil #48654 lands. Please check the two can be installed together. distribution: "system-packages"is new to the update service and nothing reads it yet. Please confirm the publish API accepts it.
|
|
||
| - name: Install nfpm and rpm | ||
| run: | | ||
| curl -sfL https://github.com/goreleaser/nfpm/releases/download/v2.41.1/nfpm_2.41.1_linux_amd64.tar.gz | tar xz -C /usr/local/bin nfpm |
There was a problem hiding this comment.
This URL returns 404: the release asset is nfpm_2.41.1_Linux_x86_64.tar.gz. The step has no if: and runs before ./script/publish.ts, so it would fail every publish run, npm releases included. tar -C /usr/local/bin also needs sudo on the runner. Please pin a checksum for the download too.
| for (const pkg of packages) { | ||
| const filename = path.basename(pkg) | ||
| const result = await UpdateArtifact.upload({ | ||
| source: pkg, |
There was a problem hiding this comment.
UpdateArtifact.upload takes { version, files, dryRun } and returns a map of { url, sha256, size }. It has no source/key and no result.url. bun run typecheck in packages/cli fails here (TS2353). At runtime it throws on input.files.map, and by then npm, AUR and Homebrew have already published. Call it once with { version: Script.version, files: packages, dryRun } and put the returned file metadata in the artifact's metadata, like publish.ts does. That also makes the dry-run path go through the same code.
| if [[ -n "$expected_version" ]]; then | ||
| local pkg_version | ||
| pkg_version=$(dpkg-deb --field "$pkg_path" Version) | ||
| [[ "$pkg_version" == "$expected_version" ]] || fail "Version mismatch: expected $expected_version, got $pkg_version" |
There was a problem hiding this comment.
nfpm turns semver prereleases into ~. With VERSION=2.0.27-beta.1 I got opencode_2.0.27~beta.1_amd64.deb, and this check fails with expected 2.0.27-beta.1, got 2.0.27~beta.1. The RPM check at line 129 has the same problem. Every beta release would fail here. Please normalise the expected version (- → ~) before comparing, for both deb and rpm.
Issue for this PR
Closes #45767
Supersedes #45766 and #53917 (both targeted v1
devbranch, now ported to v2)Type of change
What does this PR do?
Adds
.deband.rpmsystem packages for amd64 and arm64 to the v2 publish pipeline. Users can install opencode via their OS package manager instead ofcurl | bash.Packages are built using nfpm from the existing signed CLI binaries during the
publishjob. No new CI jobs are added — nfpm cross-builds arm64 packages without QEMU. Packages are uploaded to R2 and registered with the update service alongside existing npm, Homebrew, and AUR distributions.The
x64-baselinebinary variant is used for x86_64 packages (broadest compatibility, matching the AUR PKGBUILD). Shell completions are omitted since the v2 CLI does not yet have acompletionsubcommand.Files added:
packages/cli/packaging/nfpm.yaml— nfpm config for DEB/RPM withexpand: truefor env var expansionpackages/cli/packaging/distribution.xml— macOS productbuild descriptor (reserved for future.pkgsupport)packages/cli/packaging/scripts/postinstall— macOS pkg postinstall (reserved)packages/cli/packaging/validate.sh— CI validation script for DEB/RPMpackages/cli/script/publish-system-packages.ts— packaging and upload scriptFiles modified:
packages/cli/script/publish.ts— invokepublish-system-packages.tsfor beta/latest releases.github/workflows/publish.yml— install nfpm+rpm tools, validate packages after buildREADME.md— add DEB/RPM install commandsDesign decisions
No new CI jobs — packages are built inline during the existing
publishjob, matching the pattern used by AUR and Homebrew publishers. nfpm handles cross-arch without QEMU.x64-baselinefor amd64 packages — uses the non-AVX2 build for maximum compatibility, same as the AUR PKGBUILD.recommendsnotdependsfor ripgrep — soft dependency so the package installs on systems without ripgrep in their repos. The AUR package usesdependsbecause Arch users can always install ripgrep; DEB/RPM distros are more varied.R2 + update service — packages are uploaded to Cloudflare R2 and registered with the update API using the existing
UpdateArtifactpattern, keeping them consistent with other distribution channels.No macOS
.pkgyet — the distribution.xml and postinstall are included as placeholders but not wired up, since.pkgbuilding requires a macOS runner (pkgbuild). This can be added in a follow-up PR.No shell completions — the v2 CLI does not have a
completionsubcommand (v1 used yargs). Completions can be added to the packages when v2 gains completion support.How did you verify your code works?
expand: truerequired for content field env var expansionrecommendsto RPMRPMTAG_RECOMMENDNAME(queried viarpm --recommends)publish-aur.tsandpublish-homebrew.tsbuild.tsoutput layout (cli-linux-{target}/bin/opencode)Screenshots / recordings
No UI changes.
Checklist