From c1b98ca3c6f09a818345e91d79be1deee92f20ae Mon Sep 17 00:00:00 2001 From: Mitchell Alessio <5306896+malessi@users.noreply.github.com> Date: Fri, 1 Dec 2023 16:31:15 -0500 Subject: [PATCH] BFD-2906: Automate Maven Release Process (#2061) Co-authored-by: Brian Burton Co-authored-by: Michael J Burling --- .github/workflows/build-release.yml | 195 ++++++++++++++++++ .github/workflows/ci-java.yml | 8 - apps/bfd-data-fda/pom.xml | 1 - .../fda/lookup/FdaDrugCodeDisplayLookup.java | 1 + apps/bfd-data-npi/pom.xml | 1 - .../gov/cms/bfd/data/npi/utility/App.java | 1 + apps/bfd-server/bfd-server-war/pom.xml | 2 +- apps/bfd-server/pom.xml | 4 +- apps/pom.xml | 8 +- ops/terraform/env/mgmt/github-actions-iam.tf | 52 ++++- ops/terraform/env/mgmt/iam.tf | 12 +- 11 files changed, 259 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/build-release.yml diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000000..3233753189 --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,195 @@ +--- +name: "Build Release" +on: + workflow_dispatch: + inputs: + releaseBranch: + description: "The branch on which a release is based" + required: false + default: master + releaseVersion: + description: "Version to be used as tag and release" + required: true + default: X.Y.Z + developmentVersion: + description: 'Post-release Development version. Should be "(releaseVersion + 1)-SNAPSHOT"' + required: true + default: X.Y.Z-SNAPSHOT + awsRegion: + description: "AWS Region to upload artifacts to" + required: true + default: us-east-1 + +permissions: + id-token: write # This is required for requesting the AWS IAM OIDC JWT + contents: write # This is required for actions/checkout + +env: + # AWS Code Artifact Repository + CA_REPOSITORY: bfd-mgmt + CA_DOMAIN: bfd-mgmt + AWS_REGION: ${{ inputs.awsRegion }} + +jobs: + mvn-release: + runs-on: ubuntu-latest + steps: + - name: Validate Inputs + run: | + echo "Validating inputs to ensure they conform to expected formats..." + echo "${{ inputs.releaseVersion }}" | grep -P '^\d+\.\d+\.\d+$' + echo "${{ inputs.developmentVersion }}" | grep -P '^\d+\.\d+\.\d+-SNAPSHOT$' + + - 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: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ secrets.GHA_AWS_IAM_ROLE_ARN }} + role-session-name: build-release + aws-region: ${{ env.AWS_REGION }} + + - name: Login to ECR + uses: aws-actions/amazon-ecr-login@v1 + with: + mask-password: "true" + + - name: Checkout + if: github.event_name == 'workflow_dispatch' + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ inputs.releaseBranch }} + token: ${{ steps.generate_token.outputs.token }} + + - name: Setup JDK + uses: actions/setup-java@v3 + 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: Generate maven toolchain config + run: | + cat << EOF > ~/.m2/toolchains.xml + + + jdk + + 21 + OpenJDK + + + $JAVA_HOME + + + + EOF + + - name: Set Authorization Token + run: | + CODEARTIFACT_AUTH_TOKEN="$(aws codeartifact get-authorization-token --domain "$CA_DOMAIN" --domain-owner ${{ secrets.AWS_ACCOUNT_ID }} --query authorizationToken --output text --region us-east-1)" + echo "::add-mask::$CODEARTIFACT_AUTH_TOKEN" + echo CODEARTIFACT_AUTH_TOKEN=$CODEARTIFACT_AUTH_TOKEN >> $GITHUB_ENV + + - name: Get Repository Endpoint + run: | + CA_REPOSITORY_ENDPOINT="$(aws codeartifact get-repository-endpoint --domain "$CA_DOMAIN" --repository "$CA_REPOSITORY" --format maven --query repositoryEndpoint --output text)" + echo "::add-mask::$CA_REPOSITORY_ENDPOINT" + echo CA_REPOSITORY_ENDPOINT=$CA_REPOSITORY_ENDPOINT >> $GITHUB_ENV + + - name: Get ECR Registry Namespace + run: | + ECR_REPOSITORY_NAMESPACE="$(aws ecr describe-registry --region "$AWS_REGION" | jq -r '.registryId').dkr.ecr.${AWS_REGION}.amazonaws.com" + echo "::add-mask::$ECR_REPOSITORY_NAMESPACE" + echo ECR_REPOSITORY_NAMESPACE=$ECR_REPOSITORY_NAMESPACE >> $GITHUB_ENV + + - name: Configure additional maven settings.xml + run: |- + cat <<"EOF" > ~/.m2/settings.xml + + + + aws + ${env.CODEARTIFACT_AUTH_TOKEN} + ${env.CA_DOMAIN}-${env.CA_REPOSITORY} + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + + EOF + + - name: "Prepare and Perform Release" + if: github.event_name == 'workflow_dispatch' + run: |- + mvn --batch-mode --activate-profiles test-release \ + -Dtag="$BFD_RELEASE" \ + -DreleaseVersion="$BFD_RELEASE" \ + -DdevelopmentVersion="$BFD_DEV_VERSION" \ + release:prepare release:perform + working-directory: ./apps + env: + BFD_RELEASE: ${{ inputs.releaseVersion }} + BFD_DEV_VERSION: ${{ inputs.developmentVersion }} + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + + - name: "Perform Exceptional Rollback" + if: failure() + run: mvn release:rollback + working-directory: ./apps + + - name: Pull Release Files + run: | + readarray -t assets < <(echo "$CA_DATA_DICTIONARY_ASSETS" | jq -r -c '.[]') + for asset in "${assets[@]}" + do + aws codeartifact get-package-version-asset \ + --domain-owner ${{ secrets.AWS_ACCOUNT_ID }} \ + --domain "$CA_DOMAIN" \ + --repository "$CA_REPOSITORY" \ + --asset "$asset" \ + --package-version "${{ inputs.releaseVersion }}" \ + --package "$CA_PACKAGE" \ + --namespace "$CA_NAMESPACE" \ + --format maven \ + --region "$AWS_REGION" \ + "${asset/$CA_PACKAGE-/}" 1>/dev/null + done + env: + CA_NAMESPACE: gov.cms.bfd + CA_PACKAGE: bfd-server-war + CA_DATA_DICTIONARY_ASSETS: | + [ + "bfd-server-war-V1-data-dictionary-${{ inputs.releaseVersion }}.csv", + "bfd-server-war-V2-data-dictionary-${{ inputs.releaseVersion }}.csv", + "bfd-server-war-V1-data-dictionary-${{ inputs.releaseVersion }}.json", + "bfd-server-war-V2-data-dictionary-${{ inputs.releaseVersion }}.json", + "bfd-server-war-data-dictionary-${{ inputs.releaseVersion }}.xlsx" + ] + + - name: Release + uses: softprops/action-gh-release@v1 + with: + prerelease: true + generate_release_notes: true + fail_on_unmatched_files: true + tag_name: "${{ inputs.releaseVersion }}" + name: "v${{ inputs.releaseVersion }}" + files: | + *.csv + *.json + *.xlsx diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml index 69c4875ea9..0d22647857 100644 --- a/.github/workflows/ci-java.yml +++ b/.github/workflows/ci-java.yml @@ -100,14 +100,6 @@ jobs: EOF - - name: 'Run Maven Build on FDA Drug Utility' - run: mvn --threads 1C --batch-mode -Dmaven.build.cache.enabled=false install - working-directory: ./apps/bfd-data-fda - - - name: 'Run Maven Build on NPI Org Utility' - run: mvn --threads 1C --batch-mode -Dmaven.build.cache.enabled=false install - working-directory: ./apps/bfd-data-npi - - name: 'Run Maven Build' run: mvn --threads 1C --quiet --batch-mode -Dmaven.build.cache.enabled=false verify working-directory: ./apps diff --git a/apps/bfd-data-fda/pom.xml b/apps/bfd-data-fda/pom.xml index 1363e9fbc2..064d2606d9 100644 --- a/apps/bfd-data-fda/pom.xml +++ b/apps/bfd-data-fda/pom.xml @@ -13,7 +13,6 @@ gov.cms.bfd.data.fda.utility bfd-data-fda jar - 1.0-SNAPSHOT FDA Drug code lookup jar diff --git a/apps/bfd-data-fda/src/main/java/gov/cms/bfd/data/fda/lookup/FdaDrugCodeDisplayLookup.java b/apps/bfd-data-fda/src/main/java/gov/cms/bfd/data/fda/lookup/FdaDrugCodeDisplayLookup.java index 050eb11ee0..35437edf8b 100644 --- a/apps/bfd-data-fda/src/main/java/gov/cms/bfd/data/fda/lookup/FdaDrugCodeDisplayLookup.java +++ b/apps/bfd-data-fda/src/main/java/gov/cms/bfd/data/fda/lookup/FdaDrugCodeDisplayLookup.java @@ -204,6 +204,7 @@ protected Map getFdaProcessedData( } return ndcProcessedData; } + /** * Returns a inputStream from file name passed in. * diff --git a/apps/bfd-data-npi/pom.xml b/apps/bfd-data-npi/pom.xml index 786e9153b4..8c35f15952 100644 --- a/apps/bfd-data-npi/pom.xml +++ b/apps/bfd-data-npi/pom.xml @@ -12,7 +12,6 @@ gov.cms.bfd.data.npi bfd-data-npi jar - 1.0-SNAPSHOT NPI Org code lookup jar diff --git a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/App.java b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/App.java index 0e36e17429..992398e3e4 100644 --- a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/App.java +++ b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/App.java @@ -12,6 +12,7 @@ */ public final class App { private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + /** * The name of the classpath resource (for the project's main web application) for the NPI "Orgs" * TSV file. diff --git a/apps/bfd-server/bfd-server-war/pom.xml b/apps/bfd-server/bfd-server-war/pom.xml index 191825961e..7fc201aa5e 100644 --- a/apps/bfd-server/bfd-server-war/pom.xml +++ b/apps/bfd-server/bfd-server-war/pom.xml @@ -347,7 +347,7 @@ gov.cms.bfd.data.fda.utility bfd-data-fda - ${bfd.data.fda.version} + ${project.version} diff --git a/apps/bfd-server/pom.xml b/apps/bfd-server/pom.xml index 3caa083610..beb1db8093 100644 --- a/apps/bfd-server/pom.xml +++ b/apps/bfd-server/pom.xml @@ -77,7 +77,7 @@ gov.cms.bfd.data.fda.utility bfd-data-fda - ${bfd.data.fda.version} + ${project.version} @@ -93,7 +93,7 @@ gov.cms.bfd.data.npi bfd-data-npi - ${bfd.data.npi.version} + ${project.version} diff --git a/apps/pom.xml b/apps/pom.xml index ac2456727d..f4f428fb0f 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -38,13 +38,15 @@ - scm:git:git@github.com:CMSgov/beneficiary-fhir-data.git - scm:git:git@github.com:CMSgov/beneficiary-fhir-data.git + scm:git:https://github.com/CMSgov/beneficiary-fhir-data.git + scm:git:https://github.com/CMSgov/beneficiary-fhir-data.git https://github.com/CMSgov/beneficiary-fhir-data HEAD + bfd-data-npi + bfd-data-fda bfd-shared-utils bfd-shared-test-utils bfd-model @@ -68,8 +70,6 @@ they are reproducible bit-by-bit no matter when/where they are generated. See https://maven.apache.org/guides/mini/guide-reproducible-builds.html --> 2022-01-01T00:00:00Z - 1.0-SNAPSHOT - 1.0-SNAPSHOT 0.8.11 true diff --git a/ops/terraform/env/mgmt/github-actions-iam.tf b/ops/terraform/env/mgmt/github-actions-iam.tf index 65ac1358fe..62c475dc98 100644 --- a/ops/terraform/env/mgmt/github-actions-iam.tf +++ b/ops/terraform/env/mgmt/github-actions-iam.tf @@ -49,7 +49,54 @@ resource "aws_iam_policy" "github_actions_s3its" { "Version": "2012-10-17" } POLICY +} +resource "aws_iam_policy" "github_actions_ecr" { + name = "bfd-${local.env}-ecr-rw" + path = "/" + policy = jsonencode( + { + Statement = [ + { + Action = [ + "ecr:GetAuthorizationToken", + ] + Effect = "Allow" + Resource = "*" + Sid = "GetAuthorizationToken" + }, + { + Action = [ + "ecr:BatchGetImage", + "ecr:BatchCheckLayerAvailability", + "ecr:CompleteLayerUpload", + "ecr:GetDownloadUrlForLayer", + "ecr:InitiateLayerUpload", + "ecr:PutImage", + "ecr:UploadLayerPart", + ] + Effect = "Allow" + Resource = [ + "arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-db-migrator", + "arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-server", + "arn:aws:ecr:us-east-1:${local.account_id}:repository/bfd-pipeline-app", + ] + Sid = "AllowPushPull" + }, + { + Sid = "AllowDescribeRegistry", + Effect = "Allow", + Action = [ + "ecr:DescribeRegistry" + ], + Resource = [ + "*" + ] + } + ] + Version = "2012-10-17" + } + ) } data "tls_certificate" "github_actions" { @@ -68,8 +115,9 @@ resource "aws_iam_role" "github_actions" { description = "OIDC Assumable GitHub Actions Role" managed_policy_arns = [ - aws_iam_policy.code_artifact_ro.arn, - aws_iam_policy.github_actions_s3its.arn + aws_iam_policy.code_artifact_rw.arn, + aws_iam_policy.github_actions_s3its.arn, + aws_iam_policy.github_actions_ecr.arn ] assume_role_policy = jsonencode( diff --git a/ops/terraform/env/mgmt/iam.tf b/ops/terraform/env/mgmt/iam.tf index d2a60bb838..8d6dfdb1f9 100644 --- a/ops/terraform/env/mgmt/iam.tf +++ b/ops/terraform/env/mgmt/iam.tf @@ -136,7 +136,8 @@ resource "aws_iam_policy" "code_artifact_rw" { "codeartifact:ReadFromRepository", "codeartifact:TagResource", "codeartifact:UntagResource", - "codeartifact:UpdatePackageVersionsStatus" + "codeartifact:UpdatePackageVersionsStatus", + "codeartifact:GetAuthorizationToken" ], "Effect": "Allow", "Resource": [ @@ -147,18 +148,15 @@ resource "aws_iam_policy" "code_artifact_rw" { "Sid": "CodeArtifactReadWrite" }, { - "Action": "codeartifact:GetAuthorizationToken", + "Action": "sts:GetServiceBearerToken", "Effect": "Allow", - "Resource": [ - "${aws_codeartifact_domain.this.arn}" - ], - "Sid": "CodeArtifactAuthToken" + "Resource": "*", + "Sid": "TempCreds" } ], "Version": "2012-10-17" } POLICY - } resource "aws_iam_policy" "code_artifact_ro" {