Skip to content

CI and Releases

TomΓ‘s Platero edited this page Oct 9, 2026 · 4 revisions

CI and Releases

Current state: two workflows (owner decision, 2026-09-28)

The workflows were removed on 2026-09-27 (they consumed minutes and money); on 2026-09-28 the owner asked for build and release on GitHub again, and fast. That earlier decision is reverted and dated here.

There are two workflows:

  • .github/workflows/ci.yml β€” CI: on every push to master/feat/** and on every PR (ignoring .md and updates/), it compiles, runs the connector tests and uploads the packed editor as an artifact. cancel-in-progress per branch: consecutive pushes do not pile up runs.
  • .github/workflows/release.yml β€” Release: triggered by a v* tag or by hand (workflow_dispatch). It builds, creates the GitHub release with the zip and its SHA-256, generates the update feed, lands it on master, and verifies the feed live.

Why it is fast

  • Caches: node_modules + the npm cache (the pi runtime's cache too) and the electron binary, keyed on package-lock.json. With a warm tree, dev/deps-current.mjs skips the whole npm ci β€” the step that cost 5–8 minutes cold.
  • The esbuild route: the product compile uses Microsoft's factory route, re-enabled (compiling src/ in seconds, not minutes), with tsgo stitched into the prepack as the type-check gate.
  • A single job, 4 cores: the realistic target is ~10–15 minutes warm and under the 40-minute timeout. Cold (first run or a moved lockfile) takes longer: that is npm ci, not a failure.

The hard rules the release enforces

The release procedure and its rules are also documented in the repository's release guide; the workflow carries them inside so they cannot be executed wrong:

  1. The version lives only in distribution/product-delta.json. The tag matches set.picodeVersion β€” PiCode's number, the one a release is named after. The release workflow reads set.version (the editor's number) from that file before tagging.
  2. The new version must be strictly greater than the last published release (numeric comparison per segment).
  3. The feed's commit is read from the built product.json, not from HEAD.
  4. The feed is generated with dev/update-feed.mjs --target archive --platform win32 --arch x64 and --installed <previous version>; --force is never passed β€” if the generator refuses, the release stops.
  5. The feed is landed on the channel branch through a pull request: the workflow pushes a throwaway feed-ship-v<picodeVersion> branch built from that branch, opens the PR and merges it at once (branch rules require a PR on every branch, and the GitHub Actions app cannot be a bypass actor here). Then it verifies the feed against raw.githubusercontent.com until seen live (10 tries of 20 s, with CDN cache busting), and the job summary warns if the repository is still private β€” the feed only reaches users while the repository is public.

The zip is made with 7-Zip, excluding data/ (the portable profile is not product). The zip is also uploaded as a run artifact for debugging without downloading the release.

How a release is published

  1. Bump the version in distribution/product-delta.json β†’ set.version (strictly greater than the last one).
  2. Land it: commit on a branch, open a pull request and merge it. Direct pushes to branches are disabled for contributors; repository admins keep a bypass.
  3. Tag and push the tag: git tag v<version> && git push origin v<version>. Tags are not branches, so the tag goes straight up. The workflow does the rest: release + zip + SHA-256 + feed on the channel branch.
  4. The run summary (Actions β†’ Release β†’ summary) carries the version, the commit, the SHA-256, the release and feed URLs, and the visibility warning if applicable.

The manual path (running the same steps by hand) stays valid as a fallback β€” for example if Actions is unavailable; the rules are the same.

Known build traps (still current)

  • Runner/machine RAM: packing asks for more than 6 GB of heap. On an 8 GB machine, NODE_OPTIONS="--max-old-space-size=5632"; on 16 GB, 12288 is plenty. Ubuntu 24.04 also ships systemd-oomd, which kills the whole cgroup under memory pressure without printing "Killed" β€” stop it before building (sudo systemctl stop systemd-oomd).
  • GitHub asset downloads during the build (js-debug etc.): anonymous requests run out (403 rate limit); with GITHUB_TOKEN in the environment, fetch.ts authenticates itself.
  • Debian renames the arch: .deb files are generated under amd64, not x64; .rpm files under x86_64.
  • Installers in sequence: the prepare and build of each format are two invocations β€” in parallel, build runs before prepare created the directory (spawn /bin/sh ENOENT).
  • npm 11 blocks install scripts without explicit per-package approval: the prepare stage writes the approvals for the native packages.
  • Windows looks for Visual Studio in fixed paths: if the tree lives elsewhere, vs2022_install=<path> is the override it honours.
  • zip does not exist on Windows runners: the release zip is made with 7-Zip (7z a -tzip, preinstalled there); the local release binary follows the same rule of excluding data/.

The pin, without an automatic watchdog

The VS Code pin (upstream/stable.json) is moved by hand (the steps are in Building PiCode); the watchdog workflow that used to open the pin PR is gone with the retired build machinery.


Related: Building PiCode Β· Getting PiCode

Clone this wiki locally