ci: run checks and builds on GitHub Actions, with release-intent automation - #87
Open
Noah-Tervalon-Nvidia wants to merge 9 commits into
Open
Noah-Tervalon-Nvidia wants to merge 9 commits into
Noah-Tervalon-Nvidia wants to merge 9 commits into
Conversation
Runs the header, desktop, and Go test suites on pull requests and pushes to main and develop, plus unsigned installers across a six-way matrix. Windows builds natively rather than cross-compiled under wine. Also runs services/build.sh and build.bat natively on each platform. That is a second, independent build path over the same Go code: it parses versions with jq and stamps -ldflags -X main.Version, where the desktop path cross-compiles through a TypeScript script. Either can break alone. Neither workflow holds a secret or requests an OIDC token: both execute code from the pull request, so there must be no credential for that code to reach. Actions are pinned to full commit SHAs. Signed releases are built elsewhere, from a tag. Signed-off-by: Terve <ntervalon@nvidia.com>
Records the 0.1.0 and 0.1.1 notes as published on the releases page. This repository had no changelog, so release history was only discoverable there. Seeded from the published notes rather than carrying over historical development entries, and tracks the 0.1.x version that desktop/package.json and the release tags use. Signed-off-by: Terve <ntervalon@nvidia.com>
The field called `product` only ever versioned the services suite: it is declared inside services/, stamps the standalone installer and Go main.Version, and the version users install lives in desktop/package.json, which was explicitly out of scope for it. The two had drifted to 0.91.7 and 0.1.1, which is the clearest evidence they were never one number. `installer` is dropped: documented as 'always equals product', it could never differ from another field. Readers of '.installer // .product' now read '.services'. Updates all nine consumers, including build.sh which was reading .product and would have silently resolved null. The versions card already displayed this as 'Services', so no user-visible string changes. Signed-off-by: Terve <ntervalon@nvidia.com>
Contributors declare version bumps and changelog text in the pull request body; a check validates it, and after the merge lands on develop a bot applies it to desktop/package.json, services/versions.json, and CHANGELOG.md in one commit via the git data API. The contents API is one commit per file, which would land a release in pieces with a window where the changelog names a version package.json does not carry. The release version is not declared. It patch-bumps automatically whenever an intent declares a release, so the only judgement left is services and component severity; a minor or major release is a deliberate manual bump. validate_pr.py reads the body from the webhook payload, so it needs no credential and runs on fork pull requests. It has its own workflow so it can also trigger on 'edited': a body can change after checks go green, and apply reads the live body at merge time. Apply rejects unknown keys for the same reason, but tolerates missing ones, which is a concurrent pull request adding a component rather than tampering. The app token gets contents: write and not the Workflows permission, so a compromise of the apply job cannot rewrite the pipeline. Ports from the GitLab implementation, dropping its description-truncation fallback, the protected-variable split that fallback needed, and its url.insteadOf workaround — all GitLab Runner specifics. Also corrects the pull request template, which told contributors to hand-edit services/versions.json; the bot-owned path check rejects exactly that, so every pull request would have failed. Signed-off-by: Terve <ntervalon@nvidia.com>
Node and Go versions were duplicated between ci.yml and build.yml. GitHub Actions has no shared constants file — env: is per-workflow and one workflow cannot read another — so a local composite action is the only way to declare them once without moving them out of the repository into repository variables, where they would stop being reviewable. Bumping one copy and forgetting the other would have pull request checks and release builds running different toolchains, which is the failure this removes. Inputs keep what each job actually needs: the header check takes Node without an npm cache it has no install to populate, and the build-script job takes Go without Node. Checkout stays in the callers, since a local action cannot exist before its own repository is on disk. Signed-off-by: Terve <ntervalon@nvidia.com>
setup-go caches by default and looks for a dependency file at the repository root. Every Go module lives under services/, so the action found nothing and reported 'Dependencies file is not found' on each run — a warning in current versions, a hard failure in some earlier ones. Naming the path fixes that and makes the caching real: a cold build pulls roughly 40 seconds of modules, repeated across the services job, the three-platform build-script job, and the installer builds. It also pins the cache key, which is version-dependent otherwise: older setup-go hashes go.sum, newer hashes go.mod. Signed-off-by: Terve <ntervalon@nvidia.com>
The check asserted 'at least 13'. A floor stops asserting anything the moment the real number grows: add a fourteenth component and it keeps passing, so the check quietly becomes decoration. A hardcoded '-eq 13' fixes that but still only sees the count, and 13 is a magic number with no relationship to where components are actually declared. Compares the staged names against the component keys in versions.json instead. Adding, removing, or renaming a component now fails until the build script and the manifest agree, and the failure names which side is missing what rather than reporting a number. Signed-off-by: Terve <ntervalon@nvidia.com>
The product-to-services rename changed a line that verify-service-contracts generates into docs/services-api.md, but the generated file was not regenerated to match, so the freshness gate failed. Generated output only; produced by npm run service-contracts:write. Signed-off-by: Terve <ntervalon@nvidia.com>
The check compared two lists built by different pipelines, so a stray carriage return made every entry differ while printing identically. The failure output then showed the same names on both sides, which reads as nonsense rather than as a diagnosis. Both sides now run through one normalizer, in an order that matters: CR is stripped before the .exe suffix, because under Git Bash a CRLF line leaves .exe mid-string and 's/\.exe$//' never matches. LC_ALL=C makes the sort byte-wise, which is what the comm calls already assumed. On failure it also dumps the raw listing and both lists through 'sed -n l', so an invisible character shows up as \r instead of as two identical lists. Verified against a CRLF versions.json with .exe binaries, a POSIX checkout, a missing component, and an undeclared one. Signed-off-by: Terve <ntervalon@nvidia.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Moves checks and unsigned installer builds to GitHub Actions on GitHub-hosted
runners, and ports the release-intent automation that keeps version bumps and
changelog entries out of merge-conflict territory.
Self-hosted runners cannot serve a public repository: on a fork pull request
the workflow file comes from the contributor's merge ref, so
runs-onisattacker-chosen. Everything here runs on hosted runners and holds no secret,
so there is no credential for pull request code to reach. Signed releases stay
on internal infrastructure and are built from a tag.
Also renames the
versions.jsonfieldproducttoservices. It only everversioned the services suite — it stamps the standalone installer and Go
main.Version, while the version users install lives indesktop/package.json, which was explicitly out of scope for it. The two haddrifted to
0.91.7and0.1.1.Resolves #22
Release intent
Changelog title
n/a
Changelog body
n/a
Bumps
Scope
Included: workflows, the release-intent scripts, the
producttoservicesrename across all nine consumers, a changelog seeded from the published 0.1.0
and 0.1.1 release notes.
Excluded: signing, publishing, and release. Those stay on internal
infrastructure and are a separate piece of work.
Validation
Locally, on this branch:
python3 scripts/release-intent/test_lib.py— 28 testsnpm --prefix desktop run typecheck— cleannpm --prefix desktop run lint— 0 errorsnpm --prefix desktop run dead-code:check— no dead codenpm --prefix desktop run test:unit— 208 testsactionlinton all four workflows — cleannode scripts/spdx-headers.mjs— 0 missingapply_pr.py --dry-runproduces0.1.1 -> 0.1.2and a correctly numberedchangelog section
No workflow has executed before this pull request. The six-way build matrix is
unproven, and two legs are worth watching: Windows builds natively rather than
cross-compiled under wine, and
macos-latestis the smallest box in the matrixat 3 cores and 7 GB.
Risk
All bumps are
none: no Go source changed, so no compiled output changes andthis is not a release.
services/versions.jsonandCHANGELOG.mdare modified, which the newbot-owned path check rejects by design. The
allow-owned-filesmarker at thetop of this description is the documented override for a schema change the bot
cannot make itself.
Release intent applydoes not run on a pull request. It first runs on mergeto
develop, and needs the GitHub App configured before then or it will fail.Checklist
git commit -s).credentials, private data, internal URLs, internal issue identifiers, and
generated artifacts.