diff --git a/.changeset/config.json b/.changeset/config.json index 3b92b4a6..90f308c6 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,10 +1,13 @@ { "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", - "changelog": "@changesets/cli/changelog", + "changelog": [ + "@changesets/changelog-github", + { "repo": "TBD54566975/tbdex-js" } + ], "commit": false, "fixed": [["@tbdex/protocol", "@tbdex/http-client", "@tbdex/http-server"]], "linked": [], - "access": "restricted", + "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [] diff --git a/.github/workflows/changeset-version.yml b/.github/workflows/changeset-version.yml deleted file mode 100644 index 7690d28c..00000000 --- a/.github/workflows/changeset-version.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Changeset Version - -on: - push: - branches: - - main - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -jobs: - version: - name: Changeset Version - runs-on: ubuntu-latest - steps: - - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - - name: install pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Set up Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - with: - node-version: 20 - registry-url: https://registry.npmjs.org/ - - - name: Install dependencies - run: pnpm install - - - name: Create Release Pull Request - uses: changesets/action@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/create-gh-release.yml b/.github/workflows/create-gh-release.yml deleted file mode 100644 index 2ef54e3a..00000000 --- a/.github/workflows/create-gh-release.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Create GH Release - -on: - pull_request: - types: - - closed - branches: - - main - workflow_dispatch: - -# Allow only one concurrent deployment,but do NOT cancel in-progress runs as -# we want to allow these release deployments to complete. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -jobs: - create-release: - # a gh release will be created in the following conditions: - # 1. if it is a manual trigger (workflow_dispatch) - # 2. if the workflow was triggered by a merged changeset PR - if: | - (github.event_name == 'workflow_dispatch' || - (github.event.pull_request.merged == true && - (github.event.pull_request.head.ref == 'changeset-release/main' || - contains(github.event.pull_request.labels.*.name, 'automated-release')))) - name: Create GH Release - runs-on: ubuntu-latest - - steps: - - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - submodules: 'true' - - - name: Set up Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - with: - node-version: 20 - registry-url: https://registry.npmjs.org/ - - - name: Check if GitHub repo package version is latest - run: | - # get any package version from the repo - cd packages/protocol # assumption that all packages have the same version - - # Fetch the version in the GitHub repo's package.json file. - REPO_VERSION=$(node -p "require('./package.json').version") - echo "REPO_VERSION=$REPO_VERSION" >> $GITHUB_ENV - echo "Repo Version: $REPO_VERSION" - shell: bash - - - name: Create GitHub Release - uses: softprops/action-gh-release@v1 - with: - name: v${{ env.REPO_VERSION }} - tag_name: v${{ env.REPO_VERSION }} - draft: false - prerelease: false - generate_release_notes: true diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index 6edec5b6..5574c8dc 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -2,11 +2,10 @@ name: Publish Docs to GH Pages on: - workflow_run: - workflows: ["Create GH Release"] - types: - - completed + # Manual trigger workflow_dispatch: + # Call from the release workflow + workflow_call: # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. @@ -25,7 +24,7 @@ jobs: - name: Checkout source uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - submodules: 'true' + submodules: "true" - name: install pnpm uses: pnpm/action-setup@v2 diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml deleted file mode 100644 index f08be215..00000000 --- a/.github/workflows/npm-publish.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Publish Packages to NPM - -on: - workflow_run: - workflows: ["Create GH Release"] - types: - - completed - workflow_dispatch: - -# Allow only one concurrent deployment,but do NOT cancel in-progress runs as -# we want to allow these release deployments to complete. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -permissions: - contents: read - id-token: write # necessary for NPM provenance - -jobs: - publish-npm: - name: NPM Publish - runs-on: ubuntu-latest - # only runs if workflow_run is completed successfully or manually workflow dispatch - if: github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' - - strategy: - max-parallel: 1 - matrix: - package: ["protocol", "http-client", "http-server"] - - steps: - - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - submodules: 'true' - - - name: install pnpm - uses: pnpm/action-setup@v2 - with: - version: 8 - - - name: Set up Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - with: - node-version: 20 - registry-url: https://registry.npmjs.org/ - - # Note - this is not required but it gives a clean failure prior to attempting a release if the GH workflow runner is not authenticated with NPMjs.com - - name: Verify NPM token is authenticated with NPMjs.com - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} - run: pnpm whoami - - - name: Install dependencies - run: pnpm install - - - name: Build packages - run: pnpm build - - - name: Check if GitHub repo package version is latest - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} - run: | - cd packages/${{ matrix.package }} - - # Fetch the published version on NPMjs.com. - PUBLISHED_VERSION=$(pnpm view @tbdex/${{ matrix.package }} version 2>/dev/null || echo "0.0.0") - echo "Published Version: $PUBLISHED_VERSION" - - # Fetch the version in the GitHub repo's package.json file. - REPO_VERSION=$(node -p "require('./package.json').version") - echo "REPO_VERSION=$REPO_VERSION" >> $GITHUB_ENV - echo "Repo Version: $REPO_VERSION" - - # Compare the repo and NPMjs.com package versions. - IS_GREATER=$(pnpm semver --range ">$PUBLISHED_VERSION" $REPO_VERSION || true) - if [ -n "$IS_GREATER" ] ; then - echo "@tbdex/${{ matrix.package }}@$REPO_VERSION is latest" - echo "IS_LATEST=true" >> $GITHUB_ENV - else - echo "@tbdex/${{ matrix.package }}@$REPO_VERSION is already published or repo version is lower" - echo "IS_LATEST=false" >> $GITHUB_ENV - fi - shell: bash - - - name: Publish @tbdex/${{ matrix.package }}@${{ env.REPO_VERSION }} - if: env.IS_LATEST == 'true' - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} - NPM_CONFIG_PROVENANCE: true - run: | - cd packages/${{ matrix.package }} - pnpm publish --access public - shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..61578744 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,83 @@ +name: Release + +on: + push: + branches: + - main + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + # prevents this action from running on forks + if: github.repository == 'TBD54566975/tbdex-js' + permissions: + contents: write # to create release (changesets/action) + pull-requests: write # to create pull request (changesets/action) + id-token: write # necessary for NPM provenance + + name: Release + runs-on: ubuntu-latest + + outputs: + published: ${{ steps.changesets.outputs.published }} + + steps: + - name: Checkout source + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: "true" + + - name: install pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + + - name: Set up Node.js + uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + with: + node-version: 20 + registry-url: https://registry.npmjs.org/ + + - name: Verify NPM token is authenticated with NPMjs.com + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: pnpm whoami + + - name: Install dependencies + run: pnpm install + + - name: Build all workspace packages + run: pnpm build + + - name: Create Release Pull Request or Publish to npm + uses: changesets/action@v1 + id: changesets + with: + publish: pnpm changeset publish + version: pnpm changeset version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish `next` preview + if: steps.changesets.outputs.published != 'true' && steps.changesets.outputs.pullRequestNumber != '' && steps.changesets.outputs.hasChangesets == 'true' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + git checkout main + SHORT_SHA=$(git rev-parse --short HEAD) + pnpm changeset version --snapshot next-$SHORT_SHA + pnpm changeset publish --no-git-tag --tag next + + publish-docs: + needs: release + name: Publish Docs + if: ${{ needs.release.outputs.published == 'true' }} + uses: ./.github/workflows/docs-publish.yml diff --git a/README.md b/README.md index 2d6c8735..da789def 100644 --- a/README.md +++ b/README.md @@ -89,17 +89,17 @@ Prior to merging your branch into main, and given you have relevant semantic ver **You can stop here!** It is recommended to merge your branch into main with the `.changeset/*.md` files, at which point, the Changeset GitHub Action will automatically pick up those changes and open a PR to automate the `pnpm changeset version` execution. For example, [see this PR](https://github.com/TBD54566975/tbdex-js/pull/36). This command will do two things: update the version numbers in the relevant `package.json` files & also aggregate Summary notes into the relevant `CHANGELOG.md` files. In keeping with the staged commit analogy, this is akin to the actual commit. -## Cutting Releases +## Publishing Releases -When a changeset PR is merged to main we will automatically create a GitHub release using the workflow [Create GH Release](./.github/workflows/create-gh-release.yml). +Just merge the [Version Packages PR](https://github.com/TBD54566975/tbdex-js/pulls?q=is%3Apr+author%3Aapp%2Fgithub-actions+%22Version+Packages%22+) when you are ready to publish the new versions! + +When these PRs are merged to main we will automatically publish to NPM and create corresponding git tags with the changelog notes, and mirror each tag to a GitHub release per package. > [!NOTE] > -> This is done by detecting the merged PR branch name: `changeset-release/main`. - -Also, by creating the GH release, the packages will be automatically published to npm. So this way the engineer can simply just merge the changeset PR and the new GH Release and packages version will be automagically published to npm! +> This is all achieved by the Changesets GitHub action being used in the [Release Workflow](./.github/workflows/release.yml). -## Steps for a new release publish +## Recapping the steps for a new release publish Recap of the above changesets, plus the release process: @@ -107,9 +107,9 @@ Recap of the above changesets, plus the release process: 2. `changeset-bot` will automatically [comment on the PR](https://github.com/TBD54566975/tbdex-js/pull/30#issuecomment-1732721942) with a reminder & recommendations for semver 3. Run `pnpm changeset` locally and push changes (`.changet/*.md`) 4. Merge PR into `main` -5. Profit from the release automation: - - [Create GH Release Workflow](./.github/workflows/create-gh-release.yml) will automatically create a new [GitHub Release](https://github.com/TBD54566975/tbdex-js/releases) - - [NPM Publish Workflow](./.github/workflows/npm-publish.yml) will automatically publish a [new version to NPM](https://www.npmjs.com/package/@tbdex/protocol?activeTab=versions) +5. Profit from the automated release pipeline: + - [Release Workflow](./.github/workflows/release.yml) will create a new Version Package PR, or update the existing one + - When maintainers are ready to publish the new changes, they will merge that PR and the very same [Release Workflow](./.github/workflows/release.yml) will automatically publish a [new version to NPM](https://www.npmjs.com/package/@tbdex/protocol?activeTab=versions), and publish the docs to https://tbd54566975.github.io/tbdex-js/ ## Working with the `tbdex` submodule diff --git a/package.json b/package.json index eaf20664..af313de8 100644 --- a/package.json +++ b/package.json @@ -16,12 +16,12 @@ }, "license": "Apache-2.0", "devDependencies": { + "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.26.2", "@npmcli/package-json": "5.0.0", "@types/chai": "4.3.5", "@types/eslint": "8.44.2", "@types/mocha": "10.0.1", - "typescript": "5.2.2", "@typescript-eslint/eslint-plugin": "6.7.0", "@typescript-eslint/parser": "6.7.0", "c8": "^9.1.0", @@ -29,7 +29,8 @@ "mocha": "10.2.0", "mocha-junit-reporter": "2.2.1", "npkill": "0.11.3", - "semver": "7.5.4" + "semver": "7.5.4", + "typescript": "5.2.2" }, "pnpm": { "overrides": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4ec15fe..527ca193 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: .: devDependencies: + '@changesets/changelog-github': + specifier: ^0.5.0 + version: 0.5.0 '@changesets/cli': specifier: ^2.26.2 version: 2.26.2 @@ -372,6 +375,16 @@ packages: '@changesets/types': 5.2.1 dev: true + /@changesets/changelog-github@0.5.0: + resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} + dependencies: + '@changesets/get-github-info': 0.6.0 + '@changesets/types': 6.0.0 + dotenv: 8.6.0 + transitivePeerDependencies: + - encoding + dev: true + /@changesets/cli@2.26.2: resolution: {integrity: sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==} hasBin: true @@ -439,6 +452,15 @@ packages: semver: 7.5.4 dev: true + /@changesets/get-github-info@0.6.0: + resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} + dependencies: + dataloader: 1.4.0 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + /@changesets/get-release-plan@3.0.17: resolution: {integrity: sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==} dependencies: @@ -511,6 +533,10 @@ packages: resolution: {integrity: sha512-myLfHbVOqaq9UtUKqR/nZA/OY7xFjQMdfgfqeZIBK4d0hA6pgxArvdv8M+6NUzzBsjWLOtvApv8YHr4qM+Kpfg==} dev: true + /@changesets/types@6.0.0: + resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} + dev: true + /@changesets/write@0.2.3: resolution: {integrity: sha512-Dbamr7AIMvslKnNYsLFafaVORx4H0pvCA2MHqgtNCySMe1blImEyAEOzDmcgKAkgz4+uwoLz7demIrX+JBr/Xw==} dependencies: @@ -2917,6 +2943,10 @@ packages: engines: {node: '>= 14'} dev: true + /dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + dev: true + /debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} dev: true @@ -3120,6 +3150,11 @@ packages: engines: {node: '>=10'} dev: true + /dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + dev: true + /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true