Skip to content

Commit

Permalink
Add github actions
Browse files Browse the repository at this point in the history
  • Loading branch information
hampuslidin committed Dec 19, 2022
1 parent c06cfea commit e789acf
Show file tree
Hide file tree
Showing 11 changed files with 386 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "daily"
112 changes: 112 additions & 0 deletions .github/workflows/create_release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Create Release

on:
workflow_dispatch:
inputs:
bumpVersion:
description: "Bump version"
required: true
default: patch
type: choice
options:
- patch
- minor
- major

env:
CARGO_TERM_COLOR: always
RUST_VERSION: 1.66.0

jobs:
bump_version:
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.bv.outputs.new_version }}
steps:
- uses: actions/checkout@v3
- name: Prepare branch
run: |
if [[ ! `git branch --show-current` = 'master' ]] ; then
echo "Releases can only be created from the \`master\` branch" >&2
exit 1
fi
git fetch --tags
git checkout -b feature
- name: Bump version
id: bv
run: |
new_version=`scripts/bumb_version.py ${{ inputs.bumpVersion }}`
echo "new_version=$new_version" >> $GITHUB_OUTPUT
- name: Update lock file
uses: actions-rs/cargo@v1
with:
command: update
args: --package hoc
- name: Create release branch
id: crb
run: |
release_branch="release/v${NEW_VERSION}"
git checkout -b "$release_branch"
git \
-c author.name=${{ github.actor }} \
-c author.email=${{ github.actor }}@users.noreply.github.com \
-c committer.name=Github \
-c [email protected] \
commit -a -m "Prepare release v${NEW_VERSION}"
git push --set-upstream origin "$release_branch"
echo "release_branch=$release_branch" >> $GITHUB_OUTPUT
env:
NEW_VERSION: ${{ steps.bv.outputs.new_version }}
- name: Create pull request
id: cpr
uses: octokit/[email protected]
with:
route: POST /repos/${{ github.repository }}/pulls
title: Release v${{ env.NEW_VERSION }}
body: Bump to version v${{ env.NEW_VERSION }}.
base: master
head: ${{ env.RELEASE_BRANCH }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_BRANCH: ${{ steps.crb.outputs.release_branch }}
NEW_VERSION: ${{ steps.bv.outputs.new_version }}
- name: Merge pull request
uses: octokit/[email protected]
with:
route: PUT /repos/${{ github.repository }}/pulls/${{ env.PULL_NUMBER }}/merge
commit_title: Prepare release v${{ env.NEW_VERSION }} (#${{ env.PULL_NUMBER }})
merge_method: squash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_NUMBER: ${{ fromJson(steps.cpr.outputs.data).number }}
NEW_VERSION: ${{ steps.bv.outputs.new_version }}

create_release:
needs: [bump_version]
env:
NEW_VERSION: ${{ needs.bump_version.outputs.new_version }}
ARTIFACT_NAME: ${{ needs.build.outputs.artifact_name }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
ref: master
- name: Get changelog
id: gcb
run: |
changelog_body=`scripts/get_changelog.py`
echo "changelog_body=${changelog_body}" >> $GITHUB_OUTPUT
- name: Publish release
id: crd
uses: octokit/[email protected]
with:
route: POST /repos/${{ github.repository }}/releases
tag_name: v${{ env.NEW_VERSION }}
target_commitish: master
name: v${{ env.NEW_VERSION }}
body: |-
${{ steps.gcb.outputs.changelog_body }}
draft: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47 changes: 47 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Test

on:
push:
branches: [ master ]
paths-ignore:
- '**.md'
- 'scripts/**'
- '.gitignore'
- '.github/**'
- '!.github/workflows/test.yml'
pull_request:
branches: [ master ]
paths-ignore:
- '**.md'
- 'scripts/**'
- '.gitignore'
- '.github/**'
- '!.github/workflows/test.yml'

env:
CARGO_TERM_COLOR: always
RUST_VERSION: 1.66.0

jobs:
test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_VERSION }}
default: true
components: clippy
- name: Cache Rust
uses: Swatinem/rust-cache@v2
- name: Lint
uses: actions-rs/cargo@v1
with:
command: clippy
args: --verbose --release -- -D warnings
- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --release
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Initial release of game-box.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[package]
name = "game-box"
version = "0.0.1"
version = "0.0.0"
edition = "2021"
Binary file added scripts/__pycache__/get_version.cpython-310.pyc
Binary file not shown.
Binary file added scripts/__pycache__/util.cpython-310.pyc
Binary file not shown.
107 changes: 107 additions & 0 deletions scripts/bumb_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env python3

from get_version import get_version as get_current_version
from util import error
import datetime
import os
import subprocess
import sys


SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, ".."))


def run(*cmd):
output = subprocess.run(cmd, capture_output=True)
return output.stdout.decode("utf-8").strip(), output.stderr.decode("utf-8").strip()


def get_next_version(bump_comp_idx, current_version):
components = current_version.split(".")

all_digits = lambda c: all(map(str.isdigit, c))
is_empty = lambda c: len(c) == 0
is_int = lambda c: not is_empty(c) and all_digits(c)

has_three_components = len(components) == 3
all_components_are_ints = all(map(is_int, components))

if not (has_three_components and all_components_are_ints):
error(f'"{version}" version number invalid')

components[bump_comp_idx] = int(components[bump_comp_idx]) + 1
[major, minor, patch] = [*components[:bump_comp_idx+1], 0, 0, 0][:3]

return f"{major}.{minor}.{patch}"


def update_manifest(bump_comp_idx):
manifest_path = os.path.join(REPO_DIR, "Cargo.toml")
with open(manifest_path, "r") as f:
content = f.read()

current_version = get_current_version(content)
next_version = get_next_version(bump_comp_idx, current_version)
content = content.replace(
f'version = "{current_version}"',
f'version = "{next_version}"')

with open(manifest_path, "w") as f:
f.write(content)

return next_version


def update_changelog(next_version):
HEADER_KEY = "## [Unreleased]"
CHANGELOG_NAME = "CHANGELOG.md"

changelog_path = os.path.join(REPO_DIR, CHANGELOG_NAME)
last_version, _ = run("git", "-C", REPO_DIR, "rev-list", "--date-order", "--tags", "--max-count=1")
stdout, stderr = run("git", "-C", REPO_DIR, "diff", last_version, "HEAD", "--", CHANGELOG_NAME)

if len(stderr) > 0:
error(stderr.strip())
if len(stdout) == 0:
error("no changes have been made to the changelog")

with open(changelog_path, "r") as f:
content = f.read()

current_date = datetime.datetime.now(datetime.timezone.utc)
formatted_date = current_date.strftime("%Y-%m-%d")
replacement = f"## [{next_version}] - {formatted_date}"
new_content = content.replace(HEADER_KEY, replacement, 1)

if content == new_content:
error("no unreleased version section found")
if new_content != new_content.replace(HEADER_KEY, replacement):
error("multiple unreleased version sections found")

new_content = new_content.replace(replacement, f"{HEADER_KEY}\n\n{replacement}")
with open(changelog_path, "w") as f:
f.write(new_content)


def bump_version(bump_comp_idx):
next_version = update_manifest(bump_comp_idx)
update_changelog(next_version)
return next_version


if __name__ == "__main__":
if len(sys.argv) < 2:
error("component argument missing")

component = sys.argv[1]
if component == "major":
bump_comp_idx = 0
elif component == "minor":
bump_comp_idx = 1
elif component == "patch":
bump_comp_idx = 2
else:
error(f'"major", "minor" or "patch" expected')

print(bump_version(bump_comp_idx))
39 changes: 39 additions & 0 deletions scripts/get_changelog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3

from get_version import get_version
from util import error
import json
import os
import sys


SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, ".."))


def get_changelog_body():
manifest_path = os.path.join(REPO_DIR, "CHANGELOG.md")
with open(manifest_path, "r") as f:
content = f.read()

version = get_version()
version_line = f"## [{version}]"
version_split= content.split(version_line)

if len(version_split) < 2:
error("version changelog section found")
if len(version_split) > 2:
error("multiple version changelog sections found")

title_suffix_with_body_split = version_split[1].split("## [", 1)
body_split = title_suffix_with_body_split[0].split("\n", 1)

if len(body_split) == 1:
error("invalid changelog format")

stripped_body = body_split[1].strip()
return json.dumps(stripped_body)


if __name__ == "__main__":
print(get_changelog_body())
52 changes: 52 additions & 0 deletions scripts/get_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python3

import os
from util import error


SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
REPO_DIR = os.path.realpath(os.path.join(SCRIPT_DIR, ".."))


def split(content, sep, desc=None):
parts = content.split(sep, 1)
if len(parts) == 1:
if desc is not None:
error(desc)
else:
error(f'"{sep}" separator not found')
return parts


def get_version(content = None):
HEADER_KEY = "[package]"
VERSION_KEY = "version"
EQUALS = "="
NEW_LINE = "\n"

if content is None:
manifest_path = os.path.join(REPO_DIR, "Cargo.toml")
with open(manifest_path, "r") as f:
content = f.read()

[parsed, content] = split(content, HEADER_KEY)
parsed += HEADER_KEY
while len(content) > 0:
[line, content] = split(content, NEW_LINE)

if len(line.strip()) == 0:
parsed += line + NEW_LINE
continue

[key, line] = split(line, EQUALS, f'"{VERSION_KEY}" key not found')
parsed += key + EQUALS

if key.strip() != VERSION_KEY:
parsed += line + NEW_LINE
continue

return line.strip().strip('"')


if __name__ == "__main__":
print(get_version())
10 changes: 10 additions & 0 deletions scripts/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import sys


def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)


def error(msg):
eprint("error:", msg)
sys.exit(1)

0 comments on commit e789acf

Please sign in to comment.