Skip to content

Commit

Permalink
Add release and mergeback workflows
Browse files Browse the repository at this point in the history
This commit ensures that the changelog is updated before a release with
the correct date and version.

Also, after a release, a mergeback PR is created to ensure that the
changelog update and version bump is available in main.
  • Loading branch information
aeisenberg committed May 19, 2021
1 parent bc39b21 commit 14f5cf4
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 5 deletions.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.5
python-version: 3.8

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install PyGithub==1.51 requests
- name: Update git config
run: |
git config --global user.email "codeql-core@github.com"
git config --global user.name "CodeQL Actions Bot"
- name: Update release branch
run: python .github/update-release-branch.py ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }}
56 changes: 52 additions & 4 deletions .github/update-release-branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
import requests
import subprocess
import sys
import json
import datetime
import os

EMPTY_CHANGELOG = """
# CodeQL Action: Changelog
## [UNRELEASED]
"""

# The branch being merged from.
# This is the one that contains day-to-day development work.
Expand Down Expand Up @@ -71,6 +81,13 @@ def open_pr(repo, all_commits, short_main_sha, branch_name):
body += ' - ' + get_truncated_commit_message(commit)
body += ' (@' + commit.author.login + ')'

body += '\n\nPlease review the following:\n'
body += ' - [ ] The CHANGELOG displays the correct version and date.\n'
body += ' - [ ] The CHANGELOG includes all relevant, user-facing changes since the last release.\n'
body += ' - [ ] There are no unexpected commits being merged into the ' + LATEST_RELEASE_BRANCH + ' branch.\n'
body += ' - [ ] The docs team is aware of any documentation changes that need to be released.\n'
body += ' - [ ] The mergeback PR is merged back into ' + MAIN_BRANCH + ' after this PR is merged.\n'

title = 'Merge ' + MAIN_BRANCH + ' into ' + LATEST_RELEASE_BRANCH

# Create the pull request
Expand All @@ -95,7 +112,7 @@ def get_conductor(repo, pull_requests, other_commits):
# This will not include any commits that exist on the release branch
# that aren't on main.
def get_commit_difference(repo):
commits = run_git('log', '--pretty=format:%H', ORIGIN + '/' + LATEST_RELEASE_BRANCH + '..' + MAIN_BRANCH).strip().split('\n')
commits = run_git('log', '--pretty=format:%H', ORIGIN + '/' + LATEST_RELEASE_BRANCH + '..' + ORIGIN + '/' + MAIN_BRANCH).strip().split('\n')

# Convert to full-fledged commit objects
commits = [repo.get_commit(c) for c in commits]
Expand Down Expand Up @@ -135,17 +152,40 @@ def get_pr_for_commit(repo, commit):
def get_merger_of_pr(repo, pr):
return repo.get_commit(pr.merge_commit_sha).author.login

def get_current_version():
with open('package.json', 'r') as f:
return json.load(f)['version']

def get_today_string():
today = datetime.datetime.today()
return '{:%d %b %Y}'.format(today)

def update_changelog(version):
if (os.path.exists('CHANGELOG.md')):
content = ''
with open('CHANGELOG.md', 'r') as f:
content = f.read()
else:
content = EMPTY_CHANGELOG

newContent = content.replace('[UNRELEASED]', version + ' - ' + get_today_string(), 1)

with open('CHANGELOG.md', 'w') as f:
f.write(newContent)


def main():
if len(sys.argv) != 3:
raise Exception('Usage: update-release.branch.py <github token> <repository nwo>')
github_token = sys.argv[1]
repository_nwo = sys.argv[2]

repo = Github(github_token).get_repo(repository_nwo)
version = get_current_version()

# Print what we intend to go
print('Considering difference between ' + MAIN_BRANCH + ' and ' + LATEST_RELEASE_BRANCH)
short_main_sha = run_git('rev-parse', '--short', MAIN_BRANCH).strip()
short_main_sha = run_git('rev-parse', '--short', ORIGIN + '/' + MAIN_BRANCH).strip()
print('Current head of ' + MAIN_BRANCH + ' is ' + short_main_sha)

# See if there are any commits to merge in
Expand All @@ -157,7 +197,7 @@ def main():
# The branch name is based off of the name of branch being merged into
# and the SHA of the branch being merged from. Thus if the branch already
# exists we can assume we don't need to recreate it.
new_branch_name = 'update-' + LATEST_RELEASE_BRANCH + '-' + short_main_sha
new_branch_name = 'update-v' + version + '-' + short_main_sha
print('Branch name is ' + new_branch_name)

# Check if the branch already exists. If so we can abort as this script
Expand All @@ -168,7 +208,15 @@ def main():

# Create the new branch and push it to the remote
print('Creating branch ' + new_branch_name)
run_git('checkout', '-b', new_branch_name, MAIN_BRANCH)
run_git('checkout', '-b', new_branch_name, ORIGIN + '/' + MAIN_BRANCH)

print('Updating changelog')
update_changelog(version)

# Create a commit that updates the CHANGELOG
run_git('add', 'CHANGELOG.md')
run_git('commit', '-m', version)

run_git('push', ORIGIN, new_branch_name)

# Open a PR to update the branch
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/post-release-mergeback.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# This workflow runs after a release of the action.
# It merges any changes from the release back into the
# main branch. Typically, this is just a single commit
# that updates the changelog.
name: Mergeback after release

on:
workflow_dispatch:
inputs:
baseBranch:
description: 'The base branch to merge into'
default: main
required: false

# Commented for now to ensure we don't run this accidentally after a real merge
# push:
# branches:
# - v1

pull_request:
paths:
- .github/workflows/post-release-mergeback.yml

jobs:
merge-back:
runs-on: ubuntu-latest
env:
BASE_BRANCH: "${{ github.event.inputs.baseBranch || 'main' }}"
# TODO head_ref won't exist in workflow dispatch
HEAD_BRANCH: "${{ github.head_ref }}"
NEW_BRANCH: "mergeback/${{ github.head_ref }}-to-${{ github.event.inputs.baseBranch || 'main' }}"

steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
run: echo "$GITHUB_CONTEXT"

- name: Dump branches
run: |
echo "BASE_BRANCH $BASE_BRANCH"
echo "HEAD_BRANCH $HEAD_BRANCH"
echo "NEW_BRANCH $NEW_BRANCH"
- name: validate
run: |
if [ "$BASE_BRANCH" -eq "$HEAD_BRANCH" ]; then
echo "error::Base branch and head branch are the same $BASE_BRANCH."
exit -1
fi
- uses: actions/checkout@v2
- uses: actions/setup-node@v2

- name: Update git config
run: |
git config --global user.email "codeql-core@github.com"
git config --global user.name "CodeQL Actions Bot"
- name: Create mergeback branch
run: |
git checkout -b $NEW_BRANCH
- name: Check for tag
id: check
run: |
set +e # don't fail on an errored command
VERSION="$(jq '.version' -r 'package.json')"
TAG="v$VERSION"
git ls-remote --tags origin | grep $TAG
EXISTS="$?"
if [ "$EXISTS" -ne 0 ]; then
echo "::set-output name=exists::true"
echo "Tag $TAG exists. Not going to re-release."
fi
# we didn't tag the release during the update-release-branch workflow because the
# commit that actually makes it to the main branch may be different than the one
# created by the workflow. We tag now because we know the correct commit
- name: Tag release
if: steps.check.outputs.exists == 'true'
run: |
VERSION="$(jq '.version' -r 'package.json')"
git tag -a "v$VERSION" -m "v$VERSION"
git push origin --follow-tags "v$VERSION"
- name: Create mergeback branch
if: steps.check.outputs.exists == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -exu
PR_TITLE="Mergeback $HEAD_BRANCH into $BASE_BRANCH"
PR_BODY="Updates version and changelog."
# Update the changelog
perl -i -pe 's/^/## \[UNRELEASED\]\n\n/ if($.==3)' CHANGELOG.md
git add CHANGELOG.md
git commit -m "Update changelog for new version"
npm version
# Create pull request TODO: choose a better reviewer
git push origin "$NEW_BRANCH"
# TODO aeisenberg isn't the right reviewer, would like to specify the github/codeql-core team, but not working right now.
gh pr create --head "$NEW_BRANCH" --base "$BASE_BRANCH" --reviewer "aeisenberg" --title "$PR_TITLE" --body "$PR_BODY"

0 comments on commit 14f5cf4

Please sign in to comment.