fix(KAN-65): resume release publication with CI credentials
CI/CD / preconditions (pull_request) Canceled after 0s
CI/CD / test_and_check_app (pull_request) Canceled after 0s
CI/CD / Publish immutable image (pull_request) Canceled after 0s
macOS checks / Native Rust tests and unsigned build (pull_request) Canceled after 11s
Native JavaScript checks / Native launcher and release tests (pull_request) Canceled after 0s

This commit is contained in:
2026-09-28 07:27:05 +02:00
parent 40b66bf7ce
commit 9dbb491dc9
3 changed files with 90 additions and 1 deletions
+50
View File
@@ -12,6 +12,14 @@ on:
description: "Existing protected macos-vMAJOR.MINOR.PATCH tag on main" description: "Existing protected macos-vMAJOR.MINOR.PATCH tag on main"
required: true required: true
type: string type: string
mode:
description: "Build a release or resume publishing existing verified artifacts"
required: true
default: build
type: choice
options:
- build
- resume
permissions: permissions:
contents: read contents: read
@@ -49,8 +57,10 @@ jobs:
env: env:
REQUESTED_TAG: ${{ inputs.tag }} REQUESTED_TAG: ${{ inputs.tag }}
MACOS_RUNNER: ${{ vars.MACOS_RUNNER }} MACOS_RUNNER: ${{ vars.MACOS_RUNNER }}
RELEASE_MODE: ${{ inputs.mode || 'build' }}
run: | run: |
set -Eeuo pipefail set -Eeuo pipefail
[[ "${RELEASE_MODE:-build}" == build || "${RELEASE_MODE:-build}" == resume ]] || { echo 'Invalid release mode.' >&2; exit 1; }
if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]]; then if [[ "$GITHUB_EVENT_NAME" == workflow_dispatch ]]; then
[[ "$GITHUB_REF" == refs/heads/main ]] || { echo 'Dispatch this workflow from main.' >&2; exit 1; } [[ "$GITHUB_REF" == refs/heads/main ]] || { echo 'Dispatch this workflow from main.' >&2; exit 1; }
tag="$REQUESTED_TAG" tag="$REQUESTED_TAG"
@@ -80,6 +90,7 @@ jobs:
release: release:
name: Sign, notarize, verify and publish macOS name: Sign, notarize, verify and publish macOS
needs: prepare needs: prepare
if: ${{ inputs.mode != 'resume' }}
# Gitea resolves runner labels before outputs from prepare are available. # Gitea resolves runner labels before outputs from prepare are available.
runs-on: ${{ vars.MACOS_RUNNER }} runs-on: ${{ vars.MACOS_RUNNER }}
timeout-minutes: 120 timeout-minutes: 120
@@ -224,3 +235,42 @@ jobs:
finally: finally:
shutil.rmtree(directory) shutil.rmtree(directory)
PY PY
resume:
name: Resume verified release publication
needs: prepare
if: ${{ github.event_name == 'workflow_dispatch' && inputs.mode == 'resume' }}
runs-on: ${{ vars.MACOS_RUNNER }}
timeout-minutes: 15
env:
RELEASE_TAG: ${{ needs.prepare.outputs.tag }}
RELEASE_METADATA_DIRECTORY: release-source/native
steps:
- name: Check out current publishing tools
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Check out validated release metadata
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.prepare.outputs.commit }}
path: release-source
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
- name: Verify existing artifacts and resume publication
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
AWS_EC2_METADATA_DISABLED: "true"
AWS_REQUEST_CHECKSUM_CALCULATION: when_required
AWS_RESPONSE_CHECKSUM_VALIDATION: when_required
run: |
aws --version | grep '^aws-cli/2\.' || { echo 'Install AWS CLI v2 permanently on this runner.' >&2; exit 1; }
node native/publish-macos.mjs resume
+7 -1
View File
@@ -435,7 +435,13 @@ if (
process.argv[2] === 'resume' ? resumeMacos : publishMacos; process.argv[2] === 'resume' ? resumeMacos : publishMacos;
const url = await publish({ const url = await publish({
directory: process.env.RELEASE_DIRECTORY, directory: process.env.RELEASE_DIRECTORY,
metadata: releaseMetadata(), metadata: releaseMetadata(
process.env,
process.argv[2] === 'resume' &&
process.env.RELEASE_METADATA_DIRECTORY
? resolve(process.env.RELEASE_METADATA_DIRECTORY)
: undefined,
),
}); });
console.log(`Verified public release: ${url}`); console.log(`Verified public release: ${url}`);
if (process.env.GITHUB_STEP_SUMMARY) { if (process.env.GITHUB_STEP_SUMMARY) {
+33
View File
@@ -113,6 +113,38 @@ test('manual release on main accepts an existing tag without moving it', (t) =>
assert.equal(f.git(f.checkout, 'rev-parse', 'macos-v1.2.3'), f.commit); assert.equal(f.git(f.checkout, 'rev-parse', 'macos-v1.2.3'), f.commit);
}); });
test('resume uses current tools, validated tagged metadata and release credentials without rebuilding', (t) => {
const f = fixture(t);
const result = f.run({
GITHUB_EVENT_NAME: 'workflow_dispatch',
GITHUB_REF: 'refs/heads/main',
REQUESTED_TAG: 'macos-v1.2.3',
RELEASE_MODE: 'resume',
});
assert.equal(result.status, 0, result.stderr);
const resume = workflow.split('\n resume:\n')[1];
assert.match(resume, /needs: prepare/);
assert.match(
resume,
/github.event_name == 'workflow_dispatch' && inputs.mode == 'resume'/,
);
assert.match(resume, /ref: \$\{\{ github.sha \}\}/);
assert.match(resume, /ref: \$\{\{ needs.prepare.outputs.commit \}\}/);
assert.match(resume, /RELEASE_METADATA_DIRECTORY: release-source\/native/);
assert.match(resume, /path: release-source/);
assert.match(resume, /secrets.S3_ACCESS_KEY_ID/);
assert.match(resume, /secrets.S3_SECRET_ACCESS_KEY/);
assert.match(resume, /node native\/publish-macos.mjs resume/);
assert.doesNotMatch(
resume,
/tauri-action|APPLE_PASSWORD|APPLE_CERTIFICATE|TAURI_SIGNING_PRIVATE_KEY/,
);
assert.match(
workflow.split('\n release:\n')[1],
/if: \$\{\{ inputs.mode != 'resume' \}\}/,
);
});
test('release DMG packaging disables Finder automation in the Tauri action environment', () => { test('release DMG packaging disables Finder automation in the Tauri action environment', () => {
const build = workflow const build = workflow
.split(' - name: Build, sign and notarize with Tauri\n')[1] .split(' - name: Build, sign and notarize with Tauri\n')[1]
@@ -127,6 +159,7 @@ test('release DMG packaging disables Finder automation in the Tauri action envir
}); });
for (const [name, overrides] of [ for (const [name, overrides] of [
['invalid release mode', { RELEASE_MODE: 'overwrite' }],
['web release tag', { GITHUB_REF: 'refs/tags/v1.2.3' }], ['web release tag', { GITHUB_REF: 'refs/tags/v1.2.3' }],
['missing tag', { GITHUB_REF: 'refs/tags/macos-v9.9.9' }], ['missing tag', { GITHUB_REF: 'refs/tags/macos-v9.9.9' }],
[ [