diff --git a/.github/workflows/compile-and-publish.yml b/.github/workflows/compile-and-publish.yml index 167a7f408..c86f23a5b 100644 --- a/.github/workflows/compile-and-publish.yml +++ b/.github/workflows/compile-and-publish.yml @@ -11,10 +11,6 @@ permissions: id-token: write contents: read -env: - CDN_BUCKET: gc-design-system-production-cdn - CDN_REGION: ca-central-1 - jobs: publish-web: name: Publish @cdssnc/gcds-components @@ -49,31 +45,8 @@ jobs: token: ${{ secrets.NPM_TOKEN }} package: ${{ matrix.dist }} - - name: Configure AWS credentials using OIDC - if: steps.publish.outputs.id != '' - uses: aws-actions/configure-aws-credentials@50ac8dd1e1b10d09dac7b8727528b91bed831ac0 # v3.0.2 - with: - role-to-assume: arn:aws:iam::307395567143:role/gcds-components-apply - role-session-name: CDNPublish - aws-region: ${{ env.CDN_REGION }} - - - name: Update CDN ${{ matrix.name }} - if: steps.publish.outputs.id != '' - run: | - PUBLISHED_PACKAGE="${{ steps.publish.outputs.id }}" - - mkdir -p ./tmp \ - && sleep 60 \ - && npm install --prefix ./tmp "$PUBLISHED_PACKAGE" \ - && cd ./tmp/node_modules - - aws s3 sync ./${{ matrix.name }} s3://${{ env.CDN_BUCKET }}/"$PUBLISHED_PACKAGE" --delete - aws s3 sync ./${{ matrix.name }} s3://${{ env.CDN_BUCKET }}/${{ matrix.name }}@latest --delete - aws s3api head-object --bucket ${{ env.CDN_BUCKET }} --key "$PUBLISHED_PACKAGE"/package.json - aws s3api head-object --bucket ${{ env.CDN_BUCKET }} --key ${{ matrix.name }}@latest/package.json - - aws cloudfront create-invalidation --distribution-id ${{ secrets.CDN_CLOUDFRONT_DIST_ID }} --paths "/*" - working-directory: ${{ matrix.package }} + - name: Sleep for 60 seconds to give more time for NPM to complete publishing before proceeding to publish the rest + run: sleep 60 - name: Report deployment to Sentinel if: steps.publish.outputs.id != '' @@ -84,15 +57,14 @@ jobs: log_analytics_workspace_id: ${{ secrets.LOG_ANALYTICS_WORKSPACE_ID }} log_analytics_workspace_key: ${{ secrets.LOG_ANALYTICS_WORKSPACE_KEY }} - - name: Slack notify on failure if: failure() run: | json='{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":":red: Publish ${{ matrix.name }} failed: "}}]}' curl -X POST -H 'Content-type: application/json' --data "$json" ${{ secrets.SLACK_WEBHOOK_OPS }} - publish-react-angular: - name: Publish @cdssnc/gcds-components-react and @cdssnc/gcds-components-angular + publish-react-angular-vue: + name: Publish @cdssnc/gcds-components-react, @cdssnc/gcds-components-angular, @cdssnc/gcds-components-vue needs: publish-web runs-on: ubuntu-latest strategy: @@ -120,10 +92,10 @@ jobs: with: node-version: 18 - - name: Install monorepo (web, react, angular) + - name: Install monorepo (web, react, angular, vue) run: npm install - - name: Build gcds-components (web, react, angular) + - name: Build gcds-components (web, react, angular, vue) run: npm run build - name: Publish ${{ matrix.name }} @@ -133,31 +105,6 @@ jobs: token: ${{ secrets.NPM_TOKEN }} package: ${{ matrix.dist }} - - name: Configure AWS credentials using OIDC - if: steps.publish.outputs.id != '' - uses: aws-actions/configure-aws-credentials@50ac8dd1e1b10d09dac7b8727528b91bed831ac0 # v3.0.2 - with: - role-to-assume: arn:aws:iam::307395567143:role/gcds-components-apply - role-session-name: CDNPublish - aws-region: ${{ env.CDN_REGION }} - - - name: Update CDN ${{ matrix.name }} - if: steps.publish.outputs.id != '' - run: | - PUBLISHED_PACKAGE="${{ steps.publish.outputs.id }}" - mkdir -p ./tmp \ - && sleep 60 \ - && npm install --prefix ./tmp "$PUBLISHED_PACKAGE" \ - && cd ./tmp/node_modules - - aws s3 sync ./${{ matrix.name }} s3://${{ env.CDN_BUCKET }}/"$PUBLISHED_PACKAGE" --delete - aws s3 sync ./${{ matrix.name }} s3://${{ env.CDN_BUCKET }}/${{ matrix.name }}@latest --delete - aws s3api head-object --bucket ${{ env.CDN_BUCKET }} --key "$PUBLISHED_PACKAGE"/package.json - aws s3api head-object --bucket ${{ env.CDN_BUCKET }} --key ${{ matrix.name }}@latest/package.json - - aws cloudfront create-invalidation --distribution-id ${{ secrets.CDN_CLOUDFRONT_DIST_ID }} --paths "/*" - working-directory: ${{ matrix.package }} - - name: Report deployment to Sentinel if: steps.publish.outputs.id != '' uses: cds-snc/sentinel-forward-data-action@main diff --git a/.github/workflows/upload-cdn.yml b/.github/workflows/upload-cdn.yml new file mode 100644 index 000000000..91742c9bb --- /dev/null +++ b/.github/workflows/upload-cdn.yml @@ -0,0 +1,78 @@ +name: Upload packages to CDN + +on: + workflow_dispatch: + workflow_run: + workflows: ["Publish packages"] + types: + - completed + +permissions: + id-token: write + contents: read + +env: + CDN_BUCKET: gc-design-system-production-cdn + CDN_REGION: ca-central-1 + +jobs: + unable-to-deploy: + # If this was triggered by a workflow run ("Publish packages" as noted above) and the workflow run failed + if: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' }} + runs-on: ubuntu-latest + steps: + - name: Exit and notify Slack if publishing failed and we can't upload to the CDN + run: | + json='{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":":red: Publishing workflow failed, unable to upload to CDN "}}]}' + curl -X POST -H 'Content-type: application/json' --data "$json" ${{ secrets.SLACK_WEBHOOK_OPS }} + exit 1 + + upload-to-cdn: + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + include: + - name: "web" + package: "@cdssnc/gcds-components" + dist: "./packages/web" + + - name: "react" + package: "@cdssnc/gcds-components-react" + dist: "./packages/react" + + - name: "angular" + package: "@cdssnc/gcds-components-angular" + dist: "./packages/angular/dist" + + - name: "vue" + package: "@cdssnc/gcds-components-vue" + dist: "./packages/vue" + + steps: + - name: Checkout code + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + + - name: Make Upload to CDN script executable + run: chmod +x ./utils/scripts/upload_to_cdn.sh + + - name: Configure AWS credentials using OIDC + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 + with: + role-to-assume: arn:aws:iam::307395567143:role/gcds-components-apply + role-session-name: CDNPublish + aws-region: ${{ env.CDN_REGION }} + + - name: Upload file to S3 + run: ./utils/scripts/upload_to_cdn.sh ${{ matrix.package }} + env: + CDN_CLOUDFRONT_DIST_ID: ${{secrets.CDN_CLOUDFRONT_DIST_ID}} + PACKAGE_PATH: ${{ matrix.dist }} + + - name: Slack notify on failure + if: failure() + run: | + json='{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":":red: CDN upload ${{ matrix.package }} failed: "}}]}' + curl -X POST -H 'Content-type: application/json' --data "$json" ${{ secrets.SLACK_WEBHOOK_OPS }} diff --git a/utils/scripts/upload_to_cdn.sh b/utils/scripts/upload_to_cdn.sh new file mode 100755 index 000000000..53326f55a --- /dev/null +++ b/utils/scripts/upload_to_cdn.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +PACKAGE_NAME=$1 + +## Path to lerna.json +LERNA_JSON="lerna.json" + +# Check if lerna.json exists +if [ ! -f "$LERNA_JSON" ]; then + echo "lerna.json not found!" + exit 1 +fi + +echo "Current working directory: $(pwd)" + +## Read and process lerna.json using jq to get the package version +PACKAGE_VERSION=$(jq -r '.version' $LERNA_JSON) + +echo "PACKAGE_VERSION: $PACKAGE_VERSION" +echo "CDN_BUCKET: $CDN_BUCKET" +echo "PACKAGE_PATH: $PACKAGE_PATH" +echo "PACKAGE_NAME: $PACKAGE_NAME" + +# Get the published package name and version +PUBLISHED_PACKAGE=$PACKAGE_NAME@$PACKAGE_VERSION + +# Install the package from npm +install_package(){ + echo "Installing package: $PUBLISHED_PACKAGE" + mkdir -p ./tmp \ + && npm install --prefix ./tmp "$PUBLISHED_PACKAGE" \ + && cd ./tmp/node_modules +} + +# Upload the package files to the CDN +upload_to_cdn() { + echo "Uploading published package to CDN: $PUBLISHED_PACKAGE" + aws s3 sync ./$PACKAGE_NAME s3://$CDN_BUCKET/"$PUBLISHED_PACKAGE" --delete + aws s3 sync ./$PACKAGE_NAME s3://$CDN_BUCKET/$PACKAGE_NAME@latest --delete + aws s3api head-object --bucket $CDN_BUCKET --key "$PUBLISHED_PACKAGE"/package.json + aws s3api head-object --bucket $CDN_BUCKET --key $PACKAGE_NAME@latest/package.json + + aws cloudfront create-invalidation --distribution-id $CDN_CLOUDFRONT_DIST_ID --paths "/*" +} + +# Retry function +retry() { + local retries=$1 + local delay=$2 + local count=0 + + while [[ $count -lt $retries ]]; do + # Upload the package to the CDN if the package is available and was installed + if install_package; then + upload_to_cdn + return 0 + fi + + count=$((count + 1)) + echo "Retry $count/$retries failed. Retrying in $delay seconds..." + sleep $delay + done + + echo "All $retries retries failed." + return 1 +} + +# Retry 3 times with a 5-second delay in between +retry 3 5