diff --git a/.github/actions/create-release-and-publish/action.yml b/.github/actions/create-release-and-publish/action.yml new file mode 100644 index 0000000..db1283b --- /dev/null +++ b/.github/actions/create-release-and-publish/action.yml @@ -0,0 +1,80 @@ +name: create-release-and-publish +description: Create GitHub Release and publish somewhere +inputs: + github-token: + description: 'GitHub Access Token for generating changelog' + default: ${{ github.token }} + required: true + run-publish: + description: 'Script for publishing' + required: true + get-version: + description: 'Script for extracting current version' + default: | + node --print 'require("./package.json").version' + required: true +runs: + using: "composite" + steps: + - uses: ./.github/actions/release-meta + id: release-meta + with: + get-version: ${{ inputs.get-version }} + + - name: Setup git + shell: bash + run: | + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git remote set-url origin https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY} + env: + GITHUB_TOKEN: ${{ inputs.github-token }} + + - name: Update CHANGELOG.md + shell: bash + run: | + mkdir -p tmp + echo "${RELEASE_NOTE}" > tmp/CHANGELOG.head.md + git show ${{ github.base_ref }}:./CHANGELOG.md > tmp/CHANGELOG.base.md + cat -s tmp/CHANGELOG.head.md tmp/CHANGELOG.base.md > CHANGELOG.md + git add CHANGELOG.md + git commit -m "Update CHANGELOG for ${RELEASE_TAG}" + git push + env: + RELEASE_TAG: ${{ steps.release-meta.outputs.tag }} + RELEASE_NOTE: ${{ steps.release-meta.outputs.note }} + + - name: Create GitHub Release + uses: actions/github-script@v4 + with: + script: | + github.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + name: process.env.RELEASE_TAG, + tag_name: process.env.RELEASE_TAG, + body: process.env.RELEASE_NOTE, + prerelease: !/v\d+\.\d+\.\d+$/.test(process.env.RELEASE_TAG), + target_commitish: context.sha, + }) + env: + RELEASE_NOTE: ${{ steps.release-meta.outputs.note }} + RELEASE_TAG: ${{ steps.release-meta.outputs.tag }} + + - name: Publish to npm + shell: bash + run: ${{ inputs.run-publish }} + + - name: Comment to PR + uses: actions/github-script@v4 + with: + script: | + const url = `https://github.com/${context.repo.owner}/${context.repo.repo}/releases/tag/${process.env.RELEASE_TAG}` + github.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: `[${process.env.RELEASE_TAG}](${url}) is released 🚀`, + }) + env: + RELEASE_TAG: ${{ steps.release-meta.outputs.tag }} diff --git a/.github/actions/generate-changelog/action.yml b/.github/actions/generate-changelog/action.yml new file mode 100644 index 0000000..889d49e --- /dev/null +++ b/.github/actions/generate-changelog/action.yml @@ -0,0 +1,30 @@ +name: generate-changelog +description: Generate and commit the CHANGELOG, and update the body of the Pull Request. +inputs: + get-version: + description: 'Script for extracting current version' + default: | + node --print 'require("./package.json").version' + required: true +runs: + using: "composite" + steps: + - uses: ./.github/actions/release-meta + id: release-meta + with: + get-version: ${{ inputs.get-version }} + + - name: Update PR body + uses: actions/github-script@v4 + with: + script: | + github.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + title: `Release ${process.env.RELEASE_TAG}`, + body: process.env.RELEASE_NOTE, + }) + env: + RELEASE_NOTE: ${{ steps.release-meta.outputs.note }} + RELEASE_TAG: ${{ steps.release-meta.outputs.tag }} diff --git a/.github/actions/release-meta/action.yml b/.github/actions/release-meta/action.yml new file mode 100644 index 0000000..d47475e --- /dev/null +++ b/.github/actions/release-meta/action.yml @@ -0,0 +1,40 @@ +name: release-meta +description: Output release metadata +inputs: + github-token: + description: 'GitHub Access Token for generating changelog' + default: ${{ github.token }} + required: true + get-version: + description: 'Script for extracting current version' + default: | + node --print 'require("./package.json").version' + required: true +outputs: + version: + description: 'Release version' + value: ${{ steps.meta.outputs.version }} + tag: + description: 'Release git tag' + value: ${{ steps.meta.outputs.tag }} + note: + description: 'Release note' + value: ${{ steps.meta.outputs.note }} +runs: + using: "composite" + steps: + - id: meta + shell: bash + run: | + version=$(${{ inputs.get-version }}) + note=$(npx --quiet lerna-changelog --next-version ${version}) + + echo "::set-output name=version::${version}" + echo "::set-output name=tag::v${version}" + + note="${note//'%'/'%25'}" + note="${note//$'\n'/'%0A'}" + note="${note//$'\r'/'%0D'}" + echo "::set-output name=note::${note}" + env: + GITHUB_AUTH: ${{ inputs.github-token }} diff --git a/.github/workflows/check-pr-labels.yml b/.github/workflows/check-pr-labels.yml new file mode 100644 index 0000000..d265c5f --- /dev/null +++ b/.github/workflows/check-pr-labels.yml @@ -0,0 +1,20 @@ +name: Check PR Labels + +on: + pull_request_target: + types: [opened, labeled, unlabeled, synchronize] + +permissions: + pull-requests: write + +jobs: + check-labels: + if: ${{ !startswith(github.head_ref, 'releases/') }} + runs-on: ubuntu-latest + steps: + - uses: jesusvasquez333/verify-pr-label-action@v1.4.0 + with: + github-token: '${{ secrets.GITHUB_TOKEN }}' + valid-labels: 'bug, enhancement, internal, documentation' + pull-request-number: '${{ github.event.pull_request.number }}' + disable-reviews: true # use status diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..e4d5275 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,38 @@ +name: Publish + +on: + pull_request: + branches: + - main + types: [closed] + +permissions: + contents: write + pull-requests: write + packages: write + +jobs: + publish: + if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'releases/') + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v1 + with: + node-version: 14.x + registry-url: 'https://npm.pkg.github.com' + + - run: yarn --frozen-lockfile + + - uses: ./.github/actions/create-release-and-publish + with: + run-publish: | + yarn lerna publish from-package --yes + get-version: | + node --print 'require("./lerna.json").version' + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml new file mode 100644 index 0000000..34e6d09 --- /dev/null +++ b/.github/workflows/release-pr.yml @@ -0,0 +1,30 @@ +name: Release PR + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: write + +jobs: + release-note: + if: startswith(github.head_ref, 'releases/') + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v1 + with: + node-version: 14.x + + - run: yarn --frozen-lockfile + + - uses: ./.github/actions/generate-changelog + with: + get-version: | + node --print 'require("./lerna.json").version' diff --git a/scripts/create-release-pr b/scripts/create-release-pr new file mode 100755 index 0000000..79277fb --- /dev/null +++ b/scripts/create-release-pr @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -eu +set -o pipefail + +ROOT_DIR=$(dirname $0)/.. + +yarn lerna version --no-git-tag-version + +version=$(node --print 'require("./package.json").version') +branch="releases/${version}" + +git switch -c ${branch} +git commit --all -m "Release ${version}" +git push origin ${branch} + +gh pr create \ + --base="main" \ + --head="${branch}" \ + --title="Release v${version}" \ + --body="Release note will be generated automatically... ✍" \ + --asignee="@me" \ + --draft