Build Release #274
Workflow file for this run
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: "Build Release" | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| releaseBranch: | |
| description: >- | |
| releaseBranch: Override the branch on which a release is based. | |
| Default to the selected reference in the `Use workflow from` drop-down when empty. | |
| required: false | |
| default: "" | |
| releaseVersion: | |
| description: >- | |
| releaseVersion: Override the release version. Default to promoting the current | |
| X.Y.Z-SNAPSHOT to X.Y.Z when empty. | |
| required: false | |
| default: "" | |
| developmentVersion: | |
| description: >- | |
| developmentVersion: Override the next development iteration version. | |
| Default to X.(Y+1).0-SNAPSHOT of the release version X.Y.Z when empty. | |
| required: false | |
| default: "" | |
| awsRegion: | |
| description: >- | |
| awsRegion: Override the AWS Region destination for uploaded artifacts. | |
| Default to `us-east-1`. | |
| default: us-east-1 | |
| type: choice | |
| options: | |
| - us-east-1 | |
| - us-west-2 | |
| required: true | |
| forceRelease: | |
| description: >- | |
| forceRelease: Override creation of the GitHub Release object. | |
| Default to creating release objects when `releaseVersion` does not contain the hyphen | |
| character ('-'), indicating a pre-release. | |
| default: false | |
| required: false | |
| type: boolean | |
| permissions: | |
| id-token: write # This is required for requesting the AWS IAM OIDC JWT | |
| contents: write # This is required for actions/checkout | |
| env: | |
| AWS_REGION: ${{ inputs.awsRegion }} | |
| BFD_RELEASE_OVERRIDE: ${{ inputs.releaseVersion }} | |
| BFD_DEV_VERSION_OVERRIDE: ${{ inputs.developmentVersion }} | |
| JIB_IMAGES: | | |
| [ | |
| "bfd-server", | |
| "bfd-pipeline-app", | |
| "bfd-db-migrator" | |
| ] | |
| ACCOUNT_ROLE_MAP: | | |
| { | |
| "prod": "${{ secrets.PROD_ACCOUNT_GHA_ROLE_ARN }}", | |
| "non-prod": "${{ secrets.NON_PROD_ACCOUNT_GHA_ROLE_ARN }}" | |
| } | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| compute-version-strings: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| bfd_release: ${{ steps.bfd-version-strings.outputs.BFD_RELEASE }} | |
| bfd_dev_version: ${{ steps.bfd-version-strings.outputs.BFD_DEV_VERSION }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.releaseBranch || github.ref_name }} | |
| - name: "Install yq" | |
| run: | | |
| sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq | |
| sudo chmod +x /usr/bin/yq | |
| - name: Set and Validate Version Strings | |
| id: bfd-version-strings | |
| run: | | |
| # Set default values for bfd-parent version based on existing version string in apps/pom.xml | |
| BFD_PARENT_POM_VERSION="$(yq --output-format=yaml .project.version apps/pom.xml)" | |
| ## Use override OR promote default by removing '-SNAPSHOT' suffix | |
| BFD_RELEASE_DEFAULT="$(yq 'split("-") | .[0]' <<< "$BFD_PARENT_POM_VERSION")" | |
| BFD_RELEASE="${BFD_RELEASE_OVERRIDE:-$BFD_RELEASE_DEFAULT}" | |
| ## Use override OR increment default value Y in X.Y.Z formatted release version, attach '-SNAPSHOT' suffix | |
| BFD_DEV_VERSION_DEFAULT="$(yq 'split("-") | .[0] | split(".") | map(. type = "!!int") | [.[0], .[1]+1, .[2]] | join(".")' <<< "$BFD_PARENT_POM_VERSION")-SNAPSHOT" | |
| BFD_DEV_VERSION="${BFD_DEV_VERSION_OVERRIDE:-$BFD_DEV_VERSION_DEFAULT}" | |
| # Validate and set BFD_RELASE and BFD_DEV_VERSION | |
| echo "$BFD_RELEASE" | grep -P '^\d+\.\d+\.\d+$|^\d+\.\d+\.\d+-[a-zA-Z0-9-]+$' | |
| echo BFD_RELEASE="${BFD_RELEASE}" >> "$GITHUB_OUTPUT" | |
| echo "$BFD_DEV_VERSION" | grep -P '^\d+\.\d+\.\d+-SNAPSHOT$' | |
| echo BFD_DEV_VERSION="${BFD_DEV_VERSION_OVERRIDE:-$BFD_DEV_VERSION_DEFAULT}" >> "$GITHUB_OUTPUT" | |
| build-base-images: | |
| uses: ./.github/workflows/build-container-images.yml | |
| needs: compute-version-strings | |
| permissions: | |
| contents: read | |
| id-token: write | |
| with: | |
| branch: ${{ inputs.releaseBranch || github.ref_name }} | |
| versionTag: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| awsRegion: ${{ inputs.awsRegion }} | |
| # Build the base images prior to building the application images with jib in "run-mvn-release" | |
| # See .github/workflows/build_container_images_matrix.json for list of buildable images | |
| imagesCsv: "bfd-platform-base-java, bfd-platform-base-python" | |
| cleanupImageArtifacts: false # Keep the built images around so that they can be used for Jib | |
| skipBasePull: true # We're building the base images, so don't pull them | |
| secrets: inherit | |
| run-mvn-release: | |
| runs-on: ubuntu-24.04 | |
| needs: [compute-version-strings, build-base-images] | |
| env: | |
| BFD_RELEASE: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| BFD_DEV_VERSION: ${{ needs.compute-version-strings.outputs.bfd_dev_version }} | |
| steps: | |
| - name: "Generate an App Token" | |
| id: generate_token | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ secrets.BFD_RELEASE_APP_ID }} | |
| private-key: ${{ secrets.BFD_RELEASE_APP_KEY }} | |
| - name: Checkout | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.releaseBranch || github.ref_name }} | |
| token: ${{ steps.generate_token.outputs.token }} | |
| - name: Retrieve base java image | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: '*bfd-platform-base-java*' | |
| merge-multiple: true | |
| path: ${{ runner.temp }} | |
| - name: Load base image into Docker | |
| run: | | |
| docker load --input "${{ runner.temp }}/bfd-platform-base-java.tar" | |
| - name: Install gitleaks | |
| run: | | |
| curl -s https://api.github.com/repos/gitleaks/gitleaks/releases/latest \ | |
| | grep "browser_download_url.*linux_x64.tar.gz" \ | |
| | cut -d : -f 2,3 \ | |
| | tr -d \" \ | |
| | wget -qi - | |
| sudo tar -xzf "$(find -iname 'gitleaks*.tar.gz')" -C /usr/bin gitleaks | |
| sudo chmod +x /usr/bin/gitleaks | |
| - name: Setup JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: "21" | |
| distribution: corretto | |
| - name: Configure the git user | |
| run: | | |
| git config --global user.email "actions@github.com" | |
| git config --global user.name "GitHub Actions" | |
| - name: Configure additional maven settings.xml | |
| run: |- | |
| cat <<"EOF" > ~/.m2/settings.xml | |
| <settings xmlns="http://maven.apache.org/settings/1.0.0" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" | |
| xsi:schemalocation="http://maven.apache.org/settings/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"> | |
| <servers> | |
| <server> | |
| <id>github</id> | |
| <username>${env.GITHUB_ACTOR}</username> | |
| <password>${env.GITHUB_TOKEN}</password> | |
| </server> | |
| </servers> | |
| </settings> | |
| EOF | |
| - name: "Prepare Release" | |
| if: github.event_name == 'workflow_dispatch' | |
| run: |- | |
| # We set preparationGoals to an empty string because we don't want to build during the | |
| # release:prepare since we will need to build again during release:perform. We expect that the | |
| # source code has been verified to compile and pass tests prior to merging to master, so building it | |
| # unnecessarily during the prepare phase is redundant. | |
| mvn --batch-mode --activate-profiles prepare-release \ | |
| -Dtag="$BFD_RELEASE" \ | |
| -DreleaseVersion="$BFD_RELEASE" \ | |
| -DdevelopmentVersion="$BFD_DEV_VERSION" \ | |
| -DpreparationGoals="" \ | |
| release:prepare | |
| working-directory: ./apps | |
| env: | |
| GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} | |
| - name: "Perform Release" | |
| if: github.event_name == 'workflow_dispatch' | |
| run: |- | |
| mvn --batch-mode --activate-profiles perform-release \ | |
| -Dtag="$BFD_RELEASE" \ | |
| -DreleaseVersion="$BFD_RELEASE" \ | |
| -DdevelopmentVersion="$BFD_DEV_VERSION" \ | |
| release:perform | |
| working-directory: ./apps | |
| env: | |
| GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} | |
| - name: Export jib images | |
| run: | | |
| readarray -t images < <(echo "$JIB_IMAGES" | jq -r -c '.[]') | |
| for image in "${images[@]}" | |
| do | |
| docker save "$image:$BFD_RELEASE" > "${image}.tar" | |
| done | |
| working-directory: ${{ runner.temp }} | |
| - name: Upload jib image artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: jib-images | |
| path: ${{ runner.temp }}/*.tar | |
| retention-days: 1 | |
| - name: Get bfd-server-war m2 directory | |
| id: get-server-war-dir | |
| run: | | |
| server_war_dir="$(realpath "$(find ~/.m2 -type d -path '*/bfd-server-war/*' | head -n1)")" | |
| ls "$server_war_dir" | |
| echo "server-war-dir=$server_war_dir" >> "$GITHUB_OUTPUT" | |
| - name: Upload data dictionary and OpenApi artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: release-artifacts | |
| path: | | |
| ${{ steps.get-server-war-dir.outputs.server-war-dir }}/*data-dictionary* | |
| ${{ steps.get-server-war-dir.outputs.server-war-dir }}/*openapi* | |
| retention-days: 1 | |
| - name: "Perform Exceptional Rollback" | |
| if: failure() | |
| run: mvn release:rollback | |
| working-directory: ./apps | |
| push-jib-images: | |
| needs: [compute-version-strings, run-mvn-release] | |
| strategy: | |
| matrix: | |
| account: ["prod", "non-prod"] | |
| runs-on: codebuild-bfd-${{ matrix.account }}-platform-docker-${{ github.run_id }}-${{ github.run_attempt }} | |
| env: | |
| BFD_RELEASE: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| BFD_DEV_VERSION: ${{ needs.compute-version-strings.outputs.bfd_dev_version }} | |
| steps: | |
| - name: Get role ARN | |
| id: get-role-arn | |
| run: | | |
| role_arn="$(jq -r --arg account_type "${{ matrix.account }}" '.[$account_type]' <<<"$ACCOUNT_ROLE_MAP")" | |
| echo "::add-mask::$role_arn" | |
| echo "role-arn=$role_arn" >> "$GITHUB_OUTPUT" | |
| - name: Download jib image artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: jib-images | |
| path: ${{ runner.temp }} | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: ${{ steps.get-role-arn.outputs.role-arn }} | |
| role-session-name: build-release-${{ github.run_id }}-${{ github.run_attempt }} | |
| aws-region: ${{ env.AWS_REGION }} | |
| - name: Login to ECR | |
| id: ecr-login | |
| uses: aws-actions/amazon-ecr-login@v2 | |
| - name: Push jib images | |
| env: | |
| REGISTRY: ${{ steps.ecr-login.outputs.registry }} | |
| PUSH_LATEST: ${{ !contains(needs.compute-version-strings.outputs.bfd_release, '-') }} | |
| run: | | |
| echo "::add-mask::$REGISTRY" | |
| for image_filename in ./*.tar | |
| do | |
| docker load --input "$image_filename" | |
| image="$(basename "$image_filename" .tar)" | |
| docker tag "$image:$BFD_RELEASE" "$REGISTRY/$image:$BFD_RELEASE" | |
| if [[ $PUSH_LATEST == "true" ]]; then | |
| # Remove the "latest" tag from the existing latest image | |
| aws ecr batch-delete-image --repository-name "$IMAGE" --image-ids imageTag=latest | |
| # Tag the new release image as "latest" | |
| docker tag "$image:$BFD_RELEASE" "$REGISTRY/$image:latest" | |
| # Push "latest" tag | |
| docker push "$REGISTRY/$image:latest" | |
| fi | |
| docker push "$REGISTRY/$image:$BFD_RELEASE" | |
| done | |
| working-directory: ${{ runner.temp }} | |
| build-other-images: | |
| uses: ./.github/workflows/build-container-images.yml | |
| needs: [compute-version-strings, run-mvn-release] | |
| permissions: | |
| contents: read | |
| id-token: write | |
| with: | |
| branch: ${{ inputs.releaseBranch || github.ref_name }} | |
| versionTag: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| awsRegion: ${{ inputs.awsRegion }} | |
| # Build other images, like Lambda images, Python applications, etc. | |
| # See .github/workflows/build_container_images_matrix.json for list of buildable images | |
| imagesCsv: >- | |
| bfd-platform-server-regression, | |
| bfd-platform-mount-certstores, | |
| bfd-platform-server-fluent-bit, | |
| bfd-platform-run-locust, | |
| bfd-platform-eft-sftp-outbound-transfer-lambda, | |
| bfd-platform-pipeline-ccw-manifests-verifier-lambda, | |
| bfd-platform-pipeline-ccw-runner | |
| baseImagesVersion: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| cleanupImageArtifacts: false # We'll cleanup at the end of build-release, so don't do anything | |
| secrets: inherit | |
| create-gh-release: | |
| if: ${{ !contains(needs.compute-version-strings.outputs.bfd_release, '-') || inputs.forceRelease }} | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| [ | |
| compute-version-strings, | |
| build-base-images, | |
| run-mvn-release, | |
| push-jib-images, | |
| build-other-images, | |
| ] | |
| steps: | |
| - name: Pull release artifacts | |
| id: pull-release-artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-artifacts | |
| - name: Prepare artifacts | |
| env: | |
| BFD_RELEASE: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| run: | | |
| # We want artifacts to be named consistently, specifically in the form of | |
| # "<artifact_name>-<bfd_version>.<ext>". However, they are generated as | |
| # "bfd-server-war-<bfd_version>-<artifact_name>.<ext>", so we need to do some filename | |
| # manipulation here | |
| for artifact_path in ./* | |
| do | |
| artifact="$(basename -- "$artifact_path" | sed -nE "s/bfd-server-war-$BFD_RELEASE-(.*)/\1/p")" | |
| artifact_ext="${artifact#*.}" | |
| artifact_name="${artifact%%.*}" | |
| mv "$artifact_path" "./${artifact_name}-${BFD_RELEASE}.${artifact_ext}" | |
| done | |
| - name: Release | |
| uses: ncipollo/release-action@v1 | |
| with: | |
| # NOTE: Prevent automatic promotion of pre-release objects to latest | |
| makeLatest: "${{ !contains(needs.compute-version-strings.outputs.bfd_release, '-') }}" | |
| generateReleaseNotes: true | |
| artifactErrorsFailBuild: true | |
| tag: ${{ needs.compute-version-strings.outputs.bfd_release }} | |
| name: "v${{ needs.compute-version-strings.outputs.bfd_release }}" | |
| artifacts: "*.csv,*.json,*.xlsx,*.yaml" | |
| cleanup-artifacts: | |
| if: ${{ !cancelled() }} | |
| needs: [build-other-images, create-gh-release] | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Delete all artifacts | |
| uses: GeekyEggo/delete-artifact@v5.1.0 | |
| with: | |
| name: '*' | |
| failOnError: false |