diff --git a/.github/actions/build-and-test/action.yml b/.github/actions/build-and-test/action.yml new file mode 100644 index 000000000..ebad37549 --- /dev/null +++ b/.github/actions/build-and-test/action.yml @@ -0,0 +1,49 @@ +name: 'Build and Test' +description: 'Install dependencies, build, test, and lint packages' +inputs: + node-version: + description: 'Node.js version to use' + required: true + +runs: + using: "composite" + steps: + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: '**/node_modules' + key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} + + - name: Setup Node.js ${{ inputs.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ inputs.node-version }} + registry-url: 'https://registry.npmjs.org' + + - name: Install project dependencies + run: | + yarn install --frozen-lockfile + + - name: Build all packages + run: | + yarn build + + - name: Test all packages + run: | + yarn test + + - name: Lint all packages + run: | + yarn lint + + - name: Configure Git User + run: | + git config --global user.name amplitude-sdk-dev + git config --global user.email 249154226+amplitude-sdk-dev@users.noreply.github.com + + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: arn:aws:iam::358203115967:role/github-actions-role + aws-region: us-west-2 + diff --git a/.github/workflows/feature-branch-prerelease.yml b/.github/workflows/feature-branch-prerelease.yml deleted file mode 100644 index b9f30c97a..000000000 --- a/.github/workflows/feature-branch-prerelease.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: Prerelease feature branch - -on: - workflow_dispatch: - inputs: - releaseType: - type: choice - description: Select dry-run for testing before real prerelease - required: true - options: - - dry-run - - prerelease - - -jobs: - check-npm-token: - name: Check NPM Token - runs-on: ubuntu-latest - steps: - - name: Check NPM token validity - run: | - RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.NPM_PUBLISH_TOKEN }}" https://registry.npmjs.org/-/whoami) - USERNAME=$(echo "$RESPONSE" | jq -r '.username') - if [ "$USERNAME" != "sdk.dev" ]; then - echo "❌ NPM token validation failed!" - echo "Expected username: sdk.dev" - echo "Got username: $USERNAME" - echo "Full response: $RESPONSE" - echo "" - echo "The token may have expired or been revoked." - echo "📖 Token rotation guide: https://amplitude.atlassian.net/wiki/spaces/DBS/pages/3425271816/Migration+plan+Trusted+publisher+OIDC#Granular-access-token" - exit 1 - fi - echo "✅ NPM token is valid (username: $USERNAME)" - - authorize: - name: Authorize - runs-on: ubuntu-latest - needs: [check-npm-token] - steps: - - name: ${{ github.actor }} permission check to do a release - uses: 'lannonbr/repo-permission-check-action@2.0.2' - with: - permission: 'write' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - deploy: - name: Deploy - runs-on: ubuntu-latest - needs: [authorize] - permissions: - id-token: write - contents: write - strategy: - matrix: - node-version: [20.x] - - steps: - - name: Get branch name - id: branch-name - uses: tj-actions/branch-name@v7 - - - name: Check out git repository - uses: actions/checkout@v3 - with: - ref: ${{ steps.branch-name.outputs.ref_branch }} - fetch-depth: 0 - - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - - name: Install project dependencies - run: | - yarn install --frozen-lockfile - - - name: Build all packages - run: | - yarn build - - - name: Test all packages - run: | - yarn test - - - name: Lint all packages - run: | - yarn lint - - - name: Configure Git User - run: | - git config --global user.name amplitude-sdk-bot - git config --global user.email amplitude-sdk-bot@users.noreply.github.com - - - name: Configure NPM User - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_PUBLISH_TOKEN }}" > ~/.npmrc - npm whoami - - # Keep alphanumeric characters and hyphens, remove other invalid characters - # Examples: - # - SR-1858 -> SR-1858 - # - feature/my-branch -> featuremy-branch - # - fix_bug_123 -> fixbug123 - # - user@company.com -> usercompanycom - - name: Transform feature branch name - run: | - echo "PREID=$(echo '${{ steps.branch-name.outputs.current_branch }}' | tr -cd '[:alnum:]-')" >> $GITHUB_ENV - - # Use --no-push to prevent pushing to remote - # Version example: 1.0.0 -> 1.1.0-{preid}.0 - - name: Dry run pre-release version - if: ${{ github.event.inputs.releaseType == 'dry-run' }} - run: | - GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:version -- -y --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.branch-name.outputs.current_branch }} --no-changelog --no-push - - - name: Pre-release version - if: ${{ github.event.inputs.releaseType == 'prerelease' }} - run: | - GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:version -- -y --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.branch-name.outputs.current_branch }} --create-release github - - # Use 'from git' option if `lerna version` has already been run - - name: Publish Release to NPM - if: ${{ github.event.inputs.releaseType == 'prerelease' }} - run: | - GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:publish -- from-git -y --ignore-scripts --pre-dist-tag ${{ env.PREID }} - diff --git a/.github/workflows/publish-v2.yml b/.github/workflows/publish-v2.yml index b2daad128..69a4317d0 100644 --- a/.github/workflows/publish-v2.yml +++ b/.github/workflows/publish-v2.yml @@ -3,9 +3,22 @@ name: Publish v2.x on: workflow_dispatch: inputs: + releaseType: + type: choice + description: Release type (release for main branch, prerelease for feature branches) + required: true + default: release + options: + - release + - prerelease + - dry-run publishFrom: type: string - description: Publish source (leave empty for from-git, or enter "from-package") + description: Publish source (leave empty for from-git, or enter "from-package"). Only applies to 'release' type. + required: false + branch: + type: string + description: Branch to create pre-release from (only applies to prerelease/dry-run). Leave empty to use current branch. required: false jobs: @@ -13,6 +26,15 @@ jobs: name: Authorize runs-on: ubuntu-latest steps: + - name: Check branch protection + run: | + if [ "${{ github.ref_name }}" != "main" ]; then + echo "❌ This workflow can only be triggered from the main branch." + echo "Current branch: ${{ github.ref_name }}" + exit 1 + fi + echo "✅ Branch check passed: running from main" + - name: ${{ github.actor }} permission check to do a release uses: 'lannonbr/repo-permission-check-action@2.0.2' with: @@ -24,6 +46,7 @@ jobs: name: Deploy runs-on: ubuntu-latest needs: [authorize] + if: ${{ github.event.inputs.releaseType == 'release' }} permissions: id-token: write # Required for OIDC contents: write @@ -40,44 +63,10 @@ jobs: fetch-depth: 0 token: ${{ secrets.GH_PUBLISH_TOKEN }} - - name: Cache dependencies - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }} - - - name: Setup Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + - name: Build and Test + uses: ./.github/actions/build-and-test with: node-version: ${{ matrix.node-version }} - registry-url: 'https://registry.npmjs.org' - - - name: Install project dependencies - run: | - yarn install --frozen-lockfile - - - name: Build all packages - run: | - yarn build - - - name: Test all packages - run: | - yarn test - - - name: Lint all packages - run: | - yarn lint - - - name: Configure Git User - run: | - git config --global user.name amplitude-sdk-dev - git config --global user.email 249154226+amplitude-sdk-dev@users.noreply.github.com - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v2 - with: - role-to-assume: arn:aws:iam::358203115967:role/github-actions-role - aws-region: us-west-2 # Only create release version when using from-git (default behavior) # from-package mode uses existing package.json versions and doesn't need git tags @@ -120,3 +109,66 @@ jobs: GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:publish -- ${{ env.PUBLISH_FROM }} -y --pre-dist-tag beta --loglevel silly env: S3_BUCKET_NAME: ${{ secrets.S3_BUCKET_NAME }} + + prerelease: + name: Prerelease feature branch + runs-on: ubuntu-latest + needs: [authorize] + if: ${{ github.event.inputs.releaseType == 'prerelease' || github.event.inputs.releaseType == 'dry-run' }} + permissions: + id-token: write # Required for OIDC + contents: write + strategy: + matrix: + node-version: [24.x] # Ensure npm 11.5.1 or later is installed for OIDC, node 24.6 is minimal + + steps: + - name: Determine branch to use + id: determine-branch + run: | + if [ -n "${{ github.event.inputs.branch }}" ]; then + echo "branch=${{ github.event.inputs.branch }}" >> $GITHUB_OUTPUT + else + echo "branch=${{ github.ref_name }}" >> $GITHUB_OUTPUT + fi + + - name: Check out git repository + uses: actions/checkout@v3 + with: + ref: ${{ steps.determine-branch.outputs.branch }} + fetch-depth: 0 + + - name: Build and Test + uses: ./.github/actions/build-and-test + with: + node-version: ${{ matrix.node-version }} + + # Keep alphanumeric characters and hyphens, remove other invalid characters + # Examples: + # - SR-1858 -> SR-1858 + # - feature/my-branch -> featuremy-branch + # - fix_bug_123 -> fixbug123 + # - user@company.com -> usercompanycom + - name: Transform feature branch name + run: | + echo "PREID=$(echo '${{ steps.determine-branch.outputs.branch }}' | tr -cd '[:alnum:]-')" >> $GITHUB_ENV + + # Use --no-push to prevent pushing to remote + # Version example: 1.0.0 -> 1.1.0-{preid}.0 + - name: Dry run pre-release version + if: ${{ github.event.inputs.releaseType == 'dry-run' }} + run: | + GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:version -- -y --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version + + - name: Pre-release version + if: ${{ github.event.inputs.releaseType == 'prerelease' }} + run: | + GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:version -- -y --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --create-release github + + # Use 'from git' option if `lerna version` has already been run + - name: Publish Release to NPM + if: ${{ github.event.inputs.releaseType == 'prerelease' }} + run: | + GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:publish -- from-git -y --ignore-scripts --pre-dist-tag ${{ env.PREID }} + env: + S3_BUCKET_NAME: ${{ secrets.S3_BUCKET_NAME }}