diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d99a9053..a5e6b390d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -217,6 +217,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} PRERELEASE: ${{ needs.preflight.outputs.prerelease }} + REHEARSAL_PARTIAL_DRAFT: true SOURCE_SHA: ${{ needs.preflight.outputs.source_sha }} TAG: ${{ github.ref_name }} run: | @@ -225,14 +226,17 @@ jobs: release_assets=(release-candidate/*.tar.gz release-candidate/*.zip release-candidate/checksums.txt) release_error="$(mktemp "${RUNNER_TEMP}/release-view.XXXXXX")" trap 'rm -f -- "$release_error"' EXIT - if metadata="$(gh release view "$TAG" --json isDraft,isPrerelease,targetCommitish 2>"$release_error")"; then + verify_release_metadata() { node -e ' const [metadata, sourceSha, prerelease] = process.argv.slice(1); const release = JSON.parse(metadata); if (release.isDraft !== true || release.targetCommitish !== sourceSha || release.isPrerelease !== (prerelease === "true")) { - throw new Error("Existing Release metadata does not match this release candidate."); + throw new Error("Release metadata does not match this release candidate."); } - ' "$metadata" "$SOURCE_SHA" "$PRERELEASE" + ' "$1" "$SOURCE_SHA" "$PRERELEASE" + } + if metadata="$(gh release view "$TAG" --json isDraft,isPrerelease,targetCommitish 2>"$release_error")"; then + verify_release_metadata "$metadata" existing="$(mktemp -d "${RUNNER_TEMP}/draft-release.XXXXXX")" trap 'rm -f -- "$release_error"; rm -rf -- "$existing"' EXIT expected_names=("${release_assets[@]##*/}") @@ -274,11 +278,17 @@ jobs: echo "Could not determine whether the Release already exists." >&2 exit 1 fi - args=("$TAG" --target "$SOURCE_SHA" --title "$TAG" --draft) + args=("$TAG" --title "$TAG" --draft) [[ "$PRERELEASE" != "true" ]] || args+=(--prerelease) gh release create "${args[@]}" --notes-file "$release_notes" + verify_release_metadata "$(gh release view "$TAG" --json isDraft,isPrerelease,targetCommitish)" fi gh release edit "$TAG" --notes-file "$release_notes" + if [[ "${REHEARSAL_PARTIAL_DRAFT:-}" == "true" && "$GITHUB_RUN_ATTEMPT" == "1" ]]; then + gh release upload "$TAG" "${release_assets[0]}" + echo "S2 rehearsal: partial Draft uploaded; re-run failed jobs to resume." >&2 + exit 1 + fi gh release upload "$TAG" "${release_assets[@]}" diff --brief \ <(printf '%s\n' "${release_assets[@]##*/}" | sort) \ @@ -308,6 +318,7 @@ jobs: env: ARCH: ${{ matrix.arch }} MACOS_TEAM_ID: ${{ vars.MACOS_TEAM_ID }} + REHEARSAL_EXPECTED_TEAM_ID: TEST_INVALID_TEAM VERSION: ${{ needs.preflight.outputs.version }} run: | set -euo pipefail @@ -323,6 +334,7 @@ jobs: [[ -f "$binary" && ! -L "$binary" ]] || { echo "Archive did not contain a regular lark-cli binary." >&2; exit 1; } codesign --verify --strict --verbose=4 "$binary" details="$(codesign -dv --verbose=4 "$binary" 2>&1)" + [[ -z "${REHEARSAL_EXPECTED_TEAM_ID:-}" ]] || MACOS_TEAM_ID="$REHEARSAL_EXPECTED_TEAM_ID" grep -Eq '^Authority=Developer ID Application: .+' <<<"$details" grep -Fxq "TeamIdentifier=${MACOS_TEAM_ID}" <<<"$details" grep -Eq '^flags=0x[0-9A-Fa-f]+\(.*runtime.*\)' <<<"$details" diff --git a/package-lock.json b/package-lock.json index d9dbef008..1e0e87c53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@larksuite/cli", - "version": "1.0.79-beta.4", + "version": "1.0.79-beta.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@larksuite/cli", - "version": "1.0.79-beta.4", + "version": "1.0.79-beta.2", "cpu": [ "x64", "arm64", diff --git a/package.json b/package.json index 5fb52b8da..948dc08f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@larksuite/cli", - "version": "1.0.79-beta.4", + "version": "1.0.79-beta.2", "description": "The official CLI for Lark/Feishu open platform", "bin": { "lark-cli": "scripts/run.js" diff --git a/scripts/release-workflow.test.sh b/scripts/release-workflow.test.sh index cc729e700..74738392c 100755 --- a/scripts/release-workflow.test.sh +++ b/scripts/release-workflow.test.sh @@ -154,6 +154,7 @@ draft_step = jobs.fetch("create-draft-release").fetch("steps").find { |step| ste draft_run = draft_step&.fetch("run", nil) fail("Draft Release creation must write generated release notes") unless draft_run&.include?("--notes-file") fail("Draft Release reuse must validate target commit and prerelease state") unless draft_run&.include?("targetCommitish") && draft_run.include?("isPrerelease") +fail("Draft Release creation must derive its target from the existing tag") if draft_run&.include?("--target") github_steps = jobs.fetch("publish-github").fetch("steps") github_check = github_steps.find { |step| step["name"] == "Verify Draft assets match the candidate" }