diff --git a/.github/scripts/publishPrerelease.sh b/.github/scripts/publishPrerelease.sh new file mode 100755 index 00000000000..cd3506f7536 --- /dev/null +++ b/.github/scripts/publishPrerelease.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +if [ "$BRANCH" = "dev" ]; then + if [ "$NEXT_RELEASE_ENABLED" != "true" ]; then + echo "Next release is disabled" + exit 0 + fi + + if ! npm run util:is-next-deployable; then + echo "No deployable changes in dev" + exit 0 + fi +fi + +npm install + +# version the packages with lerna before building to ensure the version in +# Calcite components' source code preamble is correct for deployment +if [ "$BRANCH" = "dev" ]; then + npm run version:next +elif [ "$BRANCH" = "main" ]; then + npm run version:hotfix +elif [ "$BRANCH" = "rc" ]; then + npm run version:rc +fi + +npm run build +npm test + +git config --global user.email "github-actions[bot]@users.noreply.github.com" +git config --global user.name "github-actions[bot]" + +# make sure the committed, autogenerated files are up to date before releasing. +# The "|| true" prevents failure if there are no changes. +git add packages/calcite-components/src/components.d.ts package-lock.json || true +git commit -m "build: update types and package-lock" || true + +# try deploying storybook, but still release next if it fails with "|| true" +if [ "$BRANCH" = "main" ]; then + { npm run --workspace=@esri/calcite-components build-storybook && + npx --workspace=@esri/calcite-components storybook-to-ghpages \ + --host-token-env-variable=GH_TOKEN_FOR_STORYBOOK \ + --existing-output-dir=docs --ci; } || true + + # remove the built docs after storybook deploys to gh-pages + git reset --hard +fi + +if [ "$BRANCH" = "main" ]; then + npm run publish:next +elif [ "$BRANCH" = "dev" ]; then + npm run publish:hotfix +elif [ "$BRANCH" = "rc" ]; then + npm run publish:rc +fi + +npm run util:push-tags diff --git a/.github/workflows/chromatic.yml b/.github/workflows/chromatic.yml index faa8e133107..c70501706c0 100644 --- a/.github/workflows/chromatic.yml +++ b/.github/workflows/chromatic.yml @@ -1,9 +1,9 @@ name: Chromatic on: push: - branches: [main, hotfix, rc] + branches: [main, rc, dev] pull_request: - branches: [main, hotfix, rc] + branches: [main, rc, dev] types: [labeled, synchronize] jobs: run: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d6e3a1f9915..4dc791609b2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [main, rc] + branches: [main, rc, dev] pull_request: # The branches below must be a subset of the branches above - branches: [main, rc] + branches: [main, rc, dev] schedule: - cron: "19 2 * * 4" diff --git a/.github/workflows/deploy-latest.yml b/.github/workflows/deploy-latest.yml index fe0666074ea..2b638c7d6f8 100644 --- a/.github/workflows/deploy-latest.yml +++ b/.github/workflows/deploy-latest.yml @@ -2,7 +2,7 @@ name: Deploy Latest on: workflow_dispatch: push: - branches: [main, hotfix] + branches: [main] permissions: contents: write pull-requests: write diff --git a/.github/workflows/deploy-next.yml b/.github/workflows/deploy-next.yml deleted file mode 100644 index 7213f6a42a9..00000000000 --- a/.github/workflows/deploy-next.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Build -concurrency: - group: deploy_next - cancel-in-progress: true -on: - workflow_dispatch: - push: - branches: [main] -jobs: - build: - runs-on: ubuntu-latest - permissions: - id-token: write - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ secrets.ADMIN_TOKEN }} - ref: main - - uses: actions/setup-node@v4 - with: - node-version-file: package.json - registry-url: "https://registry.npmjs.org" - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: storybook/next deployment - env: - NEXT_RELEASE_ENABLED: ${{ secrets.NEXT_RELEASE_ENABLED }} - # https://github.com/storybookjs/storybook-deployer/issues/77#issuecomment-618560481 - GH_TOKEN_FOR_STORYBOOK: ${{ github.actor }}:${{ secrets.ADMIN_TOKEN }} - NPM_CONFIG_PROVENANCE: true - run: | - if [ "$NEXT_RELEASE_ENABLED" == "true" ]; then - npm install - - if npm run util:is-next-deployable; then - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - - # version the packages with lerna before building to ensure - # the version in the CC source code preamble is correct for deployment - npm run version:next - npm run build - npm test - - # deploy storybook, but still release next if it fails - { npm run --workspace=@esri/calcite-components build-storybook && - npx --workspace=@esri/calcite-components storybook-to-ghpages \ - --host-token-env-variable=GH_TOKEN_FOR_STORYBOOK \ - --existing-output-dir=docs --ci; } || true - - # remove the built docs after storybook deploys to gh-pages - git reset --hard - npm run publish:next - npm run util:push-tags - fi - else - echo "Next release is disabled" - fi - - name: notify teams - uses: toko-bifrost/ms-teams-deploy-card@3.1.2 - if: always() - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - webhook-uri: ${{ secrets.TEAMS_WEBHOOK_URI_BUILD }} - show-on-start: false - card-layout-exit: complete - timezone: America/Los_Angeles diff --git a/.github/workflows/deploy-prerelease.yml b/.github/workflows/deploy-prerelease.yml new file mode 100644 index 00000000000..e582df17159 --- /dev/null +++ b/.github/workflows/deploy-prerelease.yml @@ -0,0 +1,45 @@ +name: Deploy Prerelease +concurrency: + group: deploy_prerelease + cancel-in-progress: true +on: + # `next` versions are automatically released when deployabled commits are pushed to dev + push: + branches: [dev] + # `hotfix` and `rc` versions must be manually released: + # https://docs.github.com/en/actions/using-workflows/manually-running-a-workflow + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + permissions: + id-token: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.ADMIN_TOKEN }} + ref: ${{ github.base_ref || github.ref_name }} + - uses: actions/setup-node@v4 + with: + node-version-file: package.json + registry-url: "https://registry.npmjs.org" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Deploy prerelease and storybook + env: + NEXT_RELEASE_ENABLED: ${{ secrets.NEXT_RELEASE_ENABLED }} + # https://github.com/storybookjs/storybook-deployer/issues/77#issuecomment-618560481 + GH_TOKEN_FOR_STORYBOOK: ${{ github.actor }}:${{ secrets.ADMIN_TOKEN }} + NPM_CONFIG_PROVENANCE: true + BRANCH: ${{ github.base_ref || github.ref_name }} + run: ../scripts/publishPrerelease.sh + - name: notify teams + uses: toko-bifrost/ms-teams-deploy-card@3.1.2 + if: ${{ !cancelled() && github.event_name == 'push' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + webhook-uri: ${{ secrets.TEAMS_WEBHOOK_URI_BUILD }} + show-on-start: false + card-layout-exit: complete + timezone: America/Los_Angeles diff --git a/.github/workflows/pr-bot.yml b/.github/workflows/pr-bot.yml index 44f06760a26..15dc19f9b41 100644 --- a/.github/workflows/pr-bot.yml +++ b/.github/workflows/pr-bot.yml @@ -1,7 +1,7 @@ name: PR Bot on: pull_request: - branches: [main, rc, hotfix] + branches: [main, rc, dev] permissions: pull-requests: write issues: write diff --git a/.github/workflows/pr-e2e.yml b/.github/workflows/pr-e2e.yml index cbe5e9c6c31..17595a5df79 100644 --- a/.github/workflows/pr-e2e.yml +++ b/.github/workflows/pr-e2e.yml @@ -2,7 +2,7 @@ name: E2E on: workflow_dispatch: pull_request: - branches: [main, rc, hotfix] + branches: [main, rc, dev] jobs: e2e: runs-on: ubuntu-20.04 diff --git a/.github/workflows/pr-milestone.yml b/.github/workflows/pr-milestone.yml index 759dd7ea4c7..fba245a2a2e 100644 --- a/.github/workflows/pr-milestone.yml +++ b/.github/workflows/pr-milestone.yml @@ -1,7 +1,7 @@ name: PR Merged on: pull_request: - branches: [main, rc] + branches: [main, rc, dev] types: [closed] jobs: milestone: diff --git a/.github/workflows/remove-prerelease-changelog-entries.yml b/.github/workflows/remove-prerelease-changelog-entries.yml index 20308a1729d..ee89116fdbb 100644 --- a/.github/workflows/remove-prerelease-changelog-entries.yml +++ b/.github/workflows/remove-prerelease-changelog-entries.yml @@ -2,7 +2,6 @@ on: push: branches: - release-please--branches--main - - release-please--branches--hotfix permissions: contents: write pull-requests: write diff --git a/documentation/monorepo.md b/documentation/monorepo.md index 0f4a876cd0b..8e0754a31b2 100644 --- a/documentation/monorepo.md +++ b/documentation/monorepo.md @@ -166,4 +166,4 @@ A `remove-prerelease-changelog-entries.yml` GitHub Action runs the `removePrerel ### Steps to release -For the most part the releases are automated in the CI (see the sections above). However, there are a few manual steps, which are described in the [releasing documentation](/Releasing.md). +For the most part the releases are automated in the CI (see the sections above). However, there are a few manual steps, which are described in the [releasing documentation](./releasing.md). diff --git a/documentation/releasing.md b/documentation/releasing.md index 700bb803f6a..6c6b135e51c 100644 --- a/documentation/releasing.md +++ b/documentation/releasing.md @@ -12,48 +12,60 @@ When releasing during normal work hours, you should block people from merging PR 1. Let the team know via Teams in the `Core - Releases` 🔒 channel (@ the channel for visibility) 1. Go to the repo settings -> "Branches" -1. Under "Branch protection rules" edit the entry for `main` +1. Under "Branch protection rules" edit the entry for `dev` 1. Under "Require approvals" change the number from 1 to 6 and save the changes. ![image](https://user-images.githubusercontent.com/10986395/167955616-c796d1ff-5c1a-4332-a6d5-5288f9d20992.png) ### Release steps -The `latest` release process is mostly automated, but a few manual steps are required: +Follow these steps to release a major, minor, or patch version: 1. Follow the steps above to [prevent merging pull requests](#prevent-merging-pull-requests). -2. Make sure all of the workflows for the [most recent commit on `main`](https://github.com/Esri/calcite-design-system/commits/main) are completed. - 1. If time is short, you can cancel the `Build` workflow, which releases `next` and deploys storybook. We just want to make sure it doesn't deploy the `next` version after `latest` is released. If the most recent commit is a next release (titled `chore: release next`) then you can definitely cancel the `Build` workflow since it will be intentionally cancelled by the CI anyway. -3. Review the PR created by `release-please` (titled `chore: release main`) to make sure the changelog(s) and package versioning looks correct. - 1. There should be a commit on the PR's branch named `docs: remove prerelease changelog entries` that occurred **after** the most recent commit on `main`. -4. Add the `skip visual snapshots` label. -5. Make sure the rest of the PR checks are passing. -6. Approve and install the PR once all checks are passing. You will need to use Admin privilege to override the 6 approval rule [added above](#prevent-merging-pull-requests). -7. Wait for the release's [Deploy Latest](https://github.com/Esri/calcite-design-system/actions/workflows/deploy-latest.yml) action to finish. -8. Ensure the released package(s) were deployed to NPM and that [GitHub Releases were created](https://github.com/Esri/calcite-design-system/releases). +1. [Create a new branch](https://github.com/Esri/calcite-design-system/branches) off of `dev`. +1. Create a pull request from the new branch with `main` as the target. +1. Once the pull request is ready to install, enable "Allow rebase merging" under the Pull Requests section of the [repo settings](https://github.com/Esri/calcite-design-system/settings). + ![image](https://github.com/Esri/calcite-design-system/assets/10986395/9fa8be42-7923-47f9-b2d8-df65416e88cc) +1. In the pull request created in step 3, switch the merge method to "Rebase and merge" and install. + ![image](https://github.com/Esri/calcite-design-system/assets/10986395/fcbfa86d-950f-459f-8ecd-e468d4373415) +1. Disable the "Allow rebase merging" option from step 4. +1. Wait for the [Deploy Latest](https://github.com/Esri/calcite-design-system/actions/workflows/deploy-latest.yml) workflow run on `main` to complete. +1. Review the PR created by `release-please` (titled `chore: release main`) to make sure the changelog(s) and package versioning looks correct. + - There should be a commit on the PR's branch named `docs: remove prerelease changelog entries` that occurred **after** the most recent commit on `main`. +1. Make sure the rest of the PR checks are passing. +1. Approve and install the PR once all checks are passing. You will need to use Admin privilege to override the 6 approval rule. +1. Wait for the release's [Deploy Latest](https://github.com/Esri/calcite-design-system/actions/workflows/deploy-latest.yml) workflow run to finish. +1. Ensure the released package(s) were deployed to NPM and that [GitHub Releases were created](https://github.com/Esri/calcite-design-system/releases). - You can check the NPM version(s) on the website (e.g., [calcite-components](https://www.npmjs.com/package/@esri/calcite-components?activeTab=versions)) or with the CLI: - ```sh - npm view @esri/calcite-components version - ``` + ```sh + npm view @esri/calcite-components version + ``` + +1. See the [troubleshooting](#troubleshooting) section if something went wrong, or reach out to Ben or Franco for help. +1. Create a new branch off of `dev` and cherry-pick the release commit from `main` (the version bumps and changelog sections). + + ```sh + git checkout dev && git pull && git checkout -b cherry-pick-release && git cherry-pick main && git push -u HEAD + ``` -9. See the [troubleshooting](#troubleshooting) section if something went wrong, or reach out to Ben or Franco for help. -10. Change the `main` branch's required approvals back to 1 and save the changes (see the [Prevent merging PRs](#prevent-merging-pull-requests) section) -11. Let the team know via Teams merging is now unblocked in the initial `Core - Releases` message from earlier. +1. Create a pull request from the new branch to `dev`, and install it by squash merging. +1. Change the `dev` branch's required approvals back to 1 and save the changes (see the [Prevent merging PRs](#prevent-merging-pull-requests) section) +1. Let the team know via Teams merging is now unblocked in the initial `Core - Releases` message from earlier. ### Troubleshooting The following are some troubleshooting steps you can take if a release is unsuccessful. 1. Find the workflow run for the release [here](https://github.com/Esri/calcite-design-system/actions/workflows/deploy-latest.yml), and view the logs to find the error message. -2. Fix the error. In some cases you can resolve the issue with a temporary solution, and then fix the CI after the release is completed. For example, if the `components.d.ts` file is outdated and breaks releases due to an unclean working tree, the [temporary solution](https://github.com/Esri/calcite-design-system/pull/9008) would be to build locally and submit a PR with the updated file. That way you won't be so time crunched when determining an [actual fix](https://github.com/Esri/calcite-design-system/pull/9011) to prevent the same error from occurring in the future. Reach out to Ben or Franco if a solution to the error isn't clear. -3. Once the PR with the fix is installed, make sure the new workflow run is passing. -4. **IMPORTANT:** If the new release is showing up in the [GitHub releases](https://github.com/Esri/calcite-design-system/releases) but not on NPM, you'll need to release locally. This signifies the error involved publishing to NPM, which happens after the releases and tags are created on GitHub. To release locally, run the following commands: +1. Fix the error. In some cases you can resolve the issue with a temporary solution, and then fix the CI after the release is completed. For example, if the `components.d.ts` file is outdated and breaks releases due to an unclean working tree, the [temporary solution](https://github.com/Esri/calcite-design-system/pull/9008) would be to build locally and submit a PR with the updated file. That way you won't be so time crunched when determining an [actual fix](https://github.com/Esri/calcite-design-system/pull/9011) to prevent the same error from occurring in the future. Reach out to Ben or Franco if a solution to the error isn't clear. +1. Once the PR with the fix is installed, make sure the new workflow run is passing. +1. **IMPORTANT:** If the new release is showing up in the [GitHub releases](https://github.com/Esri/calcite-design-system/releases) but not on NPM, you'll need to release locally. This signifies the error involved publishing to NPM, which happens after the releases and tags are created on GitHub. To release locally, run the following commands: - ```sh - npm install && npm run build && npm test && npm run publish:latest - ``` +```sh +npm install && npm run build && npm test && npm run publish:latest +``` ### Bumping the examples @@ -61,16 +73,16 @@ A [GitHub Action](https://github.com/Esri/calcite-components-examples/blob/maste ## next releases -`next` releases are useful for testing incoming changes between releases. They are [released by the CI](/Monorepo.md#ci-for-next-releases) after 'deployable' commits are installed to `main`. A deployable commit is: +`next` releases are useful for testing incoming changes between releases. They are [released by the CI](./monorepo.md#ci-for-next-releases) after 'deployable' commits are installed to `dev`. A deployable commit is: 1. a commit of type `feat` or `fix` -2. a commit that introduces a breaking change +1. a commit that introduces a breaking change If you need to disable `next` releases, you can do so by setting the `NEXT_RELEASE_ENABLED` GitHub Secret to anything but `true`. If you need to manually release `next`, you can run the following commands from the monorepo's root directory: ```sh # make sure you don't have any unsaved work -git checkout main +git checkout dev npm run clean npm install npm test @@ -88,8 +100,10 @@ git add packages/*/CHANGELOG.md git commit amend --no-edit git tag -d "@esri/calcite-components@1.2.3" git tag -d "@esri/calcite-components-react@1.2.3" +git tag -d "@esri/calcite-components-angular@1.2.3" git tag -a "@esri/calcite-components@1.2.3" -m "@esri/calcite-components@1.2.3" HEAD git tag -a "@esri/calcite-components-react@1.2.3" -m "@esri/calcite-components-react@1.2.3" HEAD +git tag -a "@esri/calcite-components-angular@1.2.3" -m "@esri/calcite-components-angular@1.2.3" HEAD # now you can publish and push tags ``` diff --git a/lerna.json b/lerna.json index 6df7a3f8da8..f4e92ab1a44 100644 --- a/lerna.json +++ b/lerna.json @@ -5,7 +5,7 @@ "command": { "version": { "conventionalCommits": true, - "allowBranch": ["main", "rc", "hotfix"] + "allowBranch": ["main", "rc", "dev"] } } } diff --git a/package.json b/package.json index 45164384239..229f1e92f3c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "start": "turbo run start --log-order=stream", "test": "turbo run test --log-order=stream", "util:is-next-deployable": "tsx support/isNextDeployable.ts", - "util:push-tags": "git push origin main --follow-tags", + "util:push-tags": "git push origin HEAD --follow-tags", "util:upload-release-assets": "tsx support/uploadReleaseAssets.ts", "util:remove-prerelease-changelog-entries": "tsx support/removePrereleaseChangelogEntries.ts", "util:sync-linked-package-versions": "tsx support/syncLinkedPackageVersions.ts" diff --git a/support/isNextDeployable.ts b/support/isNextDeployable.ts index 293342b18b7..22705014b74 100644 --- a/support/isNextDeployable.ts +++ b/support/isNextDeployable.ts @@ -16,12 +16,12 @@ throw new Error("No deployable changes since the previous release, skipping ⛔"); } - await runGit("checkout", "main", "--quiet"); + await runGit("checkout", "dev", "--quiet"); await runGit("fetch", "--tags", "--quiet"); if ( - (await latestCommit("main")) != (await latestCommit("origin/main")) && - (await deployable("main", "origin/main")) + (await latestCommit("dev")) != (await latestCommit("origin/dev")) && + (await deployable("dev", "origin/dev")) ) { throw new Error("There is a more recent deployable install, aborting ⛔️"); } diff --git a/support/release.sh b/support/release.sh index 1ef3efb7889..a226fc2a0ba 100755 --- a/support/release.sh +++ b/support/release.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -# This script is used to version and publish releases and pre-releases. +# This script is used to version and publish releases and pre-releases. # # @arg1 The deployment step to run, must be either "version" or "publish". # @arg2 [optional] The pre-release tag, e.g., "next", "hotfix", or "rc". @@ -9,7 +9,7 @@ set -e help() { [ -n "$1" ] && printf "%s\n" "$@" - echo "Usage: ./release.sh []" + echo "Usage: ./release.sh (version | publish) []" exit 1 } @@ -39,7 +39,7 @@ sanity_checks() { version() { sanity_checks - if [ -z "$dist_tag" ]; then + if [ -z "$dist_tag" ] || [ "$dist_tag" = "latest" ]; then lerna version --no-push --no-git-tag-version --yes \ --conventional-commits \ --create-release github @@ -62,10 +62,14 @@ main() { cmd="$1" dist_tag="$2" - if [ -z "$dist_tag" ] || [ "$dist_tag" = "next" ]; then + if [ -z "$dist_tag" ] || [ "$dist_tag" = "latest" ]; then branch="main" + elif [ "$dist_tag" = "next" ]; then + branch="dev" + elif [ "$dist_tag" = "rc" ]; then + branch="rc" else - branch="$dist_tag" + help "invalid dist tag: '$dist_tag'" fi if [ -z "$cmd" ]; then @@ -76,7 +80,6 @@ main() { publish else help "invalid command: '$cmd'" - exit 1 fi }