Skip to content

Commit

Permalink
Automate the existing manual release process using GitHub Actions (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
pronovic authored Dec 30, 2022
1 parent 48f7848 commit 96b0632
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 69 deletions.
17 changes: 15 additions & 2 deletions .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ on:
push:
branches:
- master
tags:
- "v*"
pull_request:
branches:
- master
Expand All @@ -13,10 +15,21 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-test:
uses: pronovic/gha-shared-workflows/.github/workflows/poetry-build-and-test.yml@v2
linux-build-and-test:
name: "Linux"
uses: pronovic/gha-shared-workflows/.github/workflows/poetry-build-and-test.yml@v3
secrets: inherit
with:
matrix-os-version: "[ 'ubuntu-latest' ]"
matrix-python-version: "[ '3.9', '3.10', '3.11' ]"
poetry-version: "1.3.1"
release:
name: "Release"
if: github.ref_type == 'tag'
uses: pronovic/gha-shared-workflows/.github/workflows/poetry-release.yml@v3
needs: [ linux-build-and-test ]
secrets: inherit
with:
python-version: "3.9"
poetry-version: "1.3.1"
publish-pypi: false
13 changes: 13 additions & 0 deletions .run/commands/bumpchangelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# vim: set ft=bash ts=3 sw=3 expandtab:
# Bump the version in the changelog, preparing for a new development cycle

command_bumpchangelog() {
mv Changelog Changelog.$$
echo "Version $(poetry version patch --short) unreleased" > Changelog
echo "" >> Changelog
echo $'\t* ' >> Changelog
echo "" >> Changelog
cat Changelog.$$ >> Changelog
rm -f Changelog.$$
}

2 changes: 1 addition & 1 deletion .run/commands/latestcode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Make sure that the latest code is installed

command_latestcode() {
poetry install --only-root >/dev/null
poetry install --only-root --all-extras >/dev/null
if [ $? != 0 ]; then
echo "*** Failed to install the latest code"
exit 1
Expand Down
28 changes: 0 additions & 28 deletions .run/commands/publishpypi.sh

This file was deleted.

31 changes: 15 additions & 16 deletions .run/commands/tagrelease.sh
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# vim: set ft=bash ts=3 sw=3 expandtab:
# Update the changelog and tag a specific version of the code
# Update the changelog, tag a specific version of the code, and push the changes

command_tagrelease() {
local VERSION EARLIEST_YEAR LATEST_YEAR DEFAULT_BRANCH CURRENT_BRANCH COPYRIGHT DATE TAG FILES MESSAGE
local VERSION DATE TAG FILES MESSAGE

if [ $# != 1 ]; then
echo "tagrelease <version>"
exit 1
fi

VERSION=$(echo "$1" | sed 's/^v//') # so you can use "0.1.5 or "v0.1.5"
EARLIEST_YEAR=$(git log --pretty="%ci" $(git rev-list --max-parents=0 HEAD) | sed 's/-.*$//g')
LATEST_YEAR=$(git log -1 --pretty="%ci" | sed 's/-.*$//g')
DEFAULT_BRANCH=$(git config --get init.defaultBranch) # works on git > 2.28.0 from 2020
CURRENT_BRANCH=$(git branch -a | grep '^\*' | sed 's/^\* //')
DATE=$(date +'%d %b %Y')
TAG="v$VERSION" # follow PEP 440 naming convention
FILES="NOTICE pyproject.toml Changelog"
MESSAGE="Release v$VERSION to PyPI"
FILES="NOTICE Changelog"
MESSAGE="Release v$VERSION"

# Use $COPYRIGHT_START to override the earliest year found, in case git doesn't contain all history
EARLIEST_YEAR=${COPYRIGHT_START:-$(git log --pretty="%ci" $(git rev-list --max-parents=0 HEAD) | sed 's/-.*$//g')}
LATEST_YEAR=$(git log -1 --pretty="%ci" | sed 's/-.*$//g')

if [ "$EARLIEST_YEAR" == "$LATEST_YEAR" ]; then
COPYRIGHT="${EARLIEST_YEAR}"
Expand All @@ -42,13 +42,6 @@ command_tagrelease() {
exit 1
fi

poetry version $VERSION
if [ $? != 0 ]; then
echo "*** Failed to update version"
exit 1
fi

run_command dos2unix pyproject.toml
run_command sedreplace "s|^Version $VERSION[[:blank:]][[:blank:]]*unreleased|Version $VERSION $DATE|g" Changelog
run_command sedreplace "s|(^ *Copyright \(c\) *)([0-9,-]+)( *.*$)|\1$COPYRIGHT\3|" NOTICE

Expand All @@ -66,8 +59,14 @@ command_tagrelease() {
exit 1
fi

git push --follow-tags
if [ $? != 0 ]; then
echo "*** Push step failed"
exit 1
fi

echo ""
echo "*** Version v$VERSION has been released and committed; you may publish now"
echo "*** Version v$VERSION has been tagged"
echo ""
}

2 changes: 1 addition & 1 deletion .run/commands/virtualenv.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Create and update the virtualenv, synchronizing it to versions in poetry.lock

command_virtualenv() {
poetry install --sync
poetry install --sync --all-extras
if [ $? != 0 ]; then
echo "*** Failed to install the virtualenv"
exit 1
Expand Down
12 changes: 12 additions & 0 deletions .run/tasks/dch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# vim: set ft=bash sw=3 ts=3 expandtab:

help_dch() {
# No help - hidden utility feature, sort of equivalent to the Debian 'dch' command
echo -n ""
}

task_dch() {
run_command bumpchangelog
vim "+3" "+startinsert!" Changelog
}

18 changes: 1 addition & 17 deletions .run/tasks/release.sh
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
# vim: set ft=bash sw=3 ts=3 expandtab:
# runscript: customized=true

help_release() {
echo "- run release: Release a specific version and tag the code"
echo "- run release: Tag and release the code, triggering GHA to publish artifacts"
}

task_release() {
local version

run_command tagrelease "$@"
run_task build

version=$(poetry version --short)
echo ""
echo "*** Version v$version has been released and committed"
echo ""
echo "Next, push: git push --follow-tags"
echo ""
echo "Then go to: https://github.com/pronovic/vplan/releases/tag/v$version"
echo ""
echo "Convert the tag to a release and attach build artifacts:"
ls -l dist
echo ""
}

6 changes: 6 additions & 0 deletions .run/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,15 @@ task_help() {

# Setup the runtime environment
setup_environment() {
local EARLIEST_YEAR LATEST_YEAR

DOTRUN_DIR="$REPO_DIR/.run"

WORKING_DIR=$(mktemp -d)
trap "rm -rf '$WORKING_DIR'" EXIT SIGINT SIGTERM

DEFAULT_BRANCH=$(git config --get init.defaultBranch) # works on git > 2.28.0 from 2020
CURRENT_BRANCH=$(git branch -a | grep '^\*' | sed 's/^\* //')
}

# Add addendum information to the end of the help output
Expand Down
1 change: 1 addition & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Version 0.6.2 unreleased

* Add NOTICE file to sdist, alongside existing LICENSE file.
* Automate the existing manual release process using GitHub Actions.

Version 0.6.1 24 Oct 2022

Expand Down
31 changes: 30 additions & 1 deletion DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Basic tasks:
Additional tasks:
- run build: Build artifacts in the dist/ directory
- run release: Release a specific version and tag the code
- run release: Tag and release the code, triggering GHA to publish artifacts
- run rmdb: Remove the sqlite database files used for local testing
- run server: Run the vplan REST server at localhost:8080
- run server -r: Run the vplan REST server, removing the database first
Expand Down Expand Up @@ -281,3 +281,32 @@ source ~/.bash_profile
|Make console active on message in stdout|_Checked_|
|Make console active on message in stderr|_Checked_|
|Output filters|`$FILE_PATH$:$LINE$:$COLUMN.*`|


## Release Process

There is a partially-automated process to publish a new release to GitHub.

> _Note:_ In order to publish code, you must must have push permissions to the
> GitHub repo.
Ensure that you are on the `master` branch. Releases must always be done from
`master`.

Ensure that the `Changelog` is up-to-date and reflects all of the changes that
will be published. The top line must show your version as unreleased:

```
Version 0.6.2 unreleased
```

Run the release command:

```
./run release 0.6.2
```

This command updates `NOTICE` and `Changelog` to reflect the release version
and release date, commits those changes, tags the code, and pushes to GitHub.
The new tag triggers a GitHub Actions build that runs the test suite, generates
the artifacts, and finally creates a release from the tag.
14 changes: 11 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "vplan"
version = "0.6.1"
version = "0.0.0" # published version is managed using Git tags (see below)
description = "Vacation plan manager service for SmartThings"
authors = ["Kenneth J. Pronovici <[email protected]>"]
license = "Apache-2.0"
Expand All @@ -26,6 +26,14 @@ classifiers=[
"Topic :: Home Automation",
]

# Published version is managed using Git tags
# We get either the tag (like "0.24.1") or a snapshot-type version (like "0.24.1+3.e8319c4")
# If the plugin is not installed, then the version is always "0.0.0", taken from above
[tool.poetry-dynamic-versioning]
enable = true
pattern = '^[vV](?P<base>\d+\.\d+\.\d+)' # this extracts the version from our vX.Y.Z tag format
format-jinja = "{% if distance == 0 and not dirty %}{{ base }}{% else %}{{ base }}+{{ distance }}.{{ commit }}{% endif %}"

[tool.poetry.scripts]
vplan = "vplan.client.cli:vplan"

Expand Down Expand Up @@ -85,5 +93,5 @@ line_length = 132
skip_glob = [ "docs", "notes" ]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
requires = ["poetry>=1.0.0", "poetry-dynamic-versioning"]
build-backend = "poetry_dynamic_versioning.backend"

0 comments on commit 96b0632

Please sign in to comment.