fix(release): harden draft publishing flow
This commit is contained in:
parent
92d4c4cdf9
commit
240bc81d0a
2 changed files with 67 additions and 12 deletions
44
.github/workflows/release.yml
vendored
44
.github/workflows/release.yml
vendored
|
|
@ -9,9 +9,14 @@ on:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: release-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -56,7 +61,7 @@ jobs:
|
||||||
--repo "$GITHUB_REPOSITORY" \
|
--repo "$GITHUB_REPOSITORY" \
|
||||||
--title "$TAG" \
|
--title "$TAG" \
|
||||||
--generate-notes \
|
--generate-notes \
|
||||||
--draft=false 2>/dev/null || echo "Release $TAG already exists, skipping creation"
|
--draft=true 2>/dev/null || echo "Release $TAG already exists, skipping creation"
|
||||||
|
|
||||||
- name: Upload dist artifact
|
- name: Upload dist artifact
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
|
|
@ -69,6 +74,7 @@ jobs:
|
||||||
|
|
||||||
prepare-runtime:
|
prepare-runtime:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 90
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -84,7 +90,7 @@ jobs:
|
||||||
--repo "$GITHUB_REPOSITORY" \
|
--repo "$GITHUB_REPOSITORY" \
|
||||||
--title "$TAG" \
|
--title "$TAG" \
|
||||||
--generate-notes \
|
--generate-notes \
|
||||||
--draft=false 2>/dev/null || echo "Release $TAG already exists, skipping creation"
|
--draft=true 2>/dev/null || echo "Release $TAG already exists, skipping creation"
|
||||||
|
|
||||||
- name: Skip runtime asset preparation for manual builds
|
- name: Skip runtime asset preparation for manual builds
|
||||||
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
|
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
|
@ -216,6 +222,7 @@ jobs:
|
||||||
|
|
||||||
release-mac:
|
release-mac:
|
||||||
needs: [build, prepare-runtime]
|
needs: [build, prepare-runtime]
|
||||||
|
timeout-minutes: 90
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -318,13 +325,13 @@ jobs:
|
||||||
[ -f "$f" ] || continue
|
[ -f "$f" ] || continue
|
||||||
echo "Uploading: $f"
|
echo "Uploading: $f"
|
||||||
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
||||||
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1) || \
|
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1)
|
||||||
echo "WARNING: failed to upload $f, continuing..."
|
|
||||||
done
|
done
|
||||||
|
|
||||||
release-win:
|
release-win:
|
||||||
needs: [build, prepare-runtime]
|
needs: [build, prepare-runtime]
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -416,13 +423,13 @@ jobs:
|
||||||
[ -f "$f" ] || continue
|
[ -f "$f" ] || continue
|
||||||
echo "Uploading: $f"
|
echo "Uploading: $f"
|
||||||
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
||||||
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1) || \
|
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1)
|
||||||
echo "WARNING: failed to upload $f, continuing..."
|
|
||||||
done
|
done
|
||||||
|
|
||||||
release-linux:
|
release-linux:
|
||||||
needs: [build, prepare-runtime]
|
needs: [build, prepare-runtime]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 90
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|
@ -516,13 +523,13 @@ jobs:
|
||||||
[ -f "$f" ] || continue
|
[ -f "$f" ] || continue
|
||||||
echo "Uploading: $f"
|
echo "Uploading: $f"
|
||||||
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1 || \
|
||||||
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1) || \
|
(sleep 5 && gh release upload "$TAG" "$f" --repo "$GITHUB_REPOSITORY" --clobber 2>&1)
|
||||||
echo "WARNING: failed to upload $f, continuing..."
|
|
||||||
done
|
done
|
||||||
|
|
||||||
upload-stable-links:
|
upload-stable-links:
|
||||||
needs: [release-mac, release-win, release-linux]
|
needs: [release-mac, release-win, release-linux]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -533,7 +540,6 @@ jobs:
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||||
REPO="${GITHUB_REPOSITORY}"
|
REPO="${GITHUB_REPOSITORY}"
|
||||||
DOWNLOAD_BASE="https://github.com/${REPO}/releases/download/v${VERSION}"
|
|
||||||
TMP_DIR="$(mktemp -d)"
|
TMP_DIR="$(mktemp -d)"
|
||||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
|
||||||
|
|
@ -551,7 +557,11 @@ jobs:
|
||||||
for STABLE_NAME in "${!FILES[@]}"; do
|
for STABLE_NAME in "${!FILES[@]}"; do
|
||||||
VERSIONED_NAME="${FILES[$STABLE_NAME]}"
|
VERSIONED_NAME="${FILES[$STABLE_NAME]}"
|
||||||
echo "Downloading ${VERSIONED_NAME} -> ${STABLE_NAME}"
|
echo "Downloading ${VERSIONED_NAME} -> ${STABLE_NAME}"
|
||||||
curl -fSL -o "${TMP_DIR}/${VERSIONED_NAME}" "${DOWNLOAD_BASE}/${VERSIONED_NAME}"
|
gh release download "v${VERSION}" \
|
||||||
|
--repo "$REPO" \
|
||||||
|
--pattern "${VERSIONED_NAME}" \
|
||||||
|
--dir "$TMP_DIR" \
|
||||||
|
--clobber
|
||||||
cp "${TMP_DIR}/${VERSIONED_NAME}" "${TMP_DIR}/${STABLE_NAME}"
|
cp "${TMP_DIR}/${VERSIONED_NAME}" "${TMP_DIR}/${STABLE_NAME}"
|
||||||
gh release upload "v${VERSION}" "${TMP_DIR}/${STABLE_NAME}" --repo "$REPO" --clobber
|
gh release upload "v${VERSION}" "${TMP_DIR}/${STABLE_NAME}" --repo "$REPO" --clobber
|
||||||
done
|
done
|
||||||
|
|
@ -578,7 +588,11 @@ jobs:
|
||||||
|
|
||||||
download_asset() {
|
download_asset() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
curl -fSL -o "$name" "https://github.com/${REPO}/releases/download/${TAG}/${name}"
|
gh release download "${TAG}" \
|
||||||
|
--repo "${REPO}" \
|
||||||
|
--pattern "$name" \
|
||||||
|
--dir . \
|
||||||
|
--clobber
|
||||||
}
|
}
|
||||||
|
|
||||||
# Canonical Windows feed
|
# Canonical Windows feed
|
||||||
|
|
@ -636,3 +650,11 @@ jobs:
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
gh release upload "${TAG}" latest.yml latest-linux.yml latest-mac.yml --repo "${REPO}" --clobber
|
gh release upload "${TAG}" latest.yml latest-linux.yml latest-mac.yml --repo "${REPO}" --clobber
|
||||||
|
|
||||||
|
- name: Publish release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
TAG="${GITHUB_REF#refs/tags/}"
|
||||||
|
gh release edit "${TAG}" --repo "${GITHUB_REPOSITORY}" --draft=false --latest
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,37 @@ async function downloadFile(url, destinationPath) {
|
||||||
await pipeline(Readable.fromWeb(response.body), fs.createWriteStream(destinationPath));
|
await pipeline(Readable.fromWeb(response.body), fs.createWriteStream(destinationPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadReleaseAssetWithGh(runtimeLock, releaseTag, asset, destinationPath) {
|
||||||
|
if (!process.env.GH_TOKEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
|
||||||
|
const result = spawnSync(
|
||||||
|
'gh',
|
||||||
|
[
|
||||||
|
'release',
|
||||||
|
'download',
|
||||||
|
releaseTag,
|
||||||
|
'--repo',
|
||||||
|
runtimeLock.releaseRepository,
|
||||||
|
'--pattern',
|
||||||
|
asset.file,
|
||||||
|
'--dir',
|
||||||
|
path.dirname(destinationPath),
|
||||||
|
'--clobber',
|
||||||
|
],
|
||||||
|
{
|
||||||
|
cwd: repoRoot,
|
||||||
|
stdio: 'inherit',
|
||||||
|
shell: false,
|
||||||
|
env: process.env,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.status === 0 && fs.existsSync(destinationPath);
|
||||||
|
}
|
||||||
|
|
||||||
function extractArchive(archivePath, extractDir, archiveKind) {
|
function extractArchive(archivePath, extractDir, archiveKind) {
|
||||||
fs.mkdirSync(extractDir, { recursive: true });
|
fs.mkdirSync(extractDir, { recursive: true });
|
||||||
|
|
||||||
|
|
@ -208,7 +239,9 @@ async function stageRuntime(options) {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
`Downloading ${asset.file} from ${runtimeLock.releaseRepository}@${releaseTag}\n`
|
`Downloading ${asset.file} from ${runtimeLock.releaseRepository}@${releaseTag}\n`
|
||||||
);
|
);
|
||||||
await downloadFile(url, archivePath);
|
if (!downloadReleaseAssetWithGh(runtimeLock, releaseTag, asset, archivePath)) {
|
||||||
|
await downloadFile(url, archivePath);
|
||||||
|
}
|
||||||
|
|
||||||
process.stdout.write(`Extracting ${asset.file}\n`);
|
process.stdout.write(`Extracting ${asset.file}\n`);
|
||||||
extractArchive(archivePath, extractDir, asset.archiveKind);
|
extractArchive(archivePath, extractDir, asset.archiveKind);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue