diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b71bd210d2..9fe4ecf9fc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -49,7 +49,8 @@ permissions: env: NODE_OPTIONS: "--no-warnings" - CACHE_CONTROL: "\"no-store\"" # "\"max-age=3600\"" + CACHE_CONTROL_NO_STORE: "\"no-store\"" + CACHE_CONTROL_MAX_AGE: "\"max-age=3600\"" jobs: deploy: @@ -77,12 +78,12 @@ jobs: echo "Checkout SHA: $sha" echo "SHA=$sha" >> $GITHUB_OUTPUT - - name: Checkout + - name: Checkout source code uses: actions/checkout@v4 with: ref: ${{ steps.getSHA.outputs.SHA }} - - name: Get new version number + - name: Get new versions run: | current_version_v1=$(jq -r .version packages/analytics-v1.1/package.json) current_version=$(jq -r .version packages/analytics-js/package.json) @@ -96,7 +97,7 @@ jobs: node-version-file: '.nvmrc' cache: 'npm' - - name: Install dependencies + - name: Setup workspace env: HUSKY: 0 REMOTE_MODULES_BASE_PATH: 'https://cdn.rudderlabs.com/${{ inputs.s3_dir_path }}/modern/plugins' @@ -105,7 +106,7 @@ jobs: run: | npm run setup:ci - - name: Build release artifacts + - name: Build artifacts env: BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} BUGSNAG_RELEASE_STAGE: ${{ inputs.bugsnag_release_stage }} @@ -113,23 +114,36 @@ jobs: npm run build:browser npm run build:browser:modern - - name: Sync Adobe Analytics assets to S3 + - name: Copy assets to S3 if: ${{ inputs.environment == 'production' }} run: | - aws s3 cp assets/integrations/AdobeAnalytics/ s3://${{ secrets.AWS_S3_BUCKET_NAME }}/adobe-analytics-js --recursive --cache-control ${{ env.CACHE_CONTROL }} + aws s3 cp assets/integrations/AdobeAnalytics/ s3://${{ secrets.AWS_S3_BUCKET_NAME }}/adobe-analytics-js --recursive --cache-control ${{ env.CACHE_CONTROL_NO_STORE }} - - name: Create Cloudfront invalidation + - name: Invalidate CloudFront cache for assets if: ${{ inputs.environment == 'production' }} run: | - aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/adobe-analytics-js*" + invalidation_id=$(AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/adobe-analytics-js*" --query "Invalidation.Id" --output text) - - name: Sync files to S3 + aws cloudfront wait invalidation-completed --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --id "$invalidation_id" + + - name: Determine cache policy based on environment + id: cache_policy + run: | + if [ "${{ inputs.environment }}" == "production" ]; then + echo "CACHE_CONTROL=${{ env.CACHE_CONTROL_NO_STORE }}" >> $GITHUB_ENV + else + echo "CACHE_CONTROL=${{ env.CACHE_CONTROL_MAX_AGE }}" >> $GITHUB_ENV + fi + + - name: Copy SDK artifacts to S3 run: | core_sdk_path_prefix="packages/analytics-js/dist/cdn" integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" plugins_path_prefix="packages/analytics-js-plugins/dist/cdn" - s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/${{ inputs.s3_dir_path }}" - copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" + s3_relative_path_prefix="${{ inputs.s3_dir_path }}" + s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/$s3_relative_path_prefix" + copy_recursive_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" + copy_args="--cache-control ${{ env.CACHE_CONTROL }}" integration_sdks_zip_file="all_integration_sdks.tar.gz" plugins_zip_file="all_plugins.tar.gz" @@ -152,72 +166,76 @@ jobs: mv "$tmp_file" "$plugins_path_prefix/modern/plugins/$plugins_zip_file" # Upload all the files to S3 - aws s3 cp $core_sdk_path_prefix/legacy/iife/ $s3_path_prefix/legacy/ $copy_args - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/legacy/js-integrations/ $copy_args + aws s3 cp $core_sdk_path_prefix/legacy/iife/ $s3_path_prefix/legacy/ $copy_recursive_args + aws s3 cp $core_sdk_path_prefix/modern/iife/ $s3_path_prefix/modern/ $copy_recursive_args - aws s3 cp $core_sdk_path_prefix/modern/iife/ $s3_path_prefix/modern/ $copy_args - aws s3 cp $plugins_path_prefix/modern/plugins/ $s3_path_prefix/modern/plugins/ $copy_args - aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/legacy/js-integrations/ $copy_recursive_args + aws s3 cp $plugins_path_prefix/modern/plugins/ $s3_path_prefix/modern/plugins/ $copy_recursive_args + aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_recursive_args # Generate the HTML file to list all the integrations - ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} ${{ inputs.s3_dir_path }}/legacy/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/legacy/js-integrations "Device Mode Integrations" $integration_sdks_zip_file + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/legacy/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/legacy/js-integrations "Device Mode Integrations (Legacy)" $integration_sdks_zip_file - ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} ${{ inputs.s3_dir_path }}/modern/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/modern/js-integrations "Device Mode Integrations" $integration_sdks_zip_file + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/modern/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/modern/js-integrations "Device Mode Integrations (Modern)" $integration_sdks_zip_file # Generate the HTML file to list all the plugins - ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} ${{ inputs.s3_dir_path }}/modern/plugins $plugins_html_file $plugins_path_prefix/modern/plugins "Plugins" $plugins_zip_file + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/modern/plugins $plugins_html_file $plugins_path_prefix/modern/plugins "Plugins" $plugins_zip_file # Copy the HTML files to S3 - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/$integration_sdks_html_file $s3_path_prefix/legacy/js-integrations/$integration_sdks_html_file --cache-control ${{ env.CACHE_CONTROL }} - aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/$integration_sdks_html_file $s3_path_prefix/modern/js-integrations/$integration_sdks_html_file --cache-control ${{ env.CACHE_CONTROL }} - aws s3 cp $plugins_path_prefix/modern/plugins/$plugins_html_file $s3_path_prefix/modern/plugins/$plugins_html_file --cache-control ${{ env.CACHE_CONTROL }} + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/$integration_sdks_html_file $s3_path_prefix/legacy/js-integrations/$integration_sdks_html_file $copy_args + aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/$integration_sdks_html_file $s3_path_prefix/modern/js-integrations/$integration_sdks_html_file $copy_args + aws s3 cp $plugins_path_prefix/modern/plugins/$plugins_html_file $s3_path_prefix/modern/plugins/$plugins_html_file $copy_args - - name: Create Cloudfront invalidation + - name: Invalidate CloudFront cache for all the SDK artifacts run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ inputs.s3_dir_path }}/*" + invalidation_id=$(AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ inputs.s3_dir_path }}/*" --query "Invalidation.Id" --output text) - - name: Sync files to S3 versioned directory + aws cloudfront wait invalidation-completed --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --id "$invalidation_id" + + - name: Copy SDK artifacts to S3 (versioned directory) if: ${{ inputs.environment == 'production' }} run: | core_sdk_path_prefix="packages/analytics-js/dist/cdn" integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" plugins_path_prefix="packages/analytics-js-plugins/dist/cdn" - s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/${{ env.CURRENT_VERSION_VALUE }}" - copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" + s3_relative_path_prefix="${{ env.CURRENT_VERSION_VALUE }}" + s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/$s3_relative_path_prefix" + copy_recursive_args="--recursive --cache-control ${{ env.CACHE_CONTROL_MAX_AGE }}" + copy_args="--cache-control ${{ env.CACHE_CONTROL_MAX_AGE }}" - aws s3 cp $core_sdk_path_prefix/legacy/iife/ $s3_path_prefix/legacy/ $copy_args - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/legacy/js-integrations/ $copy_args + integration_sdks_zip_file="all_integration_sdks.tar.gz" + plugins_zip_file="all_plugins.tar.gz" - aws s3 cp $core_sdk_path_prefix/modern/iife/ $s3_path_prefix/modern/ $copy_args - aws s3 cp $plugins_path_prefix/modern/plugins/ $s3_path_prefix/modern/plugins/ $copy_args - aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args + integration_sdks_html_file="list.html" + plugins_html_file="list.html" - - name: Create Cloudfront invalidation - if: ${{ inputs.environment == 'production' }} - run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ env.CURRENT_VERSION_VALUE }}/*" + # Copy all the files to S3 + aws s3 cp $core_sdk_path_prefix/legacy/iife/ $s3_path_prefix/legacy/ $copy_recursive_args + aws s3 cp $core_sdk_path_prefix/modern/iife/ $s3_path_prefix/modern/ $copy_recursive_args - # TODO: The '/latest' directory is unused. Might be removed in future. - - name: Sync files to S3 latest - if: ${{ inputs.environment == 'production' }} - run: | - core_sdk_path_prefix="packages/analytics-js/dist/cdn" - integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" - plugins_path_prefix="packages/analytics-js-plugins/dist/cdn" - s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/latest" - copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/legacy/js-integrations/ $copy_recursive_args + aws s3 cp $plugins_path_prefix/modern/plugins/ $s3_path_prefix/modern/plugins/ $copy_recursive_args + aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_recursive_args - aws s3 cp $core_sdk_path_prefix/legacy/iife/ $s3_path_prefix/legacy/ $copy_args - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/legacy/js-integrations/ $copy_args + # Generate the HTML file to list all the integrations + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/legacy/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/legacy/js-integrations "Device Mode Integrations (Legacy)" $integration_sdks_zip_file - aws s3 cp $core_sdk_path_prefix/modern/iife/ $s3_path_prefix/modern/ $copy_args - aws s3 cp $plugins_path_prefix/modern/plugins/ $s3_path_prefix/modern/plugins/ $copy_args - aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/modern/js-integrations $integration_sdks_html_file $integration_sdks_path_prefix/modern/js-integrations "Device Mode Integrations (Modern)" $integration_sdks_zip_file + + # Generate the HTML file to list all the plugins + ./scripts/list-sdk-components.sh ${{ secrets.AWS_S3_BUCKET_NAME }} $s3_relative_path_prefix/modern/plugins $plugins_html_file $plugins_path_prefix/modern/plugins "Plugins" $plugins_zip_file + + # Copy all the HTML files to S3 + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/$integration_sdks_html_file $s3_path_prefix/legacy/js-integrations/$integration_sdks_html_file $copy_args + aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/$integration_sdks_html_file $s3_path_prefix/modern/js-integrations/$integration_sdks_html_file $copy_args + aws s3 cp $plugins_path_prefix/modern/plugins/$plugins_html_file $s3_path_prefix/modern/plugins/$plugins_html_file $copy_args - - name: Create Cloudfront invalidation + - name: Invalidate CloudFront cache for all the SDK artifacts (versioned directory) if: ${{ inputs.environment == 'production' }} run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/latest*" + invalidation_id=$(AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ env.CURRENT_VERSION_VALUE }}/*" --query "Invalidation.Id" --output text) + + aws cloudfront wait invalidation-completed --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --id "$invalidation_id" - name: Send message to Slack channel id: slack @@ -263,7 +281,7 @@ jobs: # Below steps are for v1.1 SDK (legacy) - - name: Sync files to S3 v1.1 directory + - name: Copy legacy SDK artifacts to S3 run: | core_sdk_path_prefix="packages/analytics-v1.1/dist/cdn" integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" @@ -271,49 +289,34 @@ jobs: copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" aws s3 cp $core_sdk_path_prefix/legacy/ $s3_path_prefix/ $copy_args - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/js-integrations/ $copy_args - aws s3 cp $core_sdk_path_prefix/modern/ $s3_path_prefix/modern/ $copy_args + + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/js-integrations/ $copy_args aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args - - name: Create Cloudfront invalidation + - name: Invalidate CloudFront cache for all the legacy SDK artifacts run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ inputs.s3_dir_path_legacy }}*" + invalidation_id=$(AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ inputs.s3_dir_path_legacy }}/*" --query "Invalidation.Id" --output text) + + aws cloudfront wait invalidation-completed --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --id "$invalidation_id" - - name: Sync files to S3 v1.1 versioned directory + - name: Copy legacy SDK artifacts to S3 (versioned directory) if: ${{ inputs.environment == 'production' }} run: | core_sdk_path_prefix="packages/analytics-v1.1/dist/cdn" integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/${{ env.CURRENT_VERSION_V1_VALUE }}" - copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" + copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL_MAX_AGE }}" aws s3 cp $core_sdk_path_prefix/legacy/ $s3_path_prefix/ $copy_args - aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/js-integrations/ $copy_args - aws s3 cp $core_sdk_path_prefix/modern/ $s3_path_prefix/modern/ $copy_args - aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args - - - name: Create Cloudfront invalidation - if: ${{ inputs.environment == 'production' }} - run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ env.CURRENT_VERSION_V1_VALUE }}*" - - - name: Sync files to S3 latest (v1.1) - if: ${{ inputs.environment == 'production' }} - run: | - core_sdk_path_prefix="packages/analytics-v1.1/dist/cdn" - integration_sdks_path_prefix="packages/analytics-js-integrations/dist/cdn" - s3_path_prefix="s3://${{ secrets.AWS_S3_BUCKET_NAME }}/latest" - copy_args="--recursive --cache-control ${{ env.CACHE_CONTROL }}" - - aws s3 cp $core_sdk_path_prefix/legacy/ $s3_path_prefix/ $copy_args + aws s3 cp $integration_sdks_path_prefix/legacy/js-integrations/ $s3_path_prefix/js-integrations/ $copy_args - - aws s3 cp $core_sdk_path_prefix/modern/ $s3_path_prefix/modern/ $copy_args aws s3 cp $integration_sdks_path_prefix/modern/js-integrations/ $s3_path_prefix/modern/js-integrations/ $copy_args - - name: Create Cloudfront invalidation + - name: Invalidate CloudFront cache for all the legacy SDK artifacts (versioned directory) if: ${{ inputs.environment == 'production' }} run: | - AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/latest*" + invalidation_id=$(AWS_MAX_ATTEMPTS=10 aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --paths "/${{ env.CURRENT_VERSION_V1_VALUE }}/*" --query "Invalidation.Id" --output text) + + aws cloudfront wait invalidation-completed --distribution-id ${{ secrets.AWS_CF_DISTRIBUTION_ID }} --id "$invalidation_id" diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 0d63cd39a8..e1146582a5 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -11,10 +11,17 @@ env: NODE_OPTIONS: '--no-warnings' jobs: + validate-actor: + # Only allow to draft a new release from develop and hotfix branches + if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/hotfix/') + uses: ./.github/workflows/validate-actor.yml + secrets: + PAT: ${{ secrets.PAT }} + draft-new-release: + needs: validate-actor name: Draft a new release runs-on: [self-hosted, Linux, X64] - if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/heads/hotfix/') steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/rollback.yml b/.github/workflows/rollback.yml index 6bc29c88c1..f1d3589e26 100644 --- a/.github/workflows/rollback.yml +++ b/.github/workflows/rollback.yml @@ -4,9 +4,16 @@ on: workflow_dispatch: jobs: + validate-actor: + # Only allow to be deployed from tags and main branch + if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' + uses: ./.github/workflows/validate-actor.yml + secrets: + PAT: ${{ secrets.PAT }} + deploy: + needs: validate-actor name: Rollback production deployment - if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' uses: ./.github/workflows/deploy.yml with: environment: 'production' diff --git a/.github/workflows/update-cache-policy.yml b/.github/workflows/update-cache-policy.yml new file mode 100644 index 0000000000..26a1856ed3 --- /dev/null +++ b/.github/workflows/update-cache-policy.yml @@ -0,0 +1,68 @@ +name: Update cache control policy + +on: + workflow_dispatch: + inputs: + policy_type: + type: choice + description: Select the cache control policy type + required: true + options: + - no-store + - max-age=3600 + +permissions: + id-token: write # allows the JWT to be requested from GitHub's OIDC provider + contents: read # This is required for actions/checkout + +jobs: + validate-actor: + # Only allow to be deployed from tags and main branch + if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' + uses: ./.github/workflows/validate-actor.yml + secrets: + PAT: ${{ secrets.PAT }} + + update-cache-policy: + needs: validate-actor + name: Update cache control policy for SDK artifacts + runs-on: [self-hosted, Linux, X64] + + steps: + - name: Install AWS CLI + uses: unfor19/install-aws-cli-action@master + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::${{ secrets.AWS_PROD_ACCOUNT_ID }}:role/${{ secrets.AWS_PROD_S3_SYNC_ROLE }} + aws-region: us-east-1 + + - name: Determine the cache control policy + id: determine_policy + run: | + echo "cache_control_policy=${{ github.event.inputs.policy_type || inputs.policy_type }}" >> $GITHUB_ENV + + - name: Update cache control policy + run: | + # Get the number of CPU cores in the runner and leave one core free + num_cores=$(nproc --ignore=1 || echo 1) # Default to 1 if nproc is unavailable + # Use a factor to set the parallel jobs (e.g., number of cores or slightly lower) + parallel_jobs=$((num_cores * 2)) + echo "Detected $num_cores cores. Using $parallel_jobs parallel jobs." + + prefixes=("adobe-analytics-js" "v3" "v1.1") + + for prefix in "${prefixes[@]}"; do + echo "Processing prefix: $prefix" + + aws s3api list-objects --bucket ${{ secrets.AWS_PROD_S3_BUCKET_NAME }} --prefix "$prefix" --query "Contents[].Key" --output text | tr '\t' '\n' | \ + parallel --retries 10 -j "$parallel_jobs" "aws s3api copy-object \ + --bucket ${{ secrets.AWS_PROD_S3_BUCKET_NAME }} \ + --copy-source ${{ secrets.AWS_PROD_S3_BUCKET_NAME }}/{} \ + --key {} \ + --metadata-directive REPLACE \ + --cache-control '${{ env.cache_control_policy }}'" + done + + diff --git a/.github/workflows/validate-actor.yml b/.github/workflows/validate-actor.yml new file mode 100644 index 0000000000..15981efc51 --- /dev/null +++ b/.github/workflows/validate-actor.yml @@ -0,0 +1,30 @@ +name: Validate Actor + +on: + workflow_call: + secrets: + PAT: + required: true + +jobs: + validate-actor: + runs-on: [self-hosted, Linux, X64] + steps: + - name: Validate if actor is allowed to trigger the workflow + env: + ORG_NAME: rudderlabs + TEAM_NAME: js-sdk + run: | + actor=${{ github.actor || github.triggering_actor }} + response=$(curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.PAT }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/orgs/${{ env.ORG_NAME }}/teams/${{ env.TEAM_NAME }}/memberships/$actor) + + if echo "$response" | grep -q '"state": "active"'; then + echo "$actor is a member of $TEAM_NAME team" + else + echo "$actor is NOT a member of $TEAM_NAME team" + exit 1 + fi diff --git a/package-lock.json b/package-lock.json index 19ac8d70d1..fc983fe54c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@rudderstack/analytics-js-monorepo", - "version": "3.68.0", + "version": "3.69.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@rudderstack/analytics-js-monorepo", - "version": "3.68.0", + "version": "3.69.0", "hasInstallScript": true, "license": "Elastic-2.0", "workspaces": [ @@ -25347,7 +25347,7 @@ }, "packages/analytics-js-plugins": { "name": "@rudderstack/analytics-js-plugins", - "version": "3.6.18", + "version": "3.6.19", "license": "Elastic-2.0", "dependencies": { "@rudderstack/analytics-js-common": "*", diff --git a/package.json b/package.json index f97fb09d68..fce5641a67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rudderstack/analytics-js-monorepo", - "version": "3.68.0", + "version": "3.69.0", "private": true, "description": "Monorepo for RudderStack Analytics JS SDK", "workspaces": [ diff --git a/packages/analytics-js-plugins/CHANGELOG.md b/packages/analytics-js-plugins/CHANGELOG.md index 2dd234d70a..85a4963512 100644 --- a/packages/analytics-js-plugins/CHANGELOG.md +++ b/packages/analytics-js-plugins/CHANGELOG.md @@ -2,6 +2,12 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +## [3.6.19](https://github.com/rudderlabs/rudder-sdk-js/compare/@rudderstack/analytics-js-plugins@3.6.18...@rudderstack/analytics-js-plugins@3.6.19) (2024-12-13) + +### Dependency Updates + +* `@rudderstack/analytics-js` updated to version `3.11.15` +* `@rudderstack/analytics-js-cookies` updated to version `0.4.16` ## [3.6.18](https://github.com/rudderlabs/rudder-sdk-js/compare/@rudderstack/analytics-js-plugins@3.6.17...@rudderstack/analytics-js-plugins@3.6.18) (2024-12-06) ### Dependency Updates diff --git a/packages/analytics-js-plugins/CHANGELOG_LATEST.md b/packages/analytics-js-plugins/CHANGELOG_LATEST.md index 21a9836db6..cfdb502faa 100644 --- a/packages/analytics-js-plugins/CHANGELOG_LATEST.md +++ b/packages/analytics-js-plugins/CHANGELOG_LATEST.md @@ -1,6 +1,6 @@ -## [3.6.18](https://github.com/rudderlabs/rudder-sdk-js/compare/@rudderstack/analytics-js-plugins@3.6.17...@rudderstack/analytics-js-plugins@3.6.18) (2024-12-06) +## [3.6.19](https://github.com/rudderlabs/rudder-sdk-js/compare/@rudderstack/analytics-js-plugins@3.6.18...@rudderstack/analytics-js-plugins@3.6.19) (2024-12-13) ### Dependency Updates -* `@rudderstack/analytics-js-common` updated to version `3.14.13` -* `@rudderstack/analytics-js` updated to version `3.11.14` +* `@rudderstack/analytics-js` updated to version `3.11.15` +* `@rudderstack/analytics-js-cookies` updated to version `0.4.16` diff --git a/packages/analytics-js-plugins/__tests__/bugsnag/index.test.ts b/packages/analytics-js-plugins/__tests__/bugsnag/index.test.ts index 4c6674bc45..0e1cb4b01a 100644 --- a/packages/analytics-js-plugins/__tests__/bugsnag/index.test.ts +++ b/packages/analytics-js-plugins/__tests__/bugsnag/index.test.ts @@ -22,6 +22,14 @@ describe('Plugin - Bugsnag', () => { installType: 'npm', }), }, + session: { + sessionInfo: signal({ id: 'test-session-id' }), + }, + autoTrack: { + pageLifecycle: { + visitId: signal('test-visit-id'), + }, + }, }; let state: any; diff --git a/packages/analytics-js-plugins/__tests__/bugsnag/utils.test.ts b/packages/analytics-js-plugins/__tests__/bugsnag/utils.test.ts index 6d58890430..4891ede13c 100644 --- a/packages/analytics-js-plugins/__tests__/bugsnag/utils.test.ts +++ b/packages/analytics-js-plugins/__tests__/bugsnag/utils.test.ts @@ -40,6 +40,14 @@ beforeEach(() => { lifecycle: { writeKey: signal('dummy-write-key'), }, + session: { + sessionInfo: signal({ id: 'test-session-id' }), + }, + autoTrack: { + pageLifecycle: { + visitId: signal('test-visit-id'), + }, + }, }; }); @@ -235,6 +243,14 @@ describe('Bugsnag utilities', () => { installType: 'npm', }, }, + session: { + sessionInfo: { id: 'test-session-id' }, + }, + autoTrack: { + pageLifecycle: { + visitId: 'test-visit-id', + }, + }, }, }); @@ -277,6 +293,14 @@ describe('Bugsnag utilities', () => { installType: 'npm', }, }, + session: { + sessionInfo: { id: 'test-session-id' }, + }, + autoTrack: { + pageLifecycle: { + visitId: 'test-visit-id', + }, + }, }, }); @@ -338,7 +362,7 @@ describe('Bugsnag utilities', () => { maxBreadcrumbs: 40, releaseStage: 'development', user: { - id: 'dummy-source-id', + id: 'dummy-source-id..test-session-id..test-visit-id', }, networkBreadcrumbsEnabled: false, beforeSend: expect.any(Function), @@ -377,7 +401,7 @@ describe('Bugsnag utilities', () => { maxBreadcrumbs: 40, releaseStage: 'development', user: { - id: 'dummy-write-key', + id: 'dummy-write-key..test-session-id..test-visit-id', }, networkBreadcrumbsEnabled: false, beforeSend: expect.any(Function), @@ -527,6 +551,14 @@ describe('Bugsnag utilities', () => { installType: 'npm', }, }, + session: { + sessionInfo: { id: 'test-session-id' }, + }, + autoTrack: { + pageLifecycle: { + visitId: 'test-visit-id', + }, + }, }); expect(error.severity).toBe('error'); expect(error.context).toBe('Script load failures'); diff --git a/packages/analytics-js-plugins/__tests__/errorReporting/index.test.ts b/packages/analytics-js-plugins/__tests__/errorReporting/index.test.ts index f1cab14dca..c956a16d6e 100644 --- a/packages/analytics-js-plugins/__tests__/errorReporting/index.test.ts +++ b/packages/analytics-js-plugins/__tests__/errorReporting/index.test.ts @@ -24,6 +24,14 @@ describe('Plugin - ErrorReporting', () => { id: 'test-source-id', config: {}, }), + session: { + sessionInfo: signal({ id: 'test-session-id' }), + }, + autoTrack: { + pageLifecycle: { + visitId: signal('test-visit-id'), + }, + }, }; let state: any; diff --git a/packages/analytics-js-plugins/__tests__/errorReporting/utils.test.ts b/packages/analytics-js-plugins/__tests__/errorReporting/utils.test.ts index 1853279900..eee1c438e6 100644 --- a/packages/analytics-js-plugins/__tests__/errorReporting/utils.test.ts +++ b/packages/analytics-js-plugins/__tests__/errorReporting/utils.test.ts @@ -319,6 +319,14 @@ describe('Error Reporting utilities', () => { breadcrumbs: signal([]), }, source: signal({ id: 'sample_source_id' }), + session: { + sessionInfo: signal({ id: 'test-session-id' }), + }, + autoTrack: { + pageLifecycle: { + visitId: signal('test-visit-id'), + }, + }, }; (window as any).RudderSnippetVersion = 'sample_snippet_version'; const enhancedError = getBugsnagErrorEvent(errorPayload, errorState, appState); @@ -392,13 +400,23 @@ describe('Error Reporting utilities', () => { source: { id: 'sample_source_id', }, + session: { + sessionInfo: { + id: 'test-session-id', + }, + }, + autoTrack: { + pageLifecycle: { + visitId: 'test-visit-id', + }, + }, }, source: { snippetVersion: 'sample_snippet_version', }, }, user: { - id: 'sample_source_id', + id: 'sample_source_id..test-session-id..test-visit-id', }, }, ], diff --git a/packages/analytics-js-plugins/package.json b/packages/analytics-js-plugins/package.json index c9aa047025..46be478981 100644 --- a/packages/analytics-js-plugins/package.json +++ b/packages/analytics-js-plugins/package.json @@ -1,6 +1,6 @@ { "name": "@rudderstack/analytics-js-plugins", - "version": "3.6.18", + "version": "3.6.19", "private": true, "description": "RudderStack JavaScript SDK plugins", "main": "dist/npm/modern/cjs/index.cjs", diff --git a/packages/analytics-js-plugins/project.json b/packages/analytics-js-plugins/project.json index 806a31ff27..2ada07f0ef 100644 --- a/packages/analytics-js-plugins/project.json +++ b/packages/analytics-js-plugins/project.json @@ -51,9 +51,9 @@ "github": { "executor": "@jscutlery/semver:github", "options": { - "tag": "@rudderstack/analytics-js-plugins@3.6.18", - "title": "@rudderstack/analytics-js-plugins@3.6.18", - "discussion-category": "@rudderstack/analytics-js-plugins@3.6.18", + "tag": "@rudderstack/analytics-js-plugins@3.6.19", + "title": "@rudderstack/analytics-js-plugins@3.6.19", + "discussion-category": "@rudderstack/analytics-js-plugins@3.6.19", "notesFile": "./packages/analytics-js-plugins/CHANGELOG_LATEST.md" } } diff --git a/packages/analytics-js-plugins/src/bugsnag/utils.ts b/packages/analytics-js-plugins/src/bugsnag/utils.ts index 135054ef83..e1c159dcae 100644 --- a/packages/analytics-js-plugins/src/bugsnag/utils.ts +++ b/packages/analytics-js-plugins/src/bugsnag/utils.ts @@ -136,7 +136,8 @@ const getNewClient = (state: ApplicationState, logger?: ILogger): BugsnagLib.Cli maxBreadcrumbs: 40, releaseStage: getReleaseStage(), user: { - id: state.source.value?.id || state.lifecycle.writeKey.value, + // Combination of source, session and visit ids + id: `${state.source.value?.id ?? (state.lifecycle.writeKey.value as string)}..${state.session.sessionInfo.value?.id ?? 'NA'}..${state.autoTrack?.pageLifecycle?.visitId?.value ?? 'NA'}`, }, logger, networkBreadcrumbsEnabled: false, diff --git a/packages/analytics-js-plugins/src/errorReporting/utils.ts b/packages/analytics-js-plugins/src/errorReporting/utils.ts index ced6d752b6..ef8fadc3bc 100644 --- a/packages/analytics-js-plugins/src/errorReporting/utils.ts +++ b/packages/analytics-js-plugins/src/errorReporting/utils.ts @@ -132,7 +132,8 @@ const getBugsnagErrorEvent = ( }, }, user: { - id: state.source.value?.id ?? (state.lifecycle.writeKey.value as string), + // Combination of source, session and visit ids + id: `${state.source.value?.id ?? (state.lifecycle.writeKey.value as string)}..${state.session.sessionInfo.value?.id ?? 'NA'}..${state.autoTrack?.pageLifecycle?.visitId?.value ?? 'NA'}`, }, }, ], diff --git a/packages/analytics-js/.size-limit.mjs b/packages/analytics-js/.size-limit.mjs index d55635d440..82b89e09dc 100644 --- a/packages/analytics-js/.size-limit.mjs +++ b/packages/analytics-js/.size-limit.mjs @@ -13,7 +13,7 @@ export default [ name: 'Core - Legacy - NPM (CJS)', path: 'dist/npm/legacy/cjs/index.cjs', import: '*', - limit: '49 KiB', + limit: '49.1 KiB', }, { name: 'Core - Legacy - NPM (UMD)', diff --git a/sonar-project.properties b/sonar-project.properties index 5a2a942a1b..d569619a3b 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.qualitygate.wait=false sonar.projectKey=rudderlabs_rudder-sdk-js sonar.organization=rudderlabs sonar.projectName=rudder-sdk-js -sonar.projectVersion=3.68.0 +sonar.projectVersion=3.69.0 # Meta-data for the project sonar.links.scm=https://github.com/rudderlabs/rudder-sdk-js