| name: finalize_release | |
| # Workflow added after https://github.com/apache/beam/commit/4183e747becebd18becee5fff547af365910fc9c | |
| # If help is needed debugging issues, you can view the release guide at that commit for guidance on how to do this manually. | |
| # (https://github.com/apache/beam/blob/4183e747becebd18becee5fff547af365910fc9c/website/www/site/content/en/contribute/release-guide.md) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| RELEASE: | |
| description: Beam version of current release (e.g. 2.XX.0) | |
| required: true | |
| default: '2.XX.0' | |
| RC: | |
| description: Integer RC version for the release that we'd like to finalize (e.g. 3 for RC3) | |
| required: true | |
| PYPI_API_TOKEN: | |
| description: PyPi API token to perform the PyPi upload with | |
| required: false | |
| PUSH_DOCKER_ARTIFACTS: | |
| description: Whether to push SDK docker images to docker hub Apache organization. Should be yes unless you've already completed this step. | |
| required: true | |
| default: 'no' | |
| PUBLISH_PYTHON_ARTIFACTS: | |
| description: Whether to publish the python artifacts into PyPi. Should be yes unless you've already completed this step. | |
| required: true | |
| default: 'no' | |
| REPO_TOKEN: | |
| description: Github Personal Access Token with repo permissions. | |
| required: true | |
| TAG_RELEASE: | |
| description: Whether to tag the release on GitHub. Should be yes unless you've already completed this step. | |
| required: true | |
| default: 'no' | |
| env: | |
| DEVELOCITY_ACCESS_KEY: ${{ secrets.BEAM_DEVELOCITY_ACCESS_KEY }} | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| push_docker_artifacts: | |
| if: ${{github.event.inputs.PUSH_DOCKER_ARTIFACTS == 'yes'}} | |
| runs-on: [self-hosted, ubuntu-24.04, main] | |
| steps: | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USER }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update --yes | |
| sudo apt-get install -y wget | |
| - name: Publish to Docker | |
| env: | |
| RELEASE: "${{ github.event.inputs.RELEASE }}" | |
| RC_NUM: "${{ github.event.inputs.RC }}" | |
| RC_VERSION: "rc${{ github.event.inputs.RC }}" | |
| run: | | |
| echo "Publish SDK docker images to Docker Hub." | |
| echo "================Pull RC Containers from DockerHub===========" | |
| IMAGES=$(docker search apache/beam --format "{{.Name}}" --limit 100) | |
| KNOWN_IMAGES=() | |
| echo "We are using ${RC_VERSION} to push docker images for ${RELEASE}." | |
| while read IMAGE; do | |
| # Try pull verified RC from dockerhub. | |
| if docker pull "${IMAGE}:${RELEASE}${RC_VERSION}" 2>/dev/null ; then | |
| KNOWN_IMAGES+=( $IMAGE ) | |
| fi | |
| done < <(echo "${IMAGES}") | |
| echo "================Confirming Release and RC version===========" | |
| echo "Publishing the following images:" | |
| # Sort by name for easy examination | |
| IFS=$'\n' KNOWN_IMAGES=($(sort <<<"${KNOWN_IMAGES[*]}")) | |
| unset IFS | |
| printf "%s\n" ${KNOWN_IMAGES[@]} | |
| for IMAGE in "${KNOWN_IMAGES[@]}"; do | |
| # Perform a carbon copy of ${RC_VERSION} to dockerhub with a new tag as ${RELEASE}. | |
| docker buildx imagetools create --tag "${IMAGE}:${RELEASE}" "${IMAGE}:${RELEASE}${RC_VERSION}" | |
| # Perform a carbon copy of ${RC_VERSION} to dockerhub with a new tag as latest. | |
| docker buildx imagetools create --tag "${IMAGE}:latest" "${IMAGE}:${RELEASE}" | |
| done | |
| # Flink 2 images have different tagging, add latest tag to latest supported Flink version | |
| echo "================Confirming Runner container Release and RC version===========" | |
| BEAM_FLINK_REPO=apache/beam_flink_job_server | |
| LATEST_FLINK_VERSION=$(wget -qO- https://raw.githubusercontent.com/apache/beam/refs/tags/v${RELEASE}-RC${RC_NUM}/gradle.properties | grep -E flink_versions | tr ',' '\n' | tail -1) | |
| docker buildx imagetools create --tag "${BEAM_FLINK_REPO}:latest" "${BEAM_FLINK_REPO}:${RELEASE}${RC_VERSION}-flink${LATEST_FLINK_VERSION}" | |
| publish_python_artifacts: | |
| if: ${{github.event.inputs.PUBLISH_PYTHON_ARTIFACTS == 'yes'}} | |
| runs-on: [self-hosted, ubuntu-24.04, main] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| persist-credentials: true | |
| - name: Mask PyPi password | |
| run: | | |
| # Workaround for Actions bug - https://github.com/actions/runner/issues/643 | |
| PYPI_PASSWORD=$(jq -r '.inputs.PYPI_PASSWORD' $GITHUB_EVENT_PATH) | |
| echo "::add-mask::$PYPI_PASSWORD" | |
| - name: Validate PyPi id/password | |
| run: | | |
| # Workaround for Actions bug - https://github.com/actions/runner/issues/643 | |
| PYPI_API_TOKEN=$(jq -r '.inputs.PYPI_API_TOKEN' $GITHUB_EVENT_PATH) | |
| echo "::add-mask::$PYPI_API_TOKEN" | |
| if [ "$PYPI_API_TOKEN" == "" ] | |
| then | |
| echo "Must provide a PyPi password to publish artifacts to PyPi" | |
| exit 1 | |
| fi | |
| - name: Setup environment | |
| uses: ./.github/actions/setup-environment-action | |
| with: | |
| python-version: 3.11 | |
| disable-cache: true | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update --yes | |
| sudo apt-get install -y wget | |
| pip install python-dateutil | |
| pip install requests | |
| pip install twine | |
| - name: Deploy to Pypi | |
| env: | |
| RELEASE: "${{ github.event.inputs.RELEASE }}" | |
| GITHUB_EVENT_INPUTS_PYPI_API_TOKEN: ${{ github.event.inputs.PYPI_API_TOKEN }} | |
| run: | | |
| wget -e robots=off -r --no-parent -A tar.gz,whl "https://dist.apache.org/repos/dist/dev/beam/${RELEASE}/python" | |
| cd "dist.apache.org/repos/dist/dev/beam/${RELEASE}/python/" | |
| echo "Will upload the following files to PyPI:" | |
| ls | |
| twine upload * -u __token__ -p "${GITHUB_EVENT_INPUTS_PYPI_API_TOKEN}" | |
| push_git_tags: | |
| if: ${{github.event.inputs.TAG_RELEASE == 'yes'}} | |
| runs-on: [self-hosted, ubuntu-24.04, main] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| token: ${{ github.event.inputs.REPO_TOKEN }} | |
| repository: apache/beam | |
| persist-credentials: true | |
| - name: Set git config | |
| run: | | |
| git config user.name $GITHUB_ACTOR | |
| git config user.email actions@"$RUNNER_NAME".local | |
| - name: Import GPG key | |
| id: import_gpg | |
| uses: crazy-max/ghaction-import-gpg@2dc316deee8e90f13e1a351ab510b4d5bc0c82cd | |
| with: | |
| gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} | |
| - name: Push tags | |
| env: | |
| VERSION_TAG: "v${{ github.event.inputs.RELEASE }}" | |
| RC_TAG: "v${{ github.event.inputs.RELEASE }}-RC${{ github.event.inputs.RC }}" | |
| POST_RELEASE_BRANCH: "release-${{ github.event.inputs.RELEASE }}-postrelease" | |
| STEPS_IMPORT_GPG_OUTPUTS_NAME: ${{steps.import_gpg.outputs.name}} | |
| run: | | |
| # Ensure local tags are in sync. If there's a mismatch, it will tell you. | |
| git fetch --all --tags --prune | |
| # If the tag exists, a commit number is produced, otherwise there's an error. | |
| git rev-list $RC_TAG -n 1 | |
| # Tag for Go SDK | |
| git tag "sdks/$VERSION_TAG" "$RC_TAG"^{} -m "Tagging release" --local-user="${STEPS_IMPORT_GPG_OUTPUTS_NAME}" | |
| git push origin "sdks/$VERSION_TAG" | |
| # Tag for repo root. | |
| git tag "$VERSION_TAG" "$RC_TAG"^{} -m "Tagging release" --local-user="${STEPS_IMPORT_GPG_OUTPUTS_NAME}" | |
| git push origin "$VERSION_TAG" | |
| git checkout -b "$POST_RELEASE_BRANCH" "$VERSION_TAG" | |
| git push origin "$POST_RELEASE_BRANCH" | |
| update_master: | |
| needs: push_git_tags | |
| runs-on: ubuntu-latest | |
| env: | |
| POST_RELEASE_BRANCH: "release-${{ github.event.inputs.RELEASE }}-postrelease" | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v7 | |
| with: | |
| token: ${{ github.event.inputs.REPO_TOKEN }} | |
| ref: master | |
| persist-credentials: true | |
| - name: Set git config | |
| run: | | |
| git config user.name $GITHUB_ACTOR | |
| git config user.email actions@"$RUNNER_NAME".local | |
| - name: Update .asf.yaml to protect new postrelease branch from force push | |
| run: | | |
| sed -i -e "s/master: {}/master: {}\n ${POST_RELEASE_BRANCH}: {}/g" .asf.yaml | |
| - name: Commit and Push to master branch files with Next Version | |
| run: | | |
| git add .asf.yaml | |
| git commit -m "Adding ${POST_RELEASE_BRANCH} to protected branches in .asf.yaml" | |
| git push origin ${MASTER_BRANCH} |