Fix/release create tag before verify (#404)

* fix(release): create missing app-v tag before release verification

Ensure reusable publish creates and pushes the expected app-v tag when absent,
then validates it points to source_ref. This prevents release records with tag_name
but no git refs/tags object, which previously broke Source code archives.

* fix(release): pin tauri publish to tagged release metadata

Pass tagName/releaseName/releaseDraft/prerelease to tauri-action in addition to
releaseId, so asset upload fallback remains bound to the expected app-v release
instead of creating untagged releases.

* chore(ci): align workflow action versions for release flow

Update github-script usage to v9 across release-related workflows and keep
the current tauri-action release binding changes in the same branch for testing.

* fix(release): harden tagged release resolution for source-only promote

Canonicalize release_id via getReleaseByTag after create/update and fail fast on
invalid tag/commit inputs to avoid untagged release binding. Also propagate
source-only marker through promote push events so push-triggered channel runs
skip platform artifacts and verify-nix consistently.
This commit is contained in:
cucadmuh
2026-05-01 22:04:26 +03:00
committed by GitHub
parent 090d129283
commit 8d424fbc98
5 changed files with 35 additions and 6 deletions
+2 -2
View File
@@ -28,6 +28,6 @@ jobs:
target_branch: next target_branch: next
prerelease: true prerelease: true
draft_release: true draft_release: true
verify_nix: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') }} verify_nix: ${{ !((github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }}
build_platform_artifacts: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') }} build_platform_artifacts: ${{ !((github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }}
secrets: inherit secrets: inherit
+5 -1
View File
@@ -68,7 +68,11 @@ jobs:
exit 0 exit 0
fi fi
NEW_VERSION="$(node -p 'require("./package.json").version')" NEW_VERSION="$(node -p 'require("./package.json").version')"
git commit -m "chore(release): bump next channel to ${NEW_VERSION}" MSG="chore(release): bump next channel to ${NEW_VERSION}"
if [[ "${{ inputs.source_only }}" == "true" ]]; then
MSG="${MSG} [source-only]"
fi
git commit -m "$MSG"
- name: push next - name: push next
run: git push --force-with-lease origin HEAD:next run: git push --force-with-lease origin HEAD:next
- name: dispatch Next Channel workflow - name: dispatch Next Channel workflow
@@ -53,7 +53,11 @@ jobs:
exit 0 exit 0
fi fi
NEW_VERSION="$(node -p 'require("./package.json").version')" NEW_VERSION="$(node -p 'require("./package.json").version')"
git commit -m "chore(release): finalize release version ${NEW_VERSION}" MSG="chore(release): finalize release version ${NEW_VERSION}"
if [[ "${{ inputs.source_only }}" == "true" ]]; then
MSG="${MSG} [source-only]"
fi
git commit -m "$MSG"
- name: push release - name: push release
run: git push --force-with-lease origin HEAD:release run: git push --force-with-lease origin HEAD:release
- name: dispatch Release Channel workflow - name: dispatch Release Channel workflow
+2 -2
View File
@@ -25,6 +25,6 @@ jobs:
target_branch: release target_branch: release
prerelease: false prerelease: false
draft_release: true draft_release: true
verify_nix: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') }} verify_nix: ${{ !((github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }}
build_platform_artifacts: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') }} build_platform_artifacts: ${{ !((github.event_name == 'workflow_dispatch' && github.event.inputs.source_only == 'true') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }}
secrets: inherit secrets: inherit
@@ -166,6 +166,14 @@ jobs:
const targetCommitish = process.env.RELEASE_COMMIT_SHA; const targetCommitish = process.env.RELEASE_COMMIT_SHA;
const name = `Psysonic v${version}`; const name = `Psysonic v${version}`;
let releaseId = null; let releaseId = null;
if (!tag || !/^app-v\d+\.\d+\.\d+/.test(tag)) {
throw new Error(`Invalid RELEASE_TAG '${tag ?? ""}'`);
}
if (!targetCommitish || !/^[0-9a-f]{40}$/i.test(targetCommitish)) {
throw new Error(`Invalid RELEASE_COMMIT_SHA '${targetCommitish ?? ""}'`);
}
try { try {
const { data } = await github.rest.repos.getReleaseByTag({ const { data } = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner, owner: context.repo.owner,
@@ -198,6 +206,19 @@ jobs:
releaseId = data.id; releaseId = data.id;
core.info(`Created release id=${releaseId} tag=${tag} target_commitish=${targetCommitish}`); core.info(`Created release id=${releaseId} tag=${tag} target_commitish=${targetCommitish}`);
} }
// Canonicalize release_id by querying the expected tag directly.
// This prevents passing a mismatched/untagged release id to later jobs.
const { data: byTag } = await github.rest.repos.getReleaseByTag({
owner: context.repo.owner,
repo: context.repo.repo,
tag,
});
if (!byTag.tag_name || byTag.tag_name.startsWith("untagged-")) {
throw new Error(`Release fetched by tag '${tag}' is untagged ('${byTag.tag_name ?? ""}')`);
}
releaseId = byTag.id;
core.info(`Resolved canonical release id=${releaseId} by tag=${tag}`);
core.setOutput("release_id", String(releaseId)); core.setOutput("release_id", String(releaseId));
- name: validate release id output - name: validate release id output
env: env: