Release #100
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: Release | |
| on: | |
| workflow_dispatch: | |
| jobs: | |
| # 1. We look at the target branch and figure out whether this should be a BUILD | |
| # release or a patch release | |
| get-update-type: | |
| # If the context.ref is refs/heads/main we want to do a standard release | |
| # If the context.ref is refs/heads/* we want to do a patch release | |
| # If the context.ref is some other ref, we want to fail | |
| # Selecting a tag github.ref becomes e.g.: refs/tags/4.1.9.0 | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: # This means this can later be referenced with needs.get-update-type.outputs.update-type | |
| update-type: ${{ steps.update-type.outputs.result }} | |
| steps: | |
| - name: Calculate update type | |
| uses: actions/github-script@v7 | |
| id: update-type | |
| with: | |
| script: | | |
| if (context.ref == "refs/heads/main") { | |
| return "BUILD"; | |
| } else if (context.ref.startsWith("refs/heads/")) { | |
| return "PATCH"; | |
| } else { | |
| throw new Error("Target must be a patch branch or main, but was: " + context.ref); | |
| } | |
| result-encoding: string | |
| - name: Print update type | |
| shell: bash | |
| run: echo "${{steps.update-type.outputs.result}}" | |
| # 2. In parallel, we run: | |
| # a) all the tests | |
| # b) the mixed-mode tests | |
| test: | |
| needs: [get-update-type] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4.2.2 | |
| - name: Setup Base Environment | |
| id: setup-base | |
| uses: ./actions/setup-base-env | |
| - name: Setup FDB | |
| uses: ./actions/setup-fdb | |
| # Increment the version here so that the version used in tests matches the eventually published version. | |
| # This is actually important in order to correctly choose appropriate external server versions during | |
| # mixed mode tests (see: https://github.com/FoundationDB/fdb-record-layer/issues/3449) | |
| - name: Increment version | |
| shell: bash | |
| run: python build/versionutils.py gradle.properties --increment -u ${{ needs.get-update-type.outputs.update-type }} | |
| - name: Run Gradle Test | |
| uses: ./actions/gradle-test | |
| with: | |
| gradle_args: -PreleaseBuild=true -PpublishBuild=true | |
| # 2. b) We run the mixed mode tests | |
| mixed-mode-test: | |
| needs: [get-update-type] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4.2.2 | |
| - name: Setup Base Environment | |
| uses: ./actions/setup-base-env | |
| - name: Setup FDB | |
| uses: ./actions/setup-fdb | |
| - name: Run Gradle Test | |
| uses: ./actions/gradle-test | |
| with: | |
| gradle_command: mixedModeTest | |
| gradle_args: -PreleaseBuild=false -PpublishBuild=false | |
| # We don't commit the incremented version, but we use this to know the version when generating | |
| # the resulting markdown | |
| - name: Increment version | |
| shell: bash | |
| run: python build/versionutils.py gradle.properties --increment -u ${{ needs.get-update-type.outputs.update-type }} | |
| - name: Get new version | |
| id: get_new_version | |
| shell: bash | |
| run: | | |
| echo "version=$(python build/versionutils.py gradle.properties)" >> "$GITHUB_OUTPUT" | |
| - name: Create markdown | |
| shell: bash | |
| run: python build/publish-mixed-mode-results.py ${{ steps.get_new_version.outputs.version }} --run-link ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} --output mixed-mode-results.md | |
| - name: Preview results | |
| shell: bash | |
| run: cat mixed-mode-results.md >> $GITHUB_STEP_SUMMARY | |
| # I think this _needs_ to be done at this level, rather than in the action | |
| # so that "mixed-mode-results" gets passed around correctly | |
| - name: Upload mixed mode results | |
| id: mixed_mode_results | |
| uses: actions/upload-artifact@v4.6.0 | |
| with: | |
| name: mixed-mode-results | |
| path: mixed-mode-results.md | |
| # 3. Update the version in the repo, update the release notes, tag the commit | |
| # and publish the artifacts, and if this is a BUILD release generate the documentation | |
| publish: | |
| needs: [test, mixed-mode-test, get-update-type] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| packages: write | |
| pull-requests: write # We create a pull request if committing the release notes updates fails | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4.2.2 | |
| with: | |
| ssh-key: ${{ secrets.DEPLOY_KEY }} | |
| fetch-tags: true | |
| # fetch all the history to make sure that we have the last release | |
| # I tried fetching part of the history, but I just couldn't get it to work, and fetching all still takes like 5s | |
| fetch-depth: 0 | |
| - name: Configure git | |
| shell: bash | |
| run: | | |
| git config --global user.name 'FoundationDB CI' | |
| git config --global user.email 'foundationdb_ci@apple.com' | |
| - name: Setup Base Environment | |
| uses: ./actions/setup-base-env | |
| # Push a version bump back to main. There are failure scenarios that can result | |
| # in published artifacts but an erroneous build, so it's safer to bump the version | |
| # at the beginning | |
| - name: Increment version | |
| shell: bash | |
| run: python build/versionutils.py gradle.properties --increment --commit -u ${{ needs.get-update-type.outputs.update-type }} | |
| - name: Get new version | |
| id: get_new_version | |
| shell: bash | |
| run: | | |
| echo "version=$(python build/versionutils.py gradle.properties)" >> "$GITHUB_OUTPUT" | |
| # We also want to push the tag, because that will be used for the next release's release notes | |
| - name: Create tag | |
| shell: bash | |
| run: git tag -m "Release ${{ steps.get_new_version.outputs.version }}" -f "${{ steps.get_new_version.outputs.version }}" | |
| # We want to do this before anything else, because if the later steps fail, we want to make sure that the full | |
| # change log includes all changes, even if they reference a release that was never actually published. | |
| - name: Download mixed mode results | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: mixed-mode-results | |
| - name: echo results | |
| shell: bash | |
| run: cat mixed-mode-results.md || ls | |
| - name: Update release notes | |
| shell: bash | |
| run: | | |
| python ./build/create_release_notes.py \ | |
| --config ./build/release-notes-config.json \ | |
| --release-notes-md docs/sphinx/source/ReleaseNotes.md \ | |
| --skip-commit $(git log -n 1 --format=%H HEAD) \ | |
| --repository ${{ github.repository }} \ | |
| --commit \ | |
| --mixed-mode-results mixed-mode-results.md \ | |
| --version ${{ steps.get_new_version.outputs.version }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| # We move the tag to after the release notes are updated so that later steps (i.e. sphinx) will pick up the udpated | |
| # release notes | |
| - name: Move tag to HEAD | |
| shell: bash | |
| run: git tag -m "Release ${{ steps.get_new_version.outputs.version }}" -f "${{ steps.get_new_version.outputs.version }}" | |
| # push the changes to gradle.properties, the release notes, and the tag as one operation, so if it fails, | |
| # it will be as if the release never did anything | |
| - name: Push Version Update | |
| shell: bash | |
| run: git push origin HEAD "${{ steps.get_new_version.outputs.version }}" | |
| - name: Publish Artifacts | |
| uses: ./actions/run-gradle | |
| with: | |
| gradle_command: publish closeAndReleaseStagingRepositories -PreleaseBuild=true -PpublishBuild=true -PgithubPublish=true -PcentralPublish=true | |
| env: | |
| ORG_GRADLE_PROJECT_signingKey: ${{ secrets.GPG_PRIVATE_KEY }} | |
| ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.GPG_PASSPHRASE }} | |
| ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} | |
| ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Post release: Update various files which reference version | |
| # Updating the yaml files has to be done after the tests complete, or it will mark tests as failing that aren't | |
| # supported by the previous version. | |
| - name: Update YAML test file versions | |
| uses: ./actions/run-gradle | |
| with: | |
| gradle_command: updateYamsql -PreleaseBuild=true | |
| - name: Commit YAML updates | |
| shell: bash | |
| run: python ./build/commit_yamsql_updates.py "${{ steps.get_new_version.outputs.version }}" | |
| - name: Push Updates | |
| id: push_updates | |
| shell: bash | |
| run: git push origin | |
| # Continue the build (including downstream steps). If the push fails, we'll create a PR | |
| continue-on-error: true | |
| - name: Create Merge PR if conflict | |
| # Only create the PR if we've otherwise been successful, but the push failed. Note that | |
| # we're checking the .outcome of the push step, which is applied before continue-on-error. | |
| if: success() && steps.push_updates.outcome == 'failure' | |
| uses: peter-evans/create-pull-request@bb88e27d3f9cc69c8bc689eba126096c6fe3dded | |
| id: pr_on_conflict | |
| with: | |
| branch: release-build | |
| branch-suffix: timestamp | |
| title: "Updates for ${{ steps.get_new_version.outputs.version }} release" | |
| sign-commits: true | |
| body: | | |
| Updates from release for version ${{ steps.get_new_version.outputs.version }}. Conflicts during the build prevented automatic updating. Please resolve conflicts by checking out the current branch, merging, and then deleting this branch. | |
| # Creating the PR can change the current branch. Explicitly check out the tag here for downstream builds | |
| - name: Revert to tag | |
| shell: bash | |
| run: git checkout "${{ steps.get_new_version.outputs.version }}" | |
| # Build documentation (We don't do any of the remaining steps for patch releases) | |
| - name: LOG update type | |
| shell: bash | |
| run: echo "${{ needs.get-update-type.outputs.update-type }}" | |
| - name: Cache Python Environment | |
| if: needs.get-update-type.outputs.update-type == 'BUILD' | |
| uses: actions/cache@v4 | |
| with: | |
| path: docs/sphinx/.venv | |
| key: ${{ runner.os }}-sphinx-python-${{ steps.setup-base.outputs.python-version }}-${{ hashFiles('docs/sphinx/requirements.txt') }} | |
| - name: Build Documentation Site | |
| if: needs.get-update-type.outputs.update-type == 'BUILD' | |
| uses: ./actions/run-gradle | |
| with: | |
| gradle_command: documentationSite -PreleaseBuild=true | |
| - name: Upload Documentation | |
| if: needs.get-update-type.outputs.update-type == 'BUILD' | |
| id: doc_upload | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: docs/sphinx/.out/html/ | |
| # 4. We deploy the documentation from (3) to github pages, unless this is a patch release | |
| # deploy_docs is a separate job so that it can run with different permissions from | |
| # everything else, but it depends on publish so, it will always run last | |
| deploy_docs: | |
| runs-on: ubuntu-latest | |
| needs: [publish] | |
| if: needs.get-update-type.outputs.update-type == 'BUILD' | |
| permissions: | |
| pages: write | |
| id-token: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.doc_upload.outputs.page_url }} | |
| steps: | |
| - name: LOG update type | |
| shell: bash | |
| run: echo "${{ needs.get-update-type.outputs.update-type }}" | |
| - name: Deploy Documentation | |
| uses: actions/deploy-pages@v4 |