Merge pull request #5394 from brucehoff/PLFM-9253 #26
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
| --- | |
| # | |
| # This workflow runs the Synapse Stack Builder and then builds and runs the tests | |
| # for the Synapse Repository Services. | |
| # | |
| # These parameters can be overridden with repo's action variables: | |
| # | |
| # - USER (the 'user' parameter for the Synapse build): defaults to repo' owner. Should be alphanumeric only. | |
| # - STACK_BUILDER_REPO_OWNER: defaults to Sage-Bionetworks | |
| # - STACK_BUILDER_BRANCH: defaults to develop | |
| # - FULL_BUILD: if true, will do a full build, vs. an abbreviated "feature build" | |
| # - EXTRA_ARGS: pass extra arguments to maven build | |
| # | |
| # To post the build status to a PR, add this repository secret: | |
| # - WRITE_STATUS_TOKEN: A GitHub token with "repo:status" and "public_repo" permissions | |
| # | |
| name: main | |
| on: | |
| push: | |
| branches: ['*'] | |
| # let only one copy of the workflow run at a time | |
| concurrency: | |
| group: ${{ github.workflow }} | |
| jobs: | |
| build_and_test: | |
| permissions: | |
| # https://graphite.dev/guides/github-actions-permissions | |
| id-token: write | |
| contents: read | |
| deployments: write | |
| security-events: write | |
| statuses: write | |
| actions: write | |
| checks: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@v5 | |
| - name: Static Analysis | |
| uses: pre-commit/action@v3.0.0 | |
| - name: Find latest tag | |
| id: find_tag | |
| uses: mathieudutour/github-tag-action@v6.2 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| dry_run: true #setting to 'true' means no new version is created | |
| - run: | | |
| # get the 'user' parameter, either from the repo' env or repo' owner if not set | |
| if [ ${{ vars.USER }} ]; then | |
| echo "user=${{ vars.USER }}" >> $GITHUB_ENV | |
| else | |
| alpha_only_trunc_repo_name=$(echo "${GITHUB_REPOSITORY_OWNER//[^[:alnum:]]/}" | cut -c1-7) | |
| echo "user=$alpha_only_trunc_repo_name" >> $GITHUB_ENV | |
| fi | |
| # capture the current branch as an environment variable | |
| branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} | |
| echo "branch=$branch" >> $GITHUB_ENV | |
| # get repo' and branch specifying the version of the stack builder to use | |
| if [ ${{ vars.STACK_BUILDER_REPO_OWNER }} ]; then | |
| echo "stack_builder_repo_owner=${{ vars.STACK_BUILDER_REPO_OWNER }}" >> $GITHUB_ENV | |
| else | |
| echo "stack_builder_repo_owner=Sage-Bionetworks" >> $GITHUB_ENV | |
| fi | |
| if [ ${{ vars.STACK_BUILDER_BRANCH }} ]; then | |
| echo "stack_builder_branch=${{ vars.STACK_BUILDER_BRANCH }}" >> $GITHUB_ENV | |
| else | |
| echo "stack_builder_branch=develop" >> $GITHUB_ENV | |
| fi | |
| echo "full_build=${{ vars.FULL_BUILD }}" >> $GITHUB_ENV | |
| echo "EXTRA_ARGS=${{ vars.EXTRA_ARGS }}" >> $GITHUB_ENV | |
| if [ ${{ secrets.WRITE_STATUS_TOKEN }} ]; then | |
| echo "WRITE_STATUS_TOKEN_EXISTS=true" >> $GITHUB_ENV | |
| fi | |
| # for builds in Sage-Bionetworks repo', publish build artifacts | |
| if [[ $GITHUB_REPOSITORY_OWNER == "Sage-Bionetworks" ]]; then | |
| if [[ $branch == "develop" ]]; then | |
| GIT_COMMIT=${{ github.sha }} | |
| ARTIFACT_VERSION=$(date +%Y-%m-%d)"-"${GIT_COMMIT:0:7} | |
| elif [[ $branch =~ "release-" ]]; then | |
| ARTIFACT_VERSION=${{ steps.find_tag.outputs.previous_version }} | |
| fi | |
| fi | |
| if [[ $ARTIFACT_VERSION ]]; then | |
| echo Build will publish artifacts with version $ARTIFACT_VERSION | |
| echo "ARTIFACT_VERSION=$ARTIFACT_VERSION" >> $GITHUB_ENV | |
| else | |
| echo "Build will not publish artifacts" | |
| fi | |
| - id: oidc | |
| uses: aws-actions/configure-aws-credentials@v5 | |
| with: | |
| role-to-assume: arn:aws:iam::449435941126:role/sagebase-github-oidc-sage-bionetworks-synapse-build | |
| aws-region: us-east-1 | |
| # eight hours | |
| role-duration-seconds: 28800 | |
| - name: Capture Session Credentials | |
| run: | | |
| # We will capture the long-lived session token to use for the build | |
| # Note: We cannot pass the credentials as inputs to code pipeline | |
| # since the token exceeded the 1000 character limit for input variables. | |
| SECRET_NAME="/build/session-token/${{ env.user }}" | |
| SECRET_VALUE='{"AwsAccessKeyId":"${{ env.AWS_ACCESS_KEY_ID }}", "AwsSecretAccessKey":"${{ env.AWS_SECRET_ACCESS_KEY }}", "AwsSessionToken":"${{ env.AWS_SESSION_TOKEN }}"}' | |
| # Try to update the secret value first | |
| if aws secretsmanager put-secret-value \ | |
| --secret-id "$SECRET_NAME" \ | |
| --secret-string "$SECRET_VALUE" \ | |
| 2>/dev/null; then | |
| echo "Secret updated successfully" | |
| else | |
| echo "Secret doesn't exist, creating new secret..." | |
| if aws secretsmanager create-secret \ | |
| --name "$SECRET_NAME" \ | |
| --secret-string "$SECRET_VALUE" \ | |
| --description "Build credentials for ${{ env.user }}"; then | |
| echo "Secret created successfully" | |
| else | |
| echo "Failed to create secret" | |
| exit 1 | |
| fi | |
| fi | |
| - name: Deploy CodePipeline to AWS CloudFormation | |
| uses: aws-actions/aws-cloudformation-github-deploy@v1 | |
| id: pipeline-deploy | |
| with: | |
| template: configuration/build/codepipeline_cf_template.yaml | |
| name: Synapse-Build-${{ env.user }} | |
| capabilities: CAPABILITY_IAM,CAPABILITY_NAMED_IAM | |
| parameter-overrides: >- | |
| SynapseBranch=${{ env.branch }}, | |
| SynapseRepoOwner=${{ github.repository_owner }}, | |
| GitHubToken=${{ secrets.GITHUB_TOKEN }}, | |
| BuildParamUser=${{ env.user }}, | |
| StackBuilderBranch=${{ env.stack_builder_branch }}, | |
| StackBuilderRepoOwner=${{ env.stack_builder_repo_owner }}, | |
| FullBuild=${{ env.full_build }}, | |
| MavenExtraArgs=${{ env.EXTRA_ARGS }}, | |
| ArtifactVersion=${{ env.ARTIFACT_VERSION }} | |
| - name: Output Pipeline Console URL | |
| run: | | |
| echo "PIPELINE_CONSOLE_URL=https://us-east-1.console.aws.amazon.com/codesuite/codepipeline/pipelines/${{ steps.pipeline-deploy.outputs.PipelineName }}/view" >> $GITHUB_ENV | |
| - name: Pending Status | |
| if: ${{ env.WRITE_STATUS_TOKEN_EXISTS }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.WRITE_STATUS_TOKEN }} | |
| run: | | |
| gh api --method POST \ | |
| /repos/Sage-Bionetworks/Synapse-Repository-Services/statuses/${{ github.sha }} \ | |
| -f "state=pending" \ | |
| -f "description=Build in Progress" \ | |
| -f "target_url=${{ env.PIPELINE_CONSOLE_URL }}" | |
| - name: Trigger CodePipeline | |
| id: pipeline-run | |
| run: | | |
| EXECUTION_ID=$(aws codepipeline start-pipeline-execution \ | |
| --name ${{ steps.pipeline-deploy.outputs.PipelineName }} \ | |
| --source-revisions actionName=CheckoutSynapseRepo,revisionType=COMMIT_ID,revisionValue=${{ github.sha }} \ | |
| --query 'pipelineExecutionId' --output text) | |
| echo "EXECUTION_ID=$EXECUTION_ID" >> $GITHUB_ENV | |
| # if the status check is too soon, the executing pipeline is not found and the workflow fails | |
| sleep 10 | |
| # Wait for completion | |
| while true; do | |
| STATUS=$(aws codepipeline get-pipeline-execution --pipeline-name ${{ steps.pipeline-deploy.outputs.PipelineName }} \ | |
| --pipeline-execution-id $EXECUTION_ID --query "pipelineExecution.status" --output text) | |
| if [[ "$STATUS" == "Succeeded" ]]; then | |
| echo "Pipeline execution $EXECUTION_ID succeeded." | |
| break | |
| elif [[ "$STATUS" == "InProgress" ]]; then | |
| echo "Pipeline execution $EXECUTION_ID is still in progress. Current status: $STATUS. Waiting..." | |
| sleep 30 # Wait for 30 seconds before checking again | |
| else | |
| echo "Pipeline execution $EXECUTION_ID terminated with: $STATUS" | |
| exit 1 | |
| fi | |
| done | |
| - name: Success Status | |
| if: ${{ env.WRITE_STATUS_TOKEN_EXISTS }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.WRITE_STATUS_TOKEN }} | |
| run: | | |
| gh api --method POST \ | |
| /repos/Sage-Bionetworks/Synapse-Repository-Services/statuses/${{ github.sha }} \ | |
| -f "state=success" \ | |
| -f "description=Build Succeeded" \ | |
| -f "target_url=${{ env.PIPELINE_CONSOLE_URL }}" | |
| - name: Failed Status | |
| if: ${{ env.WRITE_STATUS_TOKEN_EXISTS && failure()}} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.WRITE_STATUS_TOKEN }} | |
| run: | | |
| gh api --method POST \ | |
| /repos/Sage-Bionetworks/Synapse-Repository-Services/statuses/${{ github.sha }} \ | |
| -f "state=failure" \ | |
| -f "description=Build Failed" \ | |
| -f "target_url=${{ env.PIPELINE_CONSOLE_URL }}" | |
| - name: Cancelled Status | |
| if: ${{ env.WRITE_STATUS_TOKEN_EXISTS && cancelled()}} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.WRITE_STATUS_TOKEN }} | |
| run: | | |
| gh api --method POST \ | |
| /repos/Sage-Bionetworks/Synapse-Repository-Services/statuses/${{ github.sha }} \ | |
| -f "state=failure" \ | |
| -f "description=Build Cancelled" \ | |
| -f "target_url=${{ env.PIPELINE_CONSOLE_URL }}" | |
| - name: Stop CodePipeline on Workflow Cancellation | |
| if: cancelled() | |
| run: | | |
| PIPELINE_NAME=${{ steps.pipeline-deploy.outputs.PipelineName }} | |
| aws codepipeline stop-pipeline-execution \ | |
| --pipeline-name $PIPELINE_NAME \ | |
| --pipeline-execution-id ${{ env.EXECUTION_ID }} \ | |
| --abandon | |
| # Wait a moment for the pipeline to process | |
| sleep 5 | |
| # Get pipeline structure to find CodeBuild projects | |
| CODEBUILD_PROJECTS=$(aws codepipeline get-pipeline \ | |
| --name "$PIPELINE_NAME" \ | |
| --query 'pipeline.stages[].actions[?actionTypeId.provider==`CodeBuild`].configuration.ProjectName' \ | |
| --output text) | |
| echo "Found CodeBuild projects: $CODEBUILD_PROJECTS" | |
| # Stop running builds for each CodeBuild project | |
| for project in $CODEBUILD_PROJECTS; do | |
| echo "Checking builds for project: $project" | |
| # Get running builds for this project | |
| RUNNING_BUILDS=$(aws codebuild list-builds-for-project \ | |
| --project-name "$project" \ | |
| --sort-order DESCENDING \ | |
| --query 'ids[0:5]' \ | |
| --output text) | |
| for build_id in $RUNNING_BUILDS; do | |
| if [ -n "$build_id" ]; then | |
| # Check if build is still running | |
| BUILD_STATUS=$(aws codebuild batch-get-builds \ | |
| --ids "$build_id" \ | |
| --query 'builds[0].buildStatus' \ | |
| --output text) | |
| if [ "$BUILD_STATUS" = "IN_PROGRESS" ]; then | |
| echo "Stopping running build: $build_id" | |
| aws codebuild stop-build --id "$build_id" | |
| fi | |
| fi | |
| done | |
| done | |
| ... |