-
Notifications
You must be signed in to change notification settings - Fork 244
ci: create a release pipeline to release 1st gen and 2nd gen #5978
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
56e4ee5
15293fb
27a002e
c9b45f3
ea9c6ef
40bc802
54c19ef
7098a52
fb6021b
091fc77
f42a472
f1ad6a7
2f925a6
cc8cee9
ecc9239
800e373
96a07ff
e76d760
8958701
b8cf8ff
c983f5d
1f5af05
e958a57
ec9f1c0
2bd5b2b
3c7be15
29390a5
6622b8e
4233318
921a7fc
8bd5faa
822a4ef
5d6dbe3
dae6c25
653f689
a36ef82
7f76948
5578a76
3af7742
640b8e3
b46e0c1
25b6c9e
b95c82f
4f5812b
a0ba779
5eb6a33
0606d70
657ec08
bb55ab6
6954a44
efd04ef
283048c
e85afa4
dbaf007
ab7ff71
21f3581
11fab32
21db25f
7a638f8
79e2c6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, let's not forget to add a ticket to eventually change this to a more general |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,315 @@ | ||||||||||||
| name: Publish Packages | ||||||||||||
|
|
||||||||||||
| on: | ||||||||||||
| workflow_dispatch: | ||||||||||||
| inputs: | ||||||||||||
| tag: | ||||||||||||
| description: 'NPM dist-tag (e.g., latest, beta, snapshot)' | ||||||||||||
| required: false | ||||||||||||
| default: 'next' | ||||||||||||
| pull_request: | ||||||||||||
| types: [labeled, synchronize] | ||||||||||||
| push: | ||||||||||||
| branches: | ||||||||||||
| - main | ||||||||||||
|
|
||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we be on the safer side here to prevent overlapping publish/version steps?
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate on this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aaah Got it |
||||||||||||
| concurrency: | ||||||||||||
| group: publish-${{ github.ref }} | ||||||||||||
| cancel-in-progress: false | ||||||||||||
|
|
||||||||||||
| jobs: | ||||||||||||
| check-changesets: | ||||||||||||
| runs-on: ubuntu-latest | ||||||||||||
| if: >- | ||||||||||||
| github.event_name == 'workflow_dispatch' || | ||||||||||||
| github.event_name == 'push' || | ||||||||||||
| (github.event_name == 'pull_request' && | ||||||||||||
| contains(github.event.pull_request.labels.*.name, 'snapshot-release')) | ||||||||||||
| outputs: | ||||||||||||
| has_changesets: ${{ steps.check.outputs.has_changesets }} | ||||||||||||
| has_1st_gen_changesets: ${{ steps.check.outputs.has_1st_gen_changesets }} | ||||||||||||
| steps: | ||||||||||||
| - name: Checkout repository | ||||||||||||
| uses: actions/checkout@v4 | ||||||||||||
|
|
||||||||||||
| - name: Check for changesets | ||||||||||||
| id: check | ||||||||||||
| run: | | ||||||||||||
| if [ -z "$(ls -A .changeset/*.md 2>/dev/null | grep -v README)" ]; then | ||||||||||||
| echo "has_changesets=false" >> $GITHUB_OUTPUT | ||||||||||||
| echo "has_1st_gen_changesets=false" >> $GITHUB_OUTPUT | ||||||||||||
| echo "No changesets found - skipping publish" | ||||||||||||
| else | ||||||||||||
| echo "has_changesets=true" >> $GITHUB_OUTPUT | ||||||||||||
| CHANGESET_COUNT=$(ls -1 .changeset/*.md 2>/dev/null | grep -v README | wc -l | tr -d ' ') | ||||||||||||
| echo "Found $CHANGESET_COUNT changesets" | ||||||||||||
|
|
||||||||||||
| # Check if any changeset mentions 1st-gen packages | ||||||||||||
| # 1st-gen packages are @spectrum-web-components/* except core | ||||||||||||
| HAS_1ST_GEN=false | ||||||||||||
| for file in .changeset/*.md; do | ||||||||||||
| if [ "$(basename "$file")" != "README.md" ]; then | ||||||||||||
| PACKAGES=$(grep -oP "@spectrum-web-components/[a-z-]+" "$file") | ||||||||||||
| NON_CORE=$(echo "$PACKAGES" | grep -v "^@spectrum-web-components/core$") | ||||||||||||
| if [ -n "$NON_CORE" ]; then | ||||||||||||
| HAS_1ST_GEN=true | ||||||||||||
| break | ||||||||||||
| fi | ||||||||||||
| fi | ||||||||||||
| done | ||||||||||||
|
|
||||||||||||
| echo "has_1st_gen_changesets=$HAS_1ST_GEN" >> $GITHUB_OUTPUT | ||||||||||||
| if [ "$HAS_1ST_GEN" = "true" ]; then | ||||||||||||
| echo "Found 1st-gen changesets - React wrappers will be built and published" | ||||||||||||
| else | ||||||||||||
| echo "No 1st-gen changesets found - React wrappers will be skipped" | ||||||||||||
| fi | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| publish: | ||||||||||||
| needs: check-changesets | ||||||||||||
| if: needs.check-changesets.outputs.has_changesets == 'true' | ||||||||||||
| runs-on: ubuntu-latest | ||||||||||||
| environment: npm-publish | ||||||||||||
| permissions: | ||||||||||||
| id-token: write # Required for OIDC trusted publishing (1st-gen ) | ||||||||||||
| contents: write # Required for git push | ||||||||||||
| env: | ||||||||||||
| YARN_ENABLE_IMMUTABLE_INSTALLS: false | ||||||||||||
| steps: | ||||||||||||
| - name: Checkout repository | ||||||||||||
| uses: actions/checkout@v4 | ||||||||||||
| with: | ||||||||||||
| fetch-depth: 0 | ||||||||||||
|
|
||||||||||||
| - name: Setup job and install dependencies | ||||||||||||
| uses: ./.github/actions/setup-job | ||||||||||||
|
|
||||||||||||
| - name: Verify npm CLI version for trusted publishing | ||||||||||||
| run: | | ||||||||||||
| echo "Current npm version: $(npm --version)" | ||||||||||||
| npx semver -r ">=11.5.1" "$(npm --version)" || { | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we ever update our Node requirements (which we must because Node 20 is going out of life) this can be dropped! |
||||||||||||
| echo "Upgrading npm for trusted publishing support (requires 11.5.1+)" | ||||||||||||
| npm install -g npm@latest | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we avoid installing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will remove once #6034 is merged |
||||||||||||
| echo "Upgraded to npm version: $(npm --version)" | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| - name: Set Git identity | ||||||||||||
| run: | | ||||||||||||
| git config --global user.email "support+actions@github.com" | ||||||||||||
| git config --global user.name "github-actions-bot" | ||||||||||||
|
|
||||||||||||
| - name: Determine release tag | ||||||||||||
| id: extract-tag | ||||||||||||
| env: | ||||||||||||
| EVENT_NAME: ${{ github.event_name }} | ||||||||||||
| INPUT_TAG: ${{ github.event.inputs.tag }} | ||||||||||||
| run: | | ||||||||||||
| if [ "$EVENT_NAME" == "pull_request" ]; then | ||||||||||||
| # PRs with the snapshot-release label always use snapshot-test | ||||||||||||
| WORKFLOW_TAG="snapshot-test" | ||||||||||||
| elif [ -n "$INPUT_TAG" ]; then | ||||||||||||
| # Use the tag provided via workflow_dispatch input | ||||||||||||
| WORKFLOW_TAG="$INPUT_TAG" | ||||||||||||
| else | ||||||||||||
| # Default tag for push-triggered runs | ||||||||||||
| WORKFLOW_TAG="next" | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| echo "tag=$WORKFLOW_TAG" >> $GITHUB_OUTPUT | ||||||||||||
| echo "Using npm tag: $WORKFLOW_TAG" | ||||||||||||
|
|
||||||||||||
| - name: Validate release tag | ||||||||||||
| env: | ||||||||||||
| TAG: ${{ steps.extract-tag.outputs.tag }} | ||||||||||||
| GIT_REF: ${{ github.ref }} | ||||||||||||
| run: | | ||||||||||||
| if [ "$TAG" == "latest" ] && [ "$GIT_REF" != "refs/heads/main" ]; then | ||||||||||||
| echo "ERROR: Cannot publish 'latest' from non-main branch" | ||||||||||||
| exit 1 | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| - name: Verify OIDC token and configure NPM authentication | ||||||||||||
| id: npm-auth | ||||||||||||
| env: | ||||||||||||
| NPM_TOKEN: ${{ secrets.ADOBE_BOT_NPM_TOKEN }} | ||||||||||||
| run: | | ||||||||||||
| if [ -n "$ACTIONS_ID_TOKEN_REQUEST_URL" ]; then | ||||||||||||
| echo "✓ OIDC token is available for 1st-gen trusted publishing" | ||||||||||||
| else | ||||||||||||
| echo "✗ OIDC token NOT available - trusted publishing will fail" | ||||||||||||
| exit 1 | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc | ||||||||||||
| echo "✓ NPM authentication configured for 2nd-gen (Adobe namespace)" | ||||||||||||
|
|
||||||||||||
| - name: Build all packages | ||||||||||||
| run: yarn build | ||||||||||||
|
|
||||||||||||
| - name: Generate custom elements manifests | ||||||||||||
| run: yarn workspace @spectrum-web-components/1st-gen custom-element-json | ||||||||||||
|
|
||||||||||||
| - name: Confirm build artifacts | ||||||||||||
| run: yarn workspace @spectrum-web-components/1st-gen build:confirm | ||||||||||||
|
|
||||||||||||
| - name: Version packages | ||||||||||||
| env: | ||||||||||||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||
| TAG: ${{ steps.extract-tag.outputs.tag }} | ||||||||||||
| run: | | ||||||||||||
| if [ "$TAG" == "latest" ]; then | ||||||||||||
| yarn workspace @spectrum-web-components/1st-gen changelog:global | ||||||||||||
| yarn changeset version | ||||||||||||
| else | ||||||||||||
| yarn changeset version --snapshot $TAG | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| - name: Capture released versions | ||||||||||||
| id: versions | ||||||||||||
| run: | | ||||||||||||
| CORE_VERSION=$(node -p "require('./2nd-gen/packages/core/package.json').version") | ||||||||||||
| BUNDLE_VERSION=$(node -p "require('./1st-gen/tools/bundle/package.json').version") | ||||||||||||
| SWC_VERSION=$(node -p "require('./2nd-gen/packages/swc/package.json').version") | ||||||||||||
| echo "core=$CORE_VERSION" >> $GITHUB_OUTPUT | ||||||||||||
| echo "bundle=$BUNDLE_VERSION" >> $GITHUB_OUTPUT | ||||||||||||
| echo "swc=$SWC_VERSION" >> $GITHUB_OUTPUT | ||||||||||||
|
|
||||||||||||
| - name: Refresh lockfile and rebuild | ||||||||||||
| run: | | ||||||||||||
| yarn install --refresh-lockfile | ||||||||||||
| yarn build | ||||||||||||
|
|
||||||||||||
| - name: Publish all packages | ||||||||||||
| if: steps.npm-auth.outcome == 'success' | ||||||||||||
| env: | ||||||||||||
| NODE_AUTH_TOKEN: ${{ secrets.ADOBE_BOT_NPM_TOKEN }} | ||||||||||||
| TAG: ${{ steps.extract-tag.outputs.tag }} | ||||||||||||
| run: | | ||||||||||||
| # Changeset publishes all packages (1st-gen, core, and 2nd-gen) | ||||||||||||
| # npm CLI automatically uses: | ||||||||||||
| # - OIDC trusted publishing for 1st-gen packages (configured on npmjs.com) | ||||||||||||
| # - Token authentication for 2nd-gen (from .npmrc) | ||||||||||||
| if [ "$TAG" == "latest" ]; then | ||||||||||||
| yarn changeset publish --no-git-tag | ||||||||||||
| else | ||||||||||||
| yarn changeset publish --no-git-tag --tag $TAG | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| - name: Build React wrappers | ||||||||||||
| if: needs.check-changesets.outputs.has_1st_gen_changesets == 'true' | ||||||||||||
| run: yarn workspace @spectrum-web-components/1st-gen build:react | ||||||||||||
|
|
||||||||||||
| - name: Publish React wrappers | ||||||||||||
| if: needs.check-changesets.outputs.has_1st_gen_changesets == 'true' | ||||||||||||
| env: | ||||||||||||
| TAG: ${{ steps.extract-tag.outputs.tag }} | ||||||||||||
| run: | | ||||||||||||
| if [ "$TAG" == "latest" ]; then | ||||||||||||
| PUBLISH_CMD="npm publish --access public" | ||||||||||||
| else | ||||||||||||
| PUBLISH_CMD="npm publish --tag $TAG --access public" | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| # Retry function with exponential backoff | ||||||||||||
| retry_publish() { | ||||||||||||
| local dir=$1 | ||||||||||||
| local max_attempts=3 | ||||||||||||
| local attempt=1 | ||||||||||||
|
|
||||||||||||
| while [ $attempt -le $max_attempts ]; do | ||||||||||||
| echo "Publishing $dir (attempt $attempt/$max_attempts)..." | ||||||||||||
| if (cd "$dir" && $PUBLISH_CMD); then | ||||||||||||
| echo "✓ Successfully published $dir" | ||||||||||||
| return 0 | ||||||||||||
| else | ||||||||||||
| if [ $attempt -lt $max_attempts ]; then | ||||||||||||
| local wait_time=$((2 ** attempt)) | ||||||||||||
| echo "✗ Publish failed, retrying in ${wait_time}s..." | ||||||||||||
| sleep $wait_time | ||||||||||||
| else | ||||||||||||
| echo "✗ Failed to publish $dir after $max_attempts attempts" | ||||||||||||
| return 1 | ||||||||||||
| fi | ||||||||||||
| fi | ||||||||||||
| attempt=$((attempt + 1)) | ||||||||||||
| done | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| cd 1st-gen/react | ||||||||||||
| for dir in */; do | ||||||||||||
| retry_publish "$dir" || exit 1 | ||||||||||||
| done | ||||||||||||
|
|
||||||||||||
| - name: Publish summary | ||||||||||||
| if: always() | ||||||||||||
| env: | ||||||||||||
| TAG: ${{ steps.extract-tag.outputs.tag }} | ||||||||||||
| EVENT_NAME: ${{ github.event_name }} | ||||||||||||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||||||||||||
| PR_TITLE: ${{ github.event.pull_request.title }} | ||||||||||||
| PR_AUTHOR: ${{ github.event.pull_request.user.login }} | ||||||||||||
| HEAD_REF: ${{ github.head_ref }} | ||||||||||||
| BASE_REF: ${{ github.base_ref }} | ||||||||||||
| REF_NAME: ${{ github.ref_name }} | ||||||||||||
| ACTOR: ${{ github.actor }} | ||||||||||||
| COMMIT_SHA: ${{ github.sha }} | ||||||||||||
| AUTH_OUTCOME: ${{ steps.npm-auth.outcome }} | ||||||||||||
| CORE_VERSION: ${{ steps.versions.outputs.core }} | ||||||||||||
| BUNDLE_VERSION: ${{ steps.versions.outputs.bundle }} | ||||||||||||
| SWC_VERSION: ${{ steps.versions.outputs.swc }} | ||||||||||||
| run: | | ||||||||||||
| echo "## Publish summary" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "" >> $GITHUB_STEP_SUMMARY | ||||||||||||
|
|
||||||||||||
| if [ "$EVENT_NAME" == "pull_request" ]; then | ||||||||||||
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Trigger** | Pull request |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **PR** | #${PR_NUMBER} — ${PR_TITLE} |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Branch** | \`${HEAD_REF}\` → \`${BASE_REF}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **NPM tag** | \`${TAG}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Author** | @${PR_AUTHOR} |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| elif [ "$EVENT_NAME" == "workflow_dispatch" ]; then | ||||||||||||
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Trigger** | Manual dispatch |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Branch** | \`${REF_NAME}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **NPM tag** | \`${TAG}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Actor** | @${ACTOR} |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| else | ||||||||||||
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Trigger** | Push |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Branch** | \`${REF_NAME}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **NPM tag** | \`${TAG}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| **Commit** | \`${COMMIT_SHA}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. core @spectrum-web-components/core version: 1.12.0-next.20260216160808
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| if [ -n "$CORE_VERSION" ] || [ -n "$BUNDLE_VERSION" ] || [ -n "$SWC_VERSION" ]; then | ||||||||||||
| echo "## Versions released" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "| Generation | Package | Version |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "|------------|---------|---------|" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| [ -n "$CORE_VERSION" ] && echo "| Core | \`@spectrum-web-components/core\` | \`${CORE_VERSION}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| [ -n "$BUNDLE_VERSION" ] && echo "| 1st gen | \`@spectrum-web-components/bundle\` | \`${BUNDLE_VERSION}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| [ -n "$SWC_VERSION" ] && echo "| 2nd gen | \`@adobe/spectrum-wc\` | \`${SWC_VERSION}\` |" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| echo "" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| if [ "$AUTH_OUTCOME" == "success" ]; then | ||||||||||||
| echo "✅ Publish completed with tag \`${TAG}\`" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| else | ||||||||||||
| echo "❌ Publish failed — NPM authentication did not succeed" >> $GITHUB_STEP_SUMMARY | ||||||||||||
| fi | ||||||||||||
|
|
||||||||||||
| - name: Commit and push changes | ||||||||||||
| if: steps.extract-tag.outputs.tag == 'latest' | ||||||||||||
| run: | | ||||||||||||
| git add . | ||||||||||||
| git commit -m "chore: release packages #publish" || echo "No changes to commit" | ||||||||||||
| git push | ||||||||||||
|
|
||||||||||||
| - name: Create git tag | ||||||||||||
| if: steps.extract-tag.outputs.tag == 'latest' | ||||||||||||
| run: node ./1st-gen/scripts/create-git-tag.js | ||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this file is a result of a bad merge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes