Skip to content
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

feat(actions): add reusable actions, release cleanup #354

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
29 changes: 29 additions & 0 deletions .github/actions/cleanup-discarded-release/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# used to extract the version from a release branch
# "release/1.0.0-next.0" -> "1.0.0-next.0"
name: cleanup-discarded-release
description: Cleans up discarded release artifacts such as branch and draft release
inputs:
github-token:
description: GitHub token needed for ops
default: ${{ github.token }}
required: true
version:
description: version of the discarded release (e.g. v1.0.0-next.0)
required: true
branch:
description: branch name (e.g. head_ref)
required: true
runs:
using: 'composite'
steps:
- uses: actions/checkout@v3
with:
persist-credentials: true
- name: delete-release-branch
run: git push origin --quiet --delete ${{ inputs.branch }} && echo 'deleted branch' || true
shell: bash
- name: delete-release-draft
run: gh release delete ${{ inputs.version }} && echo 'deleted release' || true
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
22 changes: 22 additions & 0 deletions .github/actions/extract-version-from-branch/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# used to extract the version from a release branch
# "release/1.0.0-next.0" -> "1.0.0-next.0"
name: extract-version-from-branch
description: Extracts version from a branch name
inputs:
branch:
description: branch name (e.g. head_ref)
required: true
outputs:
version:
description: extracted version
value: ${{ steps.extract-version.outputs.version }}
runs:
using: 'composite'
steps:
- name: extract-version
id: extract-version
shell: bash
run: |
branch=${{ inputs.branch }}
version=${branch#release/}
echo "version=$version" >> $GITHUB_OUTPUT
File renamed without changes.
31 changes: 31 additions & 0 deletions .github/workflows/cleanup-discarded-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: cleanup-discarded-release
on:
pull_request:
branches:
- main
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
# We run cleanup action only if:
# 1. PR comes from internal branch (i.e. not a fork)
# 2. PR is NOT merged
# 3. PR branch name begins with "release/"
if: |
github.event.pull_request.head.repo.full_name == github.repository &&
github.event.pull_request.merged == false &&
startsWith(github.event.pull_request.head.ref, 'release/')
steps:
- uses: actions/checkout@v3
with:
persist-credentials: false
- id: version
uses: ./.github/actions/extract-version-from-branch
with:
branch: ${{ github.head_ref }}
- uses: ./.github/actions/cleanup-discarded-release
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.head_ref }}
version: ${{ steps.version.outputs.version }}
File renamed without changes.
110 changes: 110 additions & 0 deletions .github/workflows/create-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: create-release
on:
workflow_dispatch:
inputs:
type:
type: choice
description: 'Type of release'
options: # put in ascending order to not accidentally cut a "major" release PR
- prerelease
- prepatch
- preminor
- premajor
- patch
- minor
- major
required: true
jobs:
create-release:
permissions:
# needed to create release PR
pull-requests: write
# needed to create draft release
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
persist-credentials: true
- uses: pnpm/action-setup@v2
- name: set git config for pnpm version, git push
run: |
git config --global user.name "GitHub Actions"
git config --global user.email [email protected]
- name: is-prerelease
id: is-prerelease
run: |
is=false
if [[ ${{ github.event.inputs.type }} == pre* ]]
then
is=true
fi
echo "is-prerelease=$is" >> $GITHUB_OUTPUT
- name: set-version
id: version
run: |
if [[ ${{ steps.is-prerelease.outputs.is-prerelease }} == true ]]
then
version=$(pnpm version ${{ github.event.inputs.type }} --no-git-tag-version --preid next)
else
version=$(pnpm version ${{ github.event.inputs.type }} --no-git-tag-version)
fi
echo "version=$version" >> $GITHUB_OUTPUT
- run: echo "::debug::version is ${{ steps.version.outputs.version }}"
- run: echo "::notice title="releasing"::${{ steps.version.outputs.version }}"
- if: ${{ steps.version.outputs.version == '' }}
run: echo "::error ::Invalid version" && exit 1
# - uses: actions/setup-node@v3 # is this needed???
# with:
# node-version-file: '.nvmrc'
# cache: 'pnpm'
- id: branch
run: echo "name=release/${{ steps.version.outputs.version }}" >> $GITHUB_OUTPUT
- name: create release branch
run: git checkout -b ${{ steps.branch.outputs.name }}
# this is not required when pnpm is creating the git tag
- name: add and commit changes to release branch
run: |
git add package.json
git commit -m '[automated] release: ${{ steps.version.outputs.version }}'
- name: push to release branch
run: git push origin ${{ steps.branch.outputs.name }}
- name: create draft release
id: draft-release
run: |
if [[ ${{ steps.is-prerelease.outputs.is-prerelease }} == true ]]
then
url=$(gh release create ${{ steps.version.outputs.version }} --generate-notes --draft --prerelease)
else
url=$(gh release create ${{ steps.version.outputs.version }} --generate-notes --draft)
fi
echo "url=$url" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# TODO: remove sleep https://github.com/cli/cli/issues/6599#issuecomment-1314562972
- run: sleep 5
- name: create pull request
id: pr
run: |
body_file=body.md
# get URL to this workflow run
run="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
# output intro message to an ephemeral markdown file
echo "_This pull request was automatically created by [GitHub Actions]($run)_" > $body_file
# output the generated release notes to an ephemeral markdown file
gh release view ${{ steps.version.outputs.version }} --json body --jq .body >> $body_file
# get the pull request URL
url=$(gh pr create --title "release: ${{ steps.version.outputs.version }}" --body-file $body_file)
echo "link=$url" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: echo ::notice title="created"::${{ steps.pr.outputs.link }}
- run: echo ::notice title="type"::${{ github.event.inputs.type }}
- run: echo ::notice title="draft release"::${{ steps.draft-release.outputs.url }}
- name: cleanup
if: failure()
uses: ./.github/actions/cleanup-discarded-release
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ steps.branch.outputs.name }}
version: ${{ steps.version.outputs.version }}
66 changes: 0 additions & 66 deletions .github/workflows/create-release.yml

This file was deleted.

20 changes: 10 additions & 10 deletions .github/workflows/release.yml → .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ jobs:
github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'release/')
outputs:
version: ${{ steps.version.outputs.result }}
is-prerelease: ${{ contains(steps.version.outputs.result, 'next') }}
version: ${{ steps.extract-version.outputs.version }}
is-prerelease: ${{ contains(steps.extract-version.outputs.version, 'next') }}
steps:
- name: extract-version
id: version
uses: actions/[email protected]
- uses: actions/checkout@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
return context.payload.pull_request.title.replace(/release\: /, '');
persist-credentials: false
- id: extract-version
uses: ./.github/actions/extract-version-from-branch
with:
branch: ${{ github.head_ref }}
prerelease:
needs: verify-run
uses: ./.github/workflows/release-env.yml
uses: ./.github/workflows/release-env.yaml
secrets: inherit
with:
env: next
Expand All @@ -38,7 +38,7 @@ jobs:
release:
needs: [verify-run, prerelease]
if: ${{ fromJSON(needs.verify-run.outputs.is-prerelease) == false }}
uses: ./.github/workflows/release-env.yml
uses: ./.github/workflows/release-env.yaml
secrets: inherit
with:
env: main
Expand Down
18 changes: 9 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Go to either the GitHub organization or repository that you wish to recieve rele
3. Under **Payload URL** , paste in the Discord Webhook URL from before with `/github` appended to the end
4. Under **Content type**, select `application/json`
5. Create a **Secret** and store it in `.env` as `GITHUB_RELEASES_WEBHOOK_SECRET`
6. Select **Let me select individual events** then choose `releases`
6. Select **Let me select individual events** then choose `releases`
7. Click **Add Webhook**

<img src=./docs/guide/github-webhook.png width="900" >
Expand All @@ -146,10 +146,10 @@ Configuring this webhook will remove the Discord `staff` role when members leave
You must be the owner of the GitHub organization to perform the following steps.

1. Go to your GitHub organization, and click **Settings** -> **Webhooks** -> **Add Webhook**
2. Under **Payload URL** choose `http://<your-production-url>/api/webhooks/github-org-membership`
2. Under **Payload URL** choose `http://<your-production-url>/api/webhooks/github-org-membership`
3. Under **Content type**, select `application/json`
4. Create a **Secret** and store in in `.env` as `GITHUB_ORG_WEBHOOK_SECRET`
5. Select **Let me select individual events** then choose `Organizations`
5. Select **Let me select individual events** then choose `Organizations`
6. **Add Webhook**

### Configuring a GitHub App
Expand All @@ -162,7 +162,7 @@ A GitHub App is required to obtain the permissions necessary for many API calls.
2. Select **New GitHub App**
3. For the homepage URL, put in the homepage of your website
4. Under **Callback URL** put `http://<your-production-url>/api/auth/callback/github`
5. Select **Expire user authorization tokens** AND **Request user authorization (OAuth) during installation**
5. Select **Expire user authorization tokens** AND **Request user authorization (OAuth) during installation**
6. Under **Webhook** deselect **Active**
7. Scroll down to **Organization Permissions** and under **Members** select `Read-only`
8. **Create GitHub App**
Expand Down Expand Up @@ -218,8 +218,8 @@ Now you should be looking at the settings page for your app.
```

4. Copy this ID and store in `.env` as `GITHUB_INSTALLATION_ID`
<img src=./docs/guide/github-installation-id.png width="900">
<img src=./docs/guide/github-installation-id.png width="900">

## Deployment

For the deployment we will work primarily in the [`cdk`](./cdk) directory, where the [AWS CDK CLI](https://www.npmjs.com/package/aws-cdk) is installed locally to the package.
Expand Down Expand Up @@ -267,11 +267,11 @@ When `pnpm test` is run from the project root, the newly added test is executed
## Releasing

1. developer creates a PR from their fork
2. maintainers review and add the `run-ci` label to [run the CI pipeline](./.github/workflows/ci.yml) and get the apporpriate status check
2. maintainers review and add the `run-ci` label to [run the CI pipeline](./.github/workflows/ci.yaml) and get the apporpriate status check
3. after PR requirements are met, maintainers merge to `main`
4. maintainers manually run the [`create-release`](./.github/workflows/create-release.yml) action with the desired version release (major, minor, patch, prerelease)
4. maintainers manually run the [`create-release`](./.github/workflows/create-release.yaml) action with the desired version release (major, minor, patch, prerelease)
5. maintainers review and merge the automatically-created PR
6. GitHub Actions run [`release`](./.github/workflows/release.yml) action using the version specified in the PR title
6. GitHub Actions run [`release`](./.github/workflows/release.yaml) action using the version specified in the PR title

This process uses one branch, `main`, and relies on the created releases and git tags to showcase the latest source code available in each environment (release -> `main` vs prerelease -> `next`).

Expand Down