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

Bootstrap reusable workflows for initial release #1

Merged
merged 59 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
a0df3d6
Add initial reusable workflow
nwiltsie Jul 29, 2024
449e2ae
Add token to environment
nwiltsie Jul 29, 2024
83daec5
Debug
nwiltsie Jul 29, 2024
7d40caf
Actually reference the variables
nwiltsie Jul 29, 2024
4fb3029
Do it in one step again
nwiltsie Jul 29, 2024
851d758
Debug jq syntax
nwiltsie Jul 29, 2024
1f24b4c
More debugging
nwiltsie Jul 29, 2024
b509d5f
Fix bug in jq filter
nwiltsie Jul 29, 2024
75ae17d
Use the PAT to get the reusable repository
nwiltsie Jul 29, 2024
e255274
Mark the full JSON as debug output
nwiltsie Jul 29, 2024
f25cbd6
Get the next version
nwiltsie Jul 29, 2024
3187e7f
fetch-tags does not work correctly
nwiltsie Jul 29, 2024
29acc5c
Apparently both are needed
nwiltsie Jul 29, 2024
7ecdb6c
Properly handle the leading v
nwiltsie Jul 29, 2024
546e865
Include exact in the same workflow
nwiltsie Jul 29, 2024
cb34d70
Handle the first release
nwiltsie Jul 30, 2024
ceb9aa7
Add in python code
nwiltsie Jul 30, 2024
1e3461f
Update the workflow to install the python package
nwiltsie Jul 30, 2024
21ce1c3
Remove python3.11 feature
nwiltsie Jul 30, 2024
aaf608b
Bugfix
nwiltsie Jul 30, 2024
ee9de62
Bump to requiring 3.8
nwiltsie Jul 30, 2024
b78a93d
Update the CHANGELOG
nwiltsie Jul 30, 2024
a572a6e
Actually re-write the file
nwiltsie Jul 30, 2024
829dfbc
Create a pull request with the changes
nwiltsie Jul 30, 2024
8d7e43e
Add logging levels for GitHub Actions
nwiltsie Jul 30, 2024
21178b8
Log more things
nwiltsie Jul 30, 2024
beb5ca0
Bugfix
nwiltsie Jul 30, 2024
9e2335a
Logging bugfixes
nwiltsie Jul 30, 2024
bfc0078
The filter has to be set on the handler
nwiltsie Jul 30, 2024
10362ba
Capture expected 'FATAL' output from tag check
nwiltsie Jul 30, 2024
91f24b4
Minor output tweak
nwiltsie Jul 30, 2024
0a9882f
Refactor code
nwiltsie Jul 30, 2024
b0b2e77
Output PR and commit details
nwiltsie Jul 30, 2024
68489ae
Add those details to the PR
nwiltsie Jul 30, 2024
bb02766
Fix lints, add missing __init__.py file
nwiltsie Jul 30, 2024
718967b
Bugfixes
nwiltsie Jul 30, 2024
29c4319
Add timezone as an input
nwiltsie Jul 30, 2024
6f118a6
Make sure the exact version doesn't have a leading `v`
nwiltsie Jul 30, 2024
c858905
Add workflow to create new tag after merge
nwiltsie Jul 30, 2024
5c016ad
Dump the GitHub context to log
nwiltsie Jul 30, 2024
2c13cdc
Use ref, not label
nwiltsie Jul 30, 2024
6251c32
Apparently the user is an Organization
nwiltsie Jul 30, 2024
a1adc7a
Bugfix
nwiltsie Jul 30, 2024
de8e7ff
Move release logic into sidecar script
nwiltsie Jul 31, 2024
3b9058a
Rename scripts and workflows
nwiltsie Jul 31, 2024
ac07fff
Add create-draft argument, post comment with link
nwiltsie Aug 1, 2024
76c59f5
Bugfix
nwiltsie Aug 1, 2024
a804356
See if the dash is the problem
nwiltsie Aug 1, 2024
ec0bb30
Use correct URL
nwiltsie Aug 1, 2024
29cccce
Log the release data
nwiltsie Aug 1, 2024
73e602b
Bugfix
nwiltsie Aug 1, 2024
6b6aa0c
Get the proper URL
nwiltsie Aug 1, 2024
85feb1c
Update CHANGELOG
nwiltsie Aug 1, 2024
7719e91
Update README
nwiltsie Aug 1, 2024
7bd3032
Fix lint
nwiltsie Aug 1, 2024
644ce8e
Run code through ruff
nwiltsie Aug 2, 2024
f66c0b3
Format docstrings to use triple-quotes
nwiltsie Aug 2, 2024
8fd9cc9
Replace asserts with exceptions
nwiltsie Aug 2, 2024
eca4a83
Silence warning about extra branches from asserts
nwiltsie Aug 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: Run PyTest

on:
pull_request:
branches:
- main
push:
branches:
- main
- nwiltsie-reusable-workflows

jobs:
pytest:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
python-version:
- "3.9"
- "3.12"

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Run tests
run: |
pip install tox
tox -e py${{matrix.python-version}}

- name: Upload pytest test results
uses: actions/upload-artifact@v4
if: success() || failure()
with:
name: "pytest-${{ matrix.python-version }}.xml"
path: junit/test-results.xml
if-no-files-found: error
43 changes: 43 additions & 0 deletions .github/workflows/wf-finalize-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
on:
workflow_call:
inputs:
draft:
description: If true (the default), draft the release for later manual approval.
type: boolean
default: true

jobs:
finalize-release:
runs-on: ubuntu-latest

steps:
# Get the version of _this_ repository that is in use so that we can use
# sidecar scripts
- id: workflow-parsing
name: Get SHA of reusuable workflow
env:
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
GH_TOKEN: ${{ github.token }}
run: |
ACTION_DATA=$(gh api "repos/$REPO/actions/runs/$RUN_ID")
echo "::debug::$ACTION_DATA"
SHA=$(echo "$ACTION_DATA" | jq -r '.referenced_workflows | .[] | select(.path | startswith("uclahs-cds/tool-create-release")).sha')
echo "SHA=$SHA" >> "$GITHUB_OUTPUT"

- name: Checkout reusable repository
uses: actions/checkout@v4
with:
repository: uclahs-cds/tool-create-release
ref: ${{ steps.workflow-parsing.outputs.SHA }}
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}

- id: parse-version
uses: actions/github-script@v7
env:
INPUT_DRAFT: ${{ inputs.draft }}
with:
script: |
const script = require('./scripts/finalize-release.js')
await script({github, context, core})
96 changes: 96 additions & 0 deletions .github/workflows/wf-prepare-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
on:
workflow_call:
inputs:
changelog:
type: string
description: Relative path to the CHANGELOG file
required: false
default: CHANGELOG.md
bump_type:
type: string
description: Semantic version bump type. Must be one of `major`, `minor`, `patch`, `prerelease`, or `exact`. Using the first four options will compute the next appropriate semantic version tag based on the most recent tag available from the main branch. Using `exact` is required for repositories without semantic version tags and allows specifying the exact next tag to use with the `exact_version` argument.
required: true
exact_version:
type: string
description: Exact version number to target. Only used if bump_type is set to `exact`.
required: false
default: ""
timezone:
type: string
description: IANA timezone to use when computing the current date
default: "America/Los_Angeles"
required: false

jobs:
prepare-release:
runs-on: ubuntu-latest

env:
BUMP_TYPE: ${{ inputs.bump_type }}
EXACT_VERSION: ${{ inputs.exact_version }}
CHANGELOG_TIMEZONE: ${{ inputs.timezone }}

steps:
# Get the version of _this_ repository that is in use so that we can use
# sidecar scripts
- id: workflow-parsing
name: Get SHA of reusuable workflow
env:
REPO: ${{ github.repository }}
RUN_ID: ${{ github.run_id }}
GH_TOKEN: ${{ github.token }}
run: |
ACTION_DATA=$(gh api "repos/$REPO/actions/runs/$RUN_ID")
echo "::debug::$ACTION_DATA"
SHA=$(echo "$ACTION_DATA" | jq -r '.referenced_workflows | .[] | select(.path | startswith("uclahs-cds/tool-create-release")).sha')
echo "SHA=$SHA" >> "$GITHUB_OUTPUT"

- name: Checkout reusable repository
uses: actions/checkout@v4
with:
repository: uclahs-cds/tool-create-release
path: reusable
ref: ${{ steps.workflow-parsing.outputs.SHA }}
token: ${{ secrets.UCLAHS_CDS_REPO_READ_TOKEN }}

- name: Checkout calling repository
uses: actions/checkout@v4
with:
path: caller
fetch-depth: 0
fetch-tags: true

- name: Set up python
uses: actions/setup-python@v5
with:
python-version: '3.10'

# Install the bundled package
- run: pip install ./reusable

# Get the next version using the package's script
- id: get-next-version
run: get-next-version "$REPO_DIR" "$BUMP_TYPE" "$EXACT_VERSION"
env:
REPO_DIR: caller

# Update the CHANGELOG
- id: bump-changelog
run: bump-changelog "$CHANGELOG" "$URL" "$VERSION"
env:
CHANGELOG: caller/${{ inputs.changelog }}
URL: ${{ github.server_url }}/${{ github.repository }}
VERSION: ${{ steps.get-next-version.outputs.next_version }}

- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
path: caller
add-paths: ${{ inputs.changelog }}
commit-message: ${{ steps.bump-changelog.outputs.commit_message }}
title: ${{ steps.bump-changelog.outputs.pr_title }}
body-path: ${{ steps.bump-changelog.outputs.pr_bodyfile }}
# This branch name format needs to be kept in-sync with the parser in
# create-new-tag.yaml
branch: automation-create-release-${{ steps.get-next-version.outputs.next_version }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*.rd[as]

# Python
._version.py
__pycache__/
.pytest_cache/
.Python
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Added

- Initial commit
- Workflow to update CHANGELOG and open pre-release PRs
- Workflow to create/draft releases after pre-release PR merge
117 changes: 117 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,118 @@
# Automations for GitHub Releases

This pair of reusable workflows manage the complexity of creating and tagging new software releases on GitHub.

`wf-prepare-release.yaml` is triggered manually (via a `workflow_dispatch`) and takes the following actions:

1. Compute the target version number based on existing tags and user input for `major`/`minor`/`patch`/`prerelease`.
1. Re-write the `CHANGELOG.md` file to move unreleased changes into a new dated release section.
1. Open a PR listing the target version number and release tag.

`wf-finalize-release.yaml`, triggered when a release PR is merged, takes the following actions:

1. Create a new release with auto-generated notes and the target tag.
* By default the new release is a draft, so no public release or tag are created without user intervention.
1. Comment on the release PR with a link to the new release.

## Example Usage

Usage of this tool requires adding two workflows to each calling repository:

**`prepare-release.yaml`**

```yaml
---
name: Prepare new release

run-name: Open PR for new ${{ inputs.bump_type }} release

on:
workflow_dispatch:
inputs:
bump_type:
type: choice
description: >-
Semantic version bump type. Using `exact` is required for repositories
without semantic version tags and allows specifying the exact next tag
to use with the `exact_version` argument.
required: true
options:
- major
- minor
- patch
- prerelease
- exact
exact_version:
type: string
description: >-
Exact version number to target. Only used if bump_type is set to
`exact`. Do not include a leading `v`.
required: false
default: ''

permissions:
actions: read
contents: write
pull-requests: write

jobs:
prepare-release:
uses: uclahs-cds/tool-create-release/.github/workflows/wf-prepare-release.yaml@v1
with:
bump_type: ${{ inputs.bump_type }}
exact_version: ${{ inputs.exact_version }}
# Secrets are only required until tool-create-release is made public
secrets: inherit
```

**`finalize-release.yaml`**

```yaml
---
name: Finalize release

on:
pull_request:
branches:
- main
types:
- closed

permissions:
actions: read
contents: write
pull-requests: write

jobs:
finalize-release:
# This conditional ensures that the reusable workflow is only run for
# release pull requests. The called workflow repeats these checks.
if: ${{ github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'automation-create-release') }}
uses: uclahs-cds/tool-create-release/.github/workflows/wf-finalize-release.yaml@v1
with:
draft: true
# Secrets are only required until tool-create-release is made public
secrets: inherit
```

## Parameters

Parameters can be specified using the [`with`](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runsstepswith) option.

| Workflow | Parameter | Type | Required | Description |
| ---- | ---- | ---- | ---- | ---- |
| `wf-prepare-release.yaml` | `bump_type` | string | yes | Kind of semantic release version to target. Must be one of `major`, `minor`, `patch`, `prerelease`, or `exact`. Using `exact` requires `exact_version`. |
| `wf-prepare-release.yaml` | `exact_version` | string | no | The exact version to assign to the next release (only used if `bump_type` is `exact`). Must not include a leading `v` - use `1XXXX`, not `v1XXXX`. |
| `wf-prepare-release.yaml` | `changelog` | string | no | Relative path to the CHANGELOG file. Defaults to `./CHANGELOG.md`. |
| `wf-prepare-release.yaml` | `timezone` | string | no | IANA timezone to use when calculating the current date for the CHANGELOG. Defaults to `America/Los_Angeles`. |
| `wf-finalize-release.yaml` | `draft` | boolean | no | If true (the default), mark the new release as a draft and require manual intervention to continue. |

## License

tool-generate-docs is licensed under the GNU General Public License version 2. See the file LICENSE.md for the terms of the GNU GPL license.

Copyright (C) 2024 University of California Los Angeles ("Boutros Lab") All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
Empty file added bumpchanges/__init__.py
Empty file.
Loading