Rework the release pipeline and attest what it publishes (#5249) * Remove the CI scripts nothing runs anymore The release pipeline has accumulated scripts with no caller: the RPM build and signing tools from before RPM builds were switched off, the GitLab configuration, the nano-env image builders that the test workflows stopped using when they moved to ci/prepare, the Windows test wrappers superseded by ci/build.sh, the previous generation of the tag generator and the macOS dependency installer. None of them is referenced by a workflow, a Dockerfile or another script. * Name package files after the build tag CPack named packages after the CMake version, nano-node-29.0.0-Linux, and the deploy scripts renamed each one to the published name on upload. Setting CPACK_PACKAGE_FILE_NAME from the tag gives every package its published name as soon as it is built, which is also the name an attestation will record for it. The Windows build gets ZIP added to its CPack generators so one cpack run produces both the installer and the archive. * Build release packages through ci/build.sh Each platform had its own way of configuring and building the release packages: a bash script with a hard-coded Qt path for Linux and macOS, and a PowerShell wrapper around two batch files for Windows, none of them sharing anything with the ci/build.sh the test workflows use. ci/build-packages.sh now drives ci/build.sh for all three, runs cpack and collects the packages in packages/ under their published names. ci/build.sh passes the build type to cmake --build so the Visual Studio generator builds the requested configuration instead of always Debug, and CMakeLists.txt keeps every configuration's binaries in the build root, where the test scripts look for them. The Windows build step never received NETWORK or CI_TAG, so its beta packages were live-network builds reporting a development version; both are passed now. The commented-out Authenticode signing script and its secrets go, as does the SIMD flag, which has no effect on MSVC. * Upload packages with one script deploy.sh and deploy.ps1 did the same job in two languages: hash each package, write the hash beside it and copy both to the download bucket. ci/deploy/upload.sh does it for every platform from the packages/ directory, which already holds the published names, so the per-platform globs and the renaming on upload are gone, together with the RPM branch that has had no caller since RPM builds were switched off. The .sha256 files now contain the bare file name. The Linux ones used to embed the runner's absolute build path, which made them useless to sha256sum -c. * Rewrite the Docker image build and push The image went through a 170-line library sourced by five one-line wrappers, with the registry names, the nightly suffix, the tag list and the login spread across it, plus a scan of every local image to decide what to push. Two scripts replace it: docker-build.sh builds the image once and names it for the registries, docker-push.sh tags and pushes one repository and reports the digest it got, which the next step needs for attestation. The workflow logs in with docker/login-action and spells out each registry's tags, including that only beta gets a latest tag on Docker Hub. Whether a live build is a nightly is now read off the tag instead of a separate input. The build no longer pulls the previous image as a layer cache; with a multi-stage Dockerfile that cache held only the final stage and saved nothing of the compile. * Rewrite the tag generator generate_next_git_tag.sh grew its options, globals and output modes over several rounds and was hard to reason about: it matched tags with an unescaped dot, force-moved tags and force-pushed the release branch, and wrote its results to GITHUB_ENV for the workflow to copy into outputs. ci/deploy/next-tag.sh keeps the scheme (DB tags on develop, RC tags on the release branch, plain release tags on request, versions committed into CMakeLists.txt and the release commit pushed to its branch) in a third of the lines, with a --dry-run that prints the tag it would create. Pushes are no longer forced, so a collision fails instead of moving a published tag, and the outputs go straight to GITHUB_OUTPUT. The workflow checks out the full history for it: deciding whether the latest tag already covers HEAD needs the commits between them. * Run Build & Deploy on the tag it builds Build & Deploy used to create the tag in its first job and have the build jobs check that tag out, so a run's own commit was the branch head it started from while the packages came from the version commit one step ahead. Anything that records the run's commit, including the attestations the next change adds, would have named the wrong one. Tagging moves to its own workflow, Tag Build, which keeps the schedule and the manual trigger, creates the tag and then starts Build & Deploy on it with gh workflow run, the one way a GITHUB_TOKEN may start a workflow. Build & Deploy now runs on a tag ref, checks out that ref as any workflow does and takes the tag name from it, so it can also be started by hand on an existing tag to rebuild it. A first job refuses to run on anything but a build tag. The upload steps run only when the bucket credentials are present, which lets a fork build and verify packages without them. * Attest release packages and images Every job that publishes something now asks GitHub Actions to attest it: actions/attest signs the digests of the packages in packages/ and of each pushed image under the workflow's OIDC identity, stores the attestation with the repository and, for images, in the registry next to the image. A consumer can then check that a download was built by this workflow from the commit it names, which the .sha256 files beside the packages cannot show since they come from the same job. The jobs get the id-token and attestations permissions this needs, and the package jobs publish the attestation bundle next to the packages so it can be verified without the GitHub API. * Describe the release pipeline A short page under ci/deploy for whoever next has to touch a release: how a tag comes about, what Build & Deploy publishes where, and the commands a user runs to verify a download against its attestation. * Keep packages as workflow artifacts The packages only ever left the runner through the bucket upload, so a run without the bucket secrets, which is every run on a fork, lost what it built. The package jobs now attach them to the run as well, which keeps every build inspectable and lets a fork verify the attestation of what it built. * Rewrite Prepare Release and describe the whole release process Prepare Release cuts the release branch and moves develop on to the next major. The job did it in six inline steps: it fetched the default branch name over the REST API, bumped the major on a timestamped branch, opened the pull request, hard-reset its checkout and only then created the release branch, from the default branch whatever ref it had been started on, with no permissions block and a typo in a step name. ci/deploy/prepare-release.sh does the same work in the order a reader expects, refuses to run on anything but the default branch or when that branch is not at <major>.0, and takes --dry-run like the tag generator. It shares the version helpers with next-tag.sh through common.sh and names the pull request's repository explicitly, so a fork never opens one against the upstream repository. The README now opens with the release process itself: how development builds come about, the steps and the order for a release, point releases, rebuilding a tag, and where the workflows stop. * Let a failed network build finish the other one The package and Docker jobs build beta and live as one matrix with GitHub's default fail-fast, so a failure in one network cancelled the other network's build of the same platform and the run published less of the tag than it could have. With fail-fast off every build runs to its own result, and the run shows exactly which outputs were published. * Rewrite the release pipeline README as a reference The page told the release as a story: the tag grammar was spread over three paragraphs, the bucket and the registries were used before they were named, workflow names changed form from one mention to the next, and the notes a maintainer needs sat as asides inside procedure steps. It was also hard-wrapped at a column. It now defines its terms first, gives the tag kinds and the rules the tag script applies in one place, lists what Build & Deploy publishes where with the exact file and image names, describes each workflow and script with its inputs and outputs, and keeps the release procedure, repository configuration, local dry runs and verification as sections of their own. * Build packages without debug information Beta packages were RelWithDebInfo builds. On Linux the debug information goes into the binaries themselves, so each beta package weighed half a gigabyte against 25 MB for live. macOS and Windows keep their debug information outside the packaged files, so nothing shipped there changes. Packages of both networks now build as Release. The symbol table stays, so stack traces in the log keep their function names. The Docker images are unchanged and keep their debug information. * Push a release's tag and branch update together A release pushed its tag first and the version commit to its branch second. When the branch push was rejected, by a protection rule or a push that got in between, the tag stayed published while releases/v<major> was left behind, and a rerun saw HEAD covered by that tag and created nothing, so the branch never caught up on its own. The two refs now go out in one atomic push: either both land or neither does, and a rerun starts from an origin that is as it was. Pre-release runs still push only their tag.
__________
Type: commit
Hash: 429f7dc608f2b3bdeb37ccb71fdd406b5b963104
Created: yesterday
__________
gr0v1ty/nano-node:429f7dc608f2b3bdeb37ccb71fdd406b5b963104
| Test Case | Status | Duration | Median Deviation | Log | Graph |
|---|---|---|---|---|---|
| No test results available yet. Check the GitHub test run for job status and logs. | |||||