Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/mirror-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Immutable release tag to mirror, for example v2.8.2
description: Immutable release tag to mirror, for example v2.8.3
required: true
type: string

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ jobs:

- name: Upload unsigned build artifact
if: steps.v.outputs.go_release == 'true'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: unsigned-release-${{ github.ref_name }}
path: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stage-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
|| { echo "tag commit is not contained in main" >&2; exit 1; }

- name: Download gated unsigned artifact
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: unsigned-release-${{ github.event.workflow_run.head_branch }}
path: dist
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project are documented here.

## v2.8.3 - 2026-07-27

- Run the release artifact handoff on the official actions' native Node.js 24
versions. The signed `v2.8.2` tag exposed the upload action's Node.js 20
deprecation warning after the read-only gate produced an unsigned artifact;
its unsigned draft was deliberately removed before release signing or
publication, and no published v2.8.2 assets exist.

## v2.8.2 - 2026-07-27

- Serialize root integration test packages because they share the host account
Expand Down
18 changes: 9 additions & 9 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,10 @@ git -c user.name='XXV.CC' \
-c user.signingkey="${TAG_SIGNING_FPR}!" \
-c gpg.format=openpgp \
-c gpg.program=/usr/bin/gpg \
tag -s v2.8.2 "$RELEASE_COMMIT" -m 'linux-temp-admin v2.8.2'
tag -s v2.8.3 "$RELEASE_COMMIT" -m 'linux-temp-admin v2.8.3'
git -c gpg.format=openpgp -c gpg.program=/usr/bin/gpg \
verify-tag --raw v2.8.2
git push origin v2.8.2
verify-tag --raw v2.8.3
git push origin v2.8.3
```

Before pushing, the `VALIDSIG` record from `verify-tag --raw` must identify the
Expand Down Expand Up @@ -489,7 +489,7 @@ printf '\n' >/dev/tty
|| fail "GH_TOKEN must be one non-empty token without whitespace"
export GH_TOKEN
exec /opt/lta-release-tools/prepare-release.sh \
v2.8.2 /srv/linux-temp-admin /srv/release-transfer/v2.8.2-prepared
v2.8.3 /srv/linux-temp-admin /srv/release-transfer/v2.8.3-prepared
LTA_PREPARE_RELEASE
```

Expand All @@ -509,7 +509,7 @@ the candidate or transfer media:
LTA_SIGN_KEY=/offline/keys/release-v1.key
LTA_TRUSTED_SIGNER=/opt/lta-release-tools/lta-release
LTA_TRUSTED_SIGNER_SHA256='<offline-recorded signer sha256>'
LTA_EXPECTED_TAG=v2.8.2
LTA_EXPECTED_TAG=v2.8.3
LTA_EXPECTED_COMMIT='<independently recorded 40-hex commit>'
LTA_EXPECTED_PREPARED_MANIFEST_SHA256='<independently recorded sha256>'
LTA_EXPECTED_RELEASE_SIGNER_PUBKEY='<independently recorded 64-hex OLD public key>'
Expand All @@ -521,7 +521,7 @@ LTA_EXPECTED_RELEASE_SIGNER_PUBKEY='<independently recorded 64-hex OLD public ke
LTA_EXPECTED_PREPARED_MANIFEST_SHA256="$LTA_EXPECTED_PREPARED_MANIFEST_SHA256" \
LTA_EXPECTED_RELEASE_SIGNER_PUBKEY="$LTA_EXPECTED_RELEASE_SIGNER_PUBKEY" \
/opt/lta-release-tools/offline-sign-release.sh \
/media/in/v2.8.2-prepared /media/out/v2.8.2-signed
/media/in/v2.8.3-prepared /media/out/v2.8.3-signed
```

The script copies the removable input into a size-bounded private local snapshot
Expand Down Expand Up @@ -572,7 +572,7 @@ printf '\n' >/dev/tty
|| fail "GH_TOKEN must be one non-empty token without whitespace"
export GH_TOKEN
exec /opt/lta-release-tools/publish-release.sh \
/srv/release-transfer/v2.8.2-signed /srv/linux-temp-admin
/srv/release-transfer/v2.8.3-signed /srv/linux-temp-admin
LTA_PUBLISH_RELEASE
```

Expand Down Expand Up @@ -637,7 +637,7 @@ noncanonical published stable tag, excludes the failed `TAG`, and verifies the
exact resulting Latest state:

```bash
TAG=v2.8.2 # the failed release; verify this value before running
TAG=v2.8.3 # the failed release; verify this value before running
/usr/bin/sudo /usr/bin/env -i \
HOME=/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LC_ALL=C \
TAG="$TAG" /bin/bash -p <<'LTA_LATEST_RECOVERY'
Expand Down Expand Up @@ -996,7 +996,7 @@ the release audit/signing record and a separate authenticated channel, then run:
```bash
INSTALLER_COMMIT='replace-with-the-audited-40-hex-commit'
INSTALLER_SHA256='replace-with-the-independent-64-hex-script-hash'
LTA_RELEASE_TAG='v2.8.2'
LTA_RELEASE_TAG='v2.8.3'
/usr/bin/sudo /usr/bin/env -i \
HOME=/root PATH=/usr/sbin:/usr/bin:/sbin:/bin LC_ALL=C \
INSTALLER_COMMIT="$INSTALLER_COMMIT" INSTALLER_SHA256="$INSTALLER_SHA256" \
Expand Down
16 changes: 16 additions & 0 deletions internal/selfmanage/release_pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,22 @@ func TestReleaseWriterIsSeparatedFromCandidateWorkflow(t *testing.T) {
}
}

func TestReleaseArtifactHandoffUsesAuditedNode24Actions(t *testing.T) {
release := readReleaseFile(t, "../../.github/workflows/release.yml")
stage := readReleaseFile(t, "../../.github/workflows/stage-release.yml")
for name, check := range map[string]struct {
content string
pin string
}{
"upload": {release, "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1"},
"download": {stage, "actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1"},
} {
if !strings.Contains(check.content, check.pin) {
t.Errorf("release %s action is not pinned to the audited native Node.js 24 version", name)
}
}
}

func TestMirrorReleaseWorkflowPublishesVerifiedImmutableContentFailClosed(t *testing.T) {
mirror := readReleaseFile(t, "../../.github/workflows/mirror-release.yml")
installer := readReleaseFile(t, "../../scripts/install.sh")
Expand Down