Bump Emulator Version #261
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: Bump Emulator Version | |
| on: | |
| schedule: | |
| # Run daily at midnight UTC | |
| - cron: '0 0 * * *' | |
| # Allow manual triggering | |
| workflow_dispatch: | |
| jobs: | |
| bump-emulator-version: | |
| name: Check for new emulator version | |
| runs-on: ubuntu-latest | |
| permissions: | |
| issues: write | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Check out the repo | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: master | |
| - name: Get current version and check for newer versions | |
| id: version-check | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const { execSync } = require('child_process'); | |
| // Read the Dockerfile | |
| const dockerfile = fs.readFileSync('Dockerfile', 'utf8'); | |
| // Extract the current version | |
| const versionMatch = dockerfile.match(/FROM gcr\.io\/cloud-spanner-emulator\/emulator:([0-9.]+)/); | |
| if (!versionMatch) { | |
| throw new Error('Could not find emulator version in Dockerfile'); | |
| } | |
| const currentVersion = versionMatch[1]; | |
| console.log(`Current version: ${currentVersion}`); | |
| // Set output for current version | |
| core.setOutput('current_version', currentVersion); | |
| // Fetch versions from Google Container Registry | |
| const response = await fetch('https://gcr.io/v2/cloud-spanner-emulator/emulator/tags/list'); | |
| const data = await response.json(); | |
| // Filter for semantic version tags (x.y.z format) | |
| const allVersions = data.tags.filter(tag => /^[0-9]+\.[0-9]+\.[0-9]+$/.test(tag)); | |
| // Sort versions | |
| allVersions.sort((a, b) => { | |
| const aParts = a.split('.').map(Number); | |
| const bParts = b.split('.').map(Number); | |
| for (let i = 0; i < 3; i++) { | |
| if (aParts[i] !== bParts[i]) { | |
| return aParts[i] - bParts[i]; | |
| } | |
| } | |
| return 0; | |
| }); | |
| // Find versions newer than current version | |
| const newerVersions = allVersions.filter(version => { | |
| const vParts = version.split('.').map(Number); | |
| const cParts = currentVersion.split('.').map(Number); | |
| for (let i = 0; i < 3; i++) { | |
| if (vParts[i] !== cParts[i]) { | |
| return vParts[i] > cParts[i]; | |
| } | |
| } | |
| return false; | |
| }); | |
| if (newerVersions.length === 0) { | |
| console.log('No newer versions found.'); | |
| core.setOutput('has_newer_versions', 'false'); | |
| } else { | |
| // Get only the next version (first one after sorting) | |
| const nextVersion = newerVersions[0]; | |
| console.log(`Next version found: ${nextVersion}`); | |
| core.setOutput('has_newer_versions', 'true'); | |
| core.setOutput('next_version', nextVersion); | |
| // For backward compatibility | |
| core.setOutput('newer_versions', nextVersion); | |
| core.setOutput('latest_version', nextVersion); | |
| } | |
| - name: Process next version | |
| id: process-versions | |
| if: steps.version-check.outputs.has_newer_versions == 'true' | |
| env: | |
| current_version: ${{ steps.version-check.outputs.current_version }} | |
| next_version: ${{ steps.version-check.outputs.next_version }} | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const { execSync } = require('child_process'); | |
| const currentVersion = process.env.current_version; | |
| const nextVersion = process.env.next_version; | |
| console.log(`Processing next version: ${nextVersion}`); | |
| let updated = false; | |
| const failedVersions = {}; | |
| // Update Dockerfile with the next version | |
| console.log(`Updating Dockerfile to version ${nextVersion}...`); | |
| const dockerfile = fs.readFileSync('Dockerfile', 'utf8'); | |
| const updatedDockerfile = dockerfile.replace( | |
| new RegExp(`FROM gcr.io/cloud-spanner-emulator/emulator:${currentVersion}`), | |
| `FROM gcr.io/cloud-spanner-emulator/emulator:${nextVersion}` | |
| ); | |
| fs.writeFileSync('Dockerfile', updatedDockerfile); | |
| // Verify the updated Dockerfile | |
| console.log(`Verifying updated Dockerfile with version ${nextVersion}...`); | |
| try { | |
| execSync('bash verify.bash', { stdio: 'inherit' }); | |
| console.log(`Verification successful for version ${nextVersion}`); | |
| updated = true; | |
| } catch (error) { | |
| console.log(`Verification failed for version ${nextVersion}`); | |
| // Mark this version as failed | |
| failedVersions[`version_${nextVersion}`] = 'failed'; | |
| // Revert the Dockerfile change | |
| fs.writeFileSync('Dockerfile', dockerfile); | |
| } | |
| if (updated) { | |
| console.log(`Successfully updated to version ${nextVersion}`); | |
| core.setOutput('updated', 'true'); | |
| core.setOutput('updated_version', nextVersion); | |
| } else { | |
| console.log('No successful update'); | |
| core.setOutput('updated', 'false'); | |
| } | |
| // Output failed version | |
| for (const [key, value] of Object.entries(failedVersions)) { | |
| core.setOutput(key, value); | |
| } | |
| - name: Create issue for failed version verification | |
| if: steps.version-check.outputs.has_newer_versions == 'true' && steps.process-versions.outputs.updated != 'true' | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const nextVersion = process.env.NEXT_VERSION; | |
| const issueTitle = `Emulator version update verification failed: ${nextVersion}`; | |
| console.log(`Checking for existing issues for version: ${nextVersion}`); | |
| // Search for existing open issues with the same title | |
| const existingIssues = await github.rest.search.issuesAndPullRequests({ | |
| q: `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open "${issueTitle}"` | |
| }); | |
| if (existingIssues.data.total_count > 0) { | |
| console.log(`Found existing issue for version ${nextVersion}, skipping creation`); | |
| return; | |
| } | |
| console.log(`Creating issue for failed version: ${nextVersion}`); | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: issueTitle, | |
| body: `The verification of the next emulator version ${nextVersion} failed. Please check the [workflow run](${process.env.GITHUB_SERVER_URL}/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.` | |
| }); | |
| env: | |
| NEXT_VERSION: ${{ steps.version-check.outputs.next_version }} | |
| - name: Check for existing PRs and create new one if needed | |
| if: steps.process-versions.outputs.updated == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.CREATE_PR_PAT }} | |
| CURRENT_VERSION: ${{ steps.version-check.outputs.current_version }} | |
| UPDATED_VERSION: ${{ steps.process-versions.outputs.updated_version }} | |
| run: | | |
| # Check for existing PRs with the same title | |
| PR_TITLE="chore: update emulator version to $UPDATED_VERSION" | |
| EXISTING_PR=$(gh pr list --state open --search "$PR_TITLE" --json number --jq '.[0].number') | |
| if [ -n "$EXISTING_PR" ]; then | |
| echo "Found existing PR #$EXISTING_PR with the same title, skipping PR creation" | |
| exit 0 | |
| fi | |
| echo "No existing PR found, creating a new one" | |
| # Create and checkout a new branch | |
| git branch -d bump-base-version &>/dev/null || true | |
| git checkout -b bump-base-version | |
| # Commit the changes | |
| git config --global user.name "GitHub Actions" | |
| git config --global user.email "[email protected]" | |
| git commit -am "chore: update emulator version to $UPDATED_VERSION" | |
| # Push the branch (force push to handle case where branch exists remotely) | |
| git push -f -u origin bump-base-version | |
| # Create the PR | |
| gh pr create \ | |
| --title "$PR_TITLE" \ | |
| --body "This PR updates the Cloud Spanner emulator version from $CURRENT_VERSION to $UPDATED_VERSION. | |
| Original Release Notes: https://github.com/GoogleCloudPlatform/cloud-spanner-emulator/releases/tag/v$UPDATED_VERSION | |
| This PR was automatically generated by the check-emulator-version workflow." \ | |
| --base master |