From 6a73288ce34fb469617e0b9e240685babbac6d7d Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Fri, 12 Dec 2025 21:05:49 -0800 Subject: [PATCH] ci: make nightly release happen automatically every night (#7410) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Makes the existing "Release: Version Bump" workflow run at 00:00 UTC every day. ## Details - concurrency keeps only one run active while manual dispatch remains available for ad-hoc bumps. - inputs are normalized inside the workflow so scheduled runs (which lack `workflow_dispatch` inputs) safely fall back to `patch`/`main`, and the version bump + PR formatting steps only use the optional `pre_release` flag when it is provided - each nightly invocation closes any lingering bot-authored `version-bump-*` PRs/branches before creating a new patch PR, preventing stale locale bumps from conflicting - checkout now disables credential persistence and `pnpm/action-setup` is pinned to a commit for supply-chain safety. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7410-ci-make-nightly-release-happen-automatically-every-night-2c76d73d3650813a9e02ee8878370929) by [Unito](https://www.unito.io) --- .github/workflows/release-version-bump.yaml | 124 ++++++++++++++++++-- 1 file changed, 115 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-version-bump.yaml b/.github/workflows/release-version-bump.yaml index 766f5d406..ca08e25bd 100644 --- a/.github/workflows/release-version-bump.yaml +++ b/.github/workflows/release-version-bump.yaml @@ -20,6 +20,13 @@ on: required: true default: 'main' type: string + schedule: + # 00:00 UTC ≈ 4:00 PM PST / 5:00 PM PDT on the previous calendar day + - cron: '0 0 * * *' + +concurrency: + group: release-version-bump + cancel-in-progress: true jobs: bump-version: @@ -29,15 +36,99 @@ jobs: pull-requests: write steps: + - name: Prepare inputs + id: prepared-inputs + shell: bash + env: + RAW_VERSION_TYPE: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version_type || '' }} + RAW_PRE_RELEASE: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.pre_release || '' }} + RAW_BRANCH: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.branch || '' }} + run: | + set -euo pipefail + VERSION_TYPE="$RAW_VERSION_TYPE" + PRE_RELEASE="$RAW_PRE_RELEASE" + TARGET_BRANCH="$RAW_BRANCH" + + if [[ -z "$VERSION_TYPE" ]]; then + VERSION_TYPE='patch' + fi + + if [[ -z "$TARGET_BRANCH" ]]; then + TARGET_BRANCH='main' + fi + + { + echo "version_type=$VERSION_TYPE" + echo "pre_release=$PRE_RELEASE" + echo "branch=$TARGET_BRANCH" + } >> "$GITHUB_OUTPUT" + + - name: Close stale nightly version bump PRs + if: github.event_name == 'schedule' + uses: actions/github-script@v7 + with: + github-token: ${{ github.token }} + script: | + const prefix = 'version-bump-' + const closed = [] + const prs = await github.paginate(github.rest.pulls.list, { + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 100 + }) + + for (const pr of prs) { + if (!pr.head?.ref?.startsWith(prefix)) { + continue + } + + if (pr.user?.login !== 'github-actions[bot]') { + continue + } + + // Only clean up stale nightly PRs targeting main. + // Adjust here if other target branches should be cleaned. + if (pr.base?.ref !== 'main') { + continue + } + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + state: 'closed' + }) + + try { + await github.rest.git.deleteRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${pr.head.ref}` + }) + } catch (error) { + if (![404, 422].includes(error.status)) { + throw error + } + } + + closed.push(pr.number) + } + + core.info(`Closed ${closed.length} stale PR(s).`) + - name: Checkout repository uses: actions/checkout@v5 with: - ref: ${{ github.event.inputs.branch }} + ref: ${{ steps.prepared-inputs.outputs.branch }} fetch-depth: 0 + persist-credentials: false - name: Validate branch exists + env: + TARGET_BRANCH: ${{ steps.prepared-inputs.outputs.branch }} run: | - BRANCH="${{ github.event.inputs.branch }}" + BRANCH="$TARGET_BRANCH" if ! git show-ref --verify --quiet "refs/heads/$BRANCH" && ! git show-ref --verify --quiet "refs/remotes/origin/$BRANCH"; then echo "❌ Branch '$BRANCH' does not exist" echo "" @@ -51,7 +142,7 @@ jobs: echo "✅ Branch '$BRANCH' exists" - name: Install pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 with: version: 10 @@ -62,16 +153,31 @@ jobs: - name: Bump version id: bump-version + env: + VERSION_TYPE: ${{ steps.prepared-inputs.outputs.version_type }} + PRE_RELEASE: ${{ steps.prepared-inputs.outputs.pre_release }} run: | - pnpm version ${{ github.event.inputs.version_type }} --preid ${{ github.event.inputs.pre_release }} --no-git-tag-version + set -euo pipefail + if [[ -n "$PRE_RELEASE" && ! "$VERSION_TYPE" =~ ^pre(major|minor|patch)$ && "$VERSION_TYPE" != "prerelease" ]]; then + echo "❌ pre_release was provided but version_type='$VERSION_TYPE' does not support --preid" + exit 1 + fi + if [[ -n "$PRE_RELEASE" ]]; then + pnpm version "$VERSION_TYPE" --preid "$PRE_RELEASE" --no-git-tag-version + else + pnpm version "$VERSION_TYPE" --no-git-tag-version + fi + NEW_VERSION=$(node -p "require('./package.json').version") - echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "NEW_VERSION=$NEW_VERSION" >> "$GITHUB_OUTPUT" - name: Format PR string id: capitalised + env: + VERSION_TYPE: ${{ steps.prepared-inputs.outputs.version_type }} run: | - CAPITALISED_TYPE=${{ github.event.inputs.version_type }} - echo "capitalised=${CAPITALISED_TYPE@u}" >> $GITHUB_OUTPUT + CAPITALISED_TYPE="$VERSION_TYPE" + echo "capitalised=${CAPITALISED_TYPE@u}" >> "$GITHUB_OUTPUT" - name: Create Pull Request uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e @@ -82,8 +188,8 @@ jobs: body: | ${{ steps.capitalised.outputs.capitalised }} version increment to ${{ steps.bump-version.outputs.NEW_VERSION }} - **Base branch:** `${{ github.event.inputs.branch }}` + **Base branch:** `${{ steps.prepared-inputs.outputs.branch }}` branch: version-bump-${{ steps.bump-version.outputs.NEW_VERSION }} - base: ${{ github.event.inputs.branch }} + base: ${{ steps.prepared-inputs.outputs.branch }} labels: | Release