Nightly Promotion #26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Nightly Promotion | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' | |
| workflow_dispatch: | |
| jobs: | |
| prepare-promotion-pr: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Configure Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Verify nightly CI status | |
| id: ci-status | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const cutoffMs = Date.now() - 24 * 60 * 60 * 1000; | |
| const { data } = await github.rest.actions.listWorkflowRuns({ | |
| owner, | |
| repo, | |
| workflow_id: "ci.yml", | |
| branch: "nightly", | |
| status: "completed", | |
| per_page: 1, | |
| }); | |
| if (!data.workflow_runs.length) { | |
| core.info("No completed nightly CI runs found."); | |
| core.setOutput("promote", "false"); | |
| return; | |
| } | |
| const run = data.workflow_runs[0]; | |
| const updatedAt = new Date(run.updated_at).getTime(); | |
| if (run.conclusion !== "success") { | |
| core.info(`Latest nightly CI run conclusion is '${run.conclusion}'.`); | |
| core.setOutput("promote", "false"); | |
| return; | |
| } | |
| if (updatedAt < cutoffMs) { | |
| core.info("Latest nightly CI run is older than 24 hours."); | |
| core.setOutput("promote", "false"); | |
| return; | |
| } | |
| core.info(`Latest nightly CI run #${run.id} succeeded at ${run.updated_at}.`); | |
| core.setOutput("promote", "true"); | |
| - name: Check for differences | |
| id: diff | |
| if: steps.ci-status.outputs.promote == 'true' | |
| run: | | |
| git fetch origin production nightly | |
| if [ "$(git rev-list --count origin/production..origin/nightly)" -eq 0 ]; then | |
| echo "No changes between nightly and production." | |
| echo "promote=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Changes detected between nightly and production." | |
| echo "promote=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| shell: bash | |
| - name: Skip promotion (nightly CI not green) | |
| if: steps.ci-status.outputs.promote != 'true' | |
| run: | | |
| echo "Skipping promotion: no successful nightly CI run in the past 24 hours." | |
| - name: Skip promotion (no changes) | |
| if: steps.ci-status.outputs.promote == 'true' && steps.diff.outputs.promote != 'true' | |
| run: | | |
| echo "Skipping promotion: nightly and production are already in sync." | |
| - name: Prepare promotion branch | |
| if: steps.ci-status.outputs.promote == 'true' && steps.diff.outputs.promote == 'true' | |
| run: | | |
| git checkout origin/nightly | |
| git checkout -B promotion/nightly | |
| git push origin promotion/nightly --force | |
| - name: Open or update promotion pull request | |
| if: steps.ci-status.outputs.promote == 'true' && steps.diff.outputs.promote == 'true' | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const headBranch = "promotion/nightly"; | |
| const baseBranch = "production"; | |
| const { data: existing } = await github.rest.pulls.list({ | |
| owner, | |
| repo, | |
| state: "open", | |
| head: `${owner}:${headBranch}`, | |
| base: baseBranch, | |
| }); | |
| if (existing.length > 0) { | |
| core.info(`Promotion PR already open: #${existing[0].number}`); | |
| return; | |
| } | |
| const { data: pr } = await github.rest.pulls.create({ | |
| owner, | |
| repo, | |
| head: headBranch, | |
| base: baseBranch, | |
| title: "Promote nightly to production", | |
| body: [ | |
| "Automated promotion from `nightly` to `production`.", | |
| "", | |
| "Please review and merge when ready." | |
| ].join("\n"), | |
| }); | |
| core.info(`Opened promotion PR #${pr.number}`); |