Skip to content

Commit

Permalink
Merge pull request #1 from d3b-center/release-maker
Browse files Browse the repository at this point in the history
🎉 New release maker
  • Loading branch information
fiendish committed Jun 2, 2020
2 parents a5bd6cc + d07ecec commit 1c49d0a
Show file tree
Hide file tree
Showing 9 changed files with 737 additions and 2 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/gh_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This workflow will load Python, run a script to generate assets, and then
# bundle a github release

name: Release generator

on:
pull_request:
types:
- closed

jobs:
create_release:
if: github.base_ref == 'master' && github.event.pull_request.merged && contains( github.event.pull_request.labels.*.name, 'release')
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v1
with:
python-version: 3.8

- name: Create tag from title and run asset script
id: find_tag_and_prepare_assets
run: |
TAG=$(echo ${{ github.event.pull_request.title }} | sed -E "s/^.*Release (.+\..+\..+)$/\1/g")
echo "::set-output name=tag::$TAG"
SCRIPT=.github/prepare_assets.sh
if [ -f $SCRIPT ]; then
chmod u+x $SCRIPT
$SCRIPT $TAG
fi
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.find_tag_and_prepare_assets.outputs.tag }}
release_name: ${{ github.event.pull_request.title }}
body: ${{ github.event.pull_request.body }}
draft: false
prerelease: false

- name: Upload Assets
run: |
upload_url=${{ steps.create_release.outputs.upload_url }}
if [ -f .github/release_assets.txt ]; then
while IFS="" read -r FILE || [ -n "$FILE" ]
do
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Content-Type: $(file -b --mime-type $FILE)" \
--data-binary "@$FILE" \
"${upload_url%\{*}?name=$(basename $FILE)"
done < .github/release_assets.txt
fi
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Dotfiles/dotdirs
.*

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# Environments
env/
venv/
ENV/
env.bak/
venv.bak/

# Distribution / packaging
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
*.egg
MANIFEST

# Sphinx documentation
docs/_build/
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,65 @@
# d3b-release-maker
Tool to generate GitHub-based software releases
# D3b Release Maker

Tool to automate GitHub-based software releases for projects with the following
characteristics:

- Feature branching with merge-commits into master
- Gitmoji-style PR messages
- Semantic versioning tags for releases (<https://semver.org>)

## Part 1: CLI that generates release notes and creates a PR on GitHub for review

Install with pip:
`pip install git+https://github.com/d3b-center/d3b-release-maker.git`

Create a temporary auth token on GitHub and add it to your environment as
`GH_TOKEN`.

Then run: `release --help`

## Part 2: GitHub Actions Workflow that automates tagging releases and asset uploading

Copy `gh_releases.yml` from this repository's `.github/workflows/` directory
into `.github/workflows/` in your project repository. (Read more about GitHub
Actions and Workflows at <https://help.github.com/en/actions>)

If you want to attach binary assets to your GitHub releases, add a
`.github/prepare_assets.sh` script that receives one input argument with the
new release version and generates your assets and then creates
`.github/release_assets.txt` containing a list of the files you want to upload,
one per line, in the order that you want them to appear.

## What the parts do

### What the CLI does

When you run the `release build` command:

1. The CLI looks at the most recent git tag that looks like a Semantic Version.
2. Then it looks for all PRs that were merged into master after that tag which
do not themselves look like a release merge.
3. Emojis at the start of the PR titles are grouped and counted according to
the gitmoji emoji guide (<https://gitmoji.carloscuesta.me>).
4. Markdown is generated with links to PRs, merge commits, and committers and is
shown to the user.
5. The user is prompted to provide a type of version update (major, minor,
patch) based on the shown list of changes, and a new version number is
generated.
6. A fresh copy of your repository is cloned to a temporary location.
7. The new changes list is added to the CHANGELOG.md file (one is created if
one doesn't already exist).
8. An optional user-provided script is then run if you need to e.g. add the new
version number to files in your repository.
9. All newly modified files are commited with a special release commit and
pushed to a special release branch, and a Pull Request into master is opened
on GitHub for review.

### What the GitHub Actions Workflow does

When a special release branch is merged into master:

1. Your repository is tagged with the new semantic version, and a GitHub
release is created with the contents of the just-merged Pull Request body.
2. If a `.github/prepare_assets.sh` script exists, it is run.
3. If a `.github/release_assets.txt` file exists, any files listed in it are
then uploaded to the GitHub release.
Empty file added d3b_release_maker/__init__.py
Empty file.
60 changes: 60 additions & 0 deletions d3b_release_maker/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python
import click

from d3b_release_maker.release_maker import (
make_release,
new_notes,
)


@click.group(context_settings={"help_option_names": ["-h", "--help"]})
def cli():
"""
Container for the cli
"""
pass


def options(function):
function = click.option(
"--blurb_file",
prompt="Optional markdown file containing a custom message to prepend to the notes for this release",
default="",
help="Optional markdown file containing a custom message to prepend to the notes for this release",
)(function)
function = click.option(
"--repo",
prompt="The github repository (e.g. my-organization/my-project-name)",
help="The github organization/repository to make a release for",
)(function)
return function


@click.command(
name="preview", short_help="Preview the changes for a new release"
)
@options
def preview_changelog_cmd(repo, blurb_file):
new_notes(repo, blurb_file)


@click.command(name="build", short_help="Generate a new release on GitHub")
@options
@click.option(
"--project_title",
prompt="The title of the project",
default="",
help="This will be put before the release number in the generated notes",
)
@click.option(
"--pre_release_script",
prompt="Shell script to run before pushing the release to GitHub",
default="",
help="Shell script to run before pushing the release to GitHub",
)
def make_release_cmd(repo, project_title, blurb_file, pre_release_script):
make_release(repo, project_title, blurb_file, pre_release_script)


cli.add_command(preview_changelog_cmd)
cli.add_command(make_release_cmd)
49 changes: 49 additions & 0 deletions d3b_release_maker/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Default config values for release maker
"""

GITHUB_API = "https://api.github.com"
GITHUB_RAW = "https://raw.githubusercontent.com"

GH_TOKEN_VAR = "GH_TOKEN"
RELEASE_EMOJIS = "🏷🔖"
EMOJI_CATEGORIES = {
"Additions": {"✨", "🎉", "📈", "➕", "🌐", "🔀", "🔊"},
"Documentation": {"💡", "📝"},
"Removals": {"🔥", "➖", "⏪", "🔇", "🗑"},
"Fixes": {
"🐛",
"🚑",
"🔒",
"🍎",
"🐧",
"🏁",
"🤖",
"🍏",
"🚨",
"✏️",
"👽",
"👌",
"♿️",
"💬",
"🚸",
"🥅",
},
"Ops": {
"🚀",
"💚",
"⬇️",
"⬆️",
"📌",
"👷",
"🐳",
"📦",
"👥",
"🙈",
"📸",
"☸️",
"🌱",
"🚩",
},
}
OTHER_CATEGORY = "Other Changes"
Loading

0 comments on commit 1c49d0a

Please sign in to comment.