From 8d424fbc980acaab2ab847b47a6554c1db2fbce1 Mon Sep 17 00:00:00 2001 From: cucadmuh <49571317+cucadmuh@users.noreply.github.com> Date: Fri, 1 May 2026 22:04:26 +0300 Subject: [PATCH] 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. --- .github/workflows/next.yml | 4 ++-- .github/workflows/promote-main-to-next.yml | 6 +++++- .github/workflows/promote-next-to-release.yml | 6 +++++- .github/workflows/release.yml | 4 ++-- .../workflows/reusable-channel-publish.yml | 21 +++++++++++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/workflows/next.yml b/.github/workflows/next.yml index eeaa2f0a..50aa3041 100644 --- a/.github/workflows/next.yml +++ b/.github/workflows/next.yml @@ -28,6 +28,6 @@ jobs: target_branch: next prerelease: true draft_release: true - verify_nix: ${{ !(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') }} + 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') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }} secrets: inherit diff --git a/.github/workflows/promote-main-to-next.yml b/.github/workflows/promote-main-to-next.yml index 8afb8dfe..13034cc9 100644 --- a/.github/workflows/promote-main-to-next.yml +++ b/.github/workflows/promote-main-to-next.yml @@ -68,7 +68,11 @@ jobs: exit 0 fi 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 run: git push --force-with-lease origin HEAD:next - name: dispatch Next Channel workflow diff --git a/.github/workflows/promote-next-to-release.yml b/.github/workflows/promote-next-to-release.yml index ca8bbb77..9a5719a3 100644 --- a/.github/workflows/promote-next-to-release.yml +++ b/.github/workflows/promote-next-to-release.yml @@ -53,7 +53,11 @@ jobs: exit 0 fi 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 run: git push --force-with-lease origin HEAD:release - name: dispatch Release Channel workflow diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7523f0e7..9b5020d0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,6 @@ jobs: target_branch: release prerelease: false draft_release: true - verify_nix: ${{ !(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') }} + 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') || (github.event_name == 'push' && contains(github.event.head_commit.message, '[source-only]'))) }} secrets: inherit diff --git a/.github/workflows/reusable-channel-publish.yml b/.github/workflows/reusable-channel-publish.yml index df7f9a1e..ed0e8297 100644 --- a/.github/workflows/reusable-channel-publish.yml +++ b/.github/workflows/reusable-channel-publish.yml @@ -166,6 +166,14 @@ jobs: const targetCommitish = process.env.RELEASE_COMMIT_SHA; const name = `Psysonic v${version}`; 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 { const { data } = await github.rest.repos.getReleaseByTag({ owner: context.repo.owner, @@ -198,6 +206,19 @@ jobs: releaseId = data.id; 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)); - name: validate release id output env: