Merge pull request #1602 from pypeclub/feature/continuous-integration-github-workflow

This commit is contained in:
Milan Kolar 2021-06-03 17:04:34 +02:00 committed by GitHub
commit b50d00f606
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 356 additions and 0 deletions

23
.github/workflows/nightly_merge.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: Nightly Merge
on:
schedule:
- cron: '21 3 * * 3,6'
workflow_dispatch:
jobs:
develop-to-main:
runs-on: ubuntu-latest
steps:
- name: 🚛 Checkout Code
uses: actions/checkout@v2
- name: Merge development -> main
uses: devmasx/merge-branch@v1.3.1
with:
type: now
from_branch: develop
target_branch: main
github_token: ${{ secrets.TOKEN }}

93
.github/workflows/prerelease.yml vendored Normal file
View file

@ -0,0 +1,93 @@
name: Nightly Prerelease
on:
push:
branches: [main]
jobs:
create_nightly:
runs-on: ubuntu-latest
steps:
- name: 🚛 Checkout Code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Python requirements
run: pip install gitpython semver
- name: 🔎 Determine next version type
id: version_type
run: |
TYPE=$(python ./tools/ci_tools.py --bump)
echo ::set-output name=type::$TYPE
- name: 💉 Inject new version into files
id: version
if: steps.version_type.outputs.type != 'skip'
run: |
RESULT=$(python ./tools/ci_tools.py --nightly)
echo ::set-output name=next_tag::$RESULT
- name: "✏️ Generate full changelog"
if: steps.version_type.outputs.type != 'skip'
id: generate-full-changelog
uses: heinrichreimer/github-changelog-generator-action@v2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
breakingLabel: '#### 💥 Breaking'
enhancementLabel: '#### 🚀 Enhancements'
bugsLabel: '#### 🐛 Bug fixes'
deprecatedLabel: '#### ⚠️ Deprecations'
addSections: '{"documentation":{"prefix":"### 📖 Documentation","labels":["documentation"]},"tests":{"prefix":"### ✅ Testing","labels":["tests"]}}'
issues: false
issuesWoLabels: false
pullRequests: true
prWoLabels: false
author: false
unreleased: true
compareLink: true
stripGeneratorNotice: true
verbose: true
unreleasedLabel: ${{ steps.version.outputs.next_tag }}
excludeTagsRegex: "CI/.+"
releaseBranch: "main"
- name: "🖨️ Print changelog to console"
if: steps.version_type.outputs.type != 'skip'
run: cat CHANGELOG.md
- name: 💾 Commit and Tag
id: git_commit
if: steps.version_type.outputs.type != 'skip'
run: |
git config user.email ${{ secrets.CI_EMAIL }}
git config user.name ${{ secrets.CI_USER }}
cd repos/avalon-core
git checkout main
git pull
cd ../..
git add .
git commit -m "[Automated] Bump version"
tag_name="CI/${{ steps.version.outputs.next_tag }}"
git tag -a $tag_name -m "nightly build"
git push
git push origin $tag_name
- name: 🔨 Merge main back to develop
uses: everlytic/branch-merge@1.1.0
if: steps.version_type.outputs.type != 'skip'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
source_ref: 'main'
target_branch: 'develop'
commit_message_template: '[Automated] Merged {source_ref} into {target_branch}'

99
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,99 @@
name: Stable Release
on:
push:
tags:
- '*[0-9].*[0-9].*[0-9]*'
jobs:
create_release:
runs-on: ubuntu-latest
steps:
- name: 🚛 Checkout Code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Python requirements
run: pip install gitpython semver
- name: Set env
run: |
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
git config user.email ${{ secrets.CI_EMAIL }}
git config user.name ${{ secrets.CI_USER }}
git fetch
git checkout -b main origin/main
git tag -d ${GITHUB_REF#refs/*/}
git push origin --delete ${GITHUB_REF#refs/*/}
echo PREVIOUS_VERSION=`git describe --tags --match="[0-9]*" --abbrev=0` >> $GITHUB_ENV
- name: 💉 Inject new version into files
id: version
if: steps.version_type.outputs.type != 'skip'
run: |
python ./tools/ci_tools.py --version ${{ env.RELEASE_VERSION }}
- name: "✏️ Generate full changelog"
if: steps.version_type.outputs.type != 'skip'
id: generate-full-changelog
uses: heinrichreimer/github-changelog-generator-action@v2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
breakingLabel: '#### 💥 Breaking'
enhancementLabel: '#### 🚀 Enhancements'
bugsLabel: '#### 🐛 Bug fixes'
deprecatedLabel: '#### ⚠️ Deprecations'
addSections: '{"documentation":{"prefix":"### 📖 Documentation","labels":["documentation"]},"tests":{"prefix":"### ✅ Testing","labels":["tests"]}}'
issues: false
issuesWoLabels: false
pullRequests: true
prWoLabels: false
author: false
unreleased: true
compareLink: true
stripGeneratorNotice: true
verbose: true
futureRelease: ${{ env.RELEASE_VERSION }}
excludeTagsRegex: "CI/.+"
releaseBranch: "main"
- name: "🖨️ Print changelog to console"
run: echo ${{ steps.generate-last-changelog.outputs.changelog }}
- name: 💾 Commit and Tag
id: git_commit
if: steps.version_type.outputs.type != 'skip'
run: |
git add .
git commit -m "[Automated] Release"
tag_name="${{ env.RELEASE_VERSION }}"
git push
git tag -fa $tag_name -m "stable release"
git push origin $tag_name
- name: "🚀 Github Release"
uses: docker://antonyurchenko/git-release:latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DRAFT_RELEASE: "false"
PRE_RELEASE: "false"
CHANGELOG_FILE: "CHANGELOG.md"
ALLOW_EMPTY_CHANGELOG: "false"
ALLOW_TAG_PREFIX: "true"
- name: 🔨 Merge main back to develop
uses: everlytic/branch-merge@1.1.0
if: steps.version_type.outputs.type != 'skip'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
source_ref: 'main'
target_branch: 'develop'
commit_message_template: '[Automated] Merged release {source_ref} into {target_branch}'

View file

@ -51,6 +51,7 @@ flake8 = "^3.7"
autopep8 = "^1.4"
coverage = "*"
cx_freeze = "^6.6"
GitPython = "*"
jedi = "^0.13"
Jinja2 = "^2.11"
pycodestyle = "^2.5.0"

140
tools/ci_tools.py Normal file
View file

@ -0,0 +1,140 @@
import re
import sys
from semver import VersionInfo
from git import Repo
from optparse import OptionParser
def remove_prefix(text, prefix):
return text[text.startswith(prefix) and len(prefix):]
def get_last_version(match):
repo = Repo()
assert not repo.bare
version_types = {
"CI": "CI/[0-9]*",
"release": "[0-9]*"
}
tag = repo.git.describe(
'--tags',
f'--match={version_types[match]}',
'--abbrev=0'
)
if match == "CI":
return remove_prefix(tag, "CI/"), tag
else:
return tag, tag
def get_log_since_tag(version):
repo = Repo()
assert not repo.bare
return repo.git.log(f'{version}..HEAD', '--merges', '--oneline')
def release_type(log):
regex_minor = ["feature/", "(feat)"]
regex_patch = ["bugfix/", "fix/", "(fix)"]
for reg in regex_minor:
if re.search(reg, log):
return "minor"
for reg in regex_patch:
if re.search(reg, log):
return "patch"
return None
def file_regex_replace(filename, regex, version):
with open(filename, 'r+') as f:
text = f.read()
text = re.sub(regex, version, text)
# pp.pprint(f"NEW VERSION {version} INSERTED into {filename}")
f.seek(0)
f.write(text)
f.truncate()
def bump_file_versions(version):
filename = "./openpypeCItest/version.py"
regex = "(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-((0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?"
file_regex_replace(filename, regex, version)
# bump pyproject.toml
filename = "pyproject.toml"
regex = "version = \"(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-((0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?\" # OpenPype"
pyproject_version = f"version = \"{version}\" # OpenPype"
file_regex_replace(filename, regex, pyproject_version)
def calculate_next_nightly(token="nightly"):
last_prerelease, last_pre_tag = get_last_version("CI")
last_pre_v = VersionInfo.parse(last_prerelease)
last_pre_v_finalized = last_pre_v.finalize_version()
# print(last_pre_v_finalized)
last_release, last_release_tag = get_last_version("release")
last_release_v = VersionInfo.parse(last_release)
bump_type = release_type(get_log_since_tag(last_release))
if not bump_type:
return None
next_release_v = last_release_v.next_version(part=bump_type)
# print(next_release_v)
if next_release_v > last_pre_v_finalized:
next_tag = next_release_v.bump_prerelease(token=token).__str__()
return next_tag
elif next_release_v == last_pre_v_finalized:
next_tag = last_pre_v.bump_prerelease(token=token).__str__()
return next_tag
def main():
usage = "usage: %prog [options] arg"
parser = OptionParser(usage)
parser.add_option("-n", "--nightly",
dest="nightly", action="store_true",
help="Bump nightly version and return it")
parser.add_option("-b", "--bump",
dest="bump", action="store_true",
help="Return if there is something to bump")
parser.add_option("-v", "--version",
dest="version", action="store",
help="work with explicit version")
parser.add_option("-p", "--prerelease",
dest="prerelease", action="store",
help="define prerelease token")
(options, args) = parser.parse_args()
if options.bump:
last_CI, last_CI_tag = get_last_version("CI")
last_release, last_release_tag = get_last_version("release")
bump_type_CI = release_type(get_log_since_tag(last_CI_tag))
bump_type_release = release_type(get_log_since_tag(last_release_tag))
if bump_type_CI is None or bump_type_release is None:
print("skip")
if options.nightly:
next_tag_v = calculate_next_nightly()
print(next_tag_v)
bump_file_versions(next_tag_v)
if options.prerelease:
current_prerelease = VersionInfo.parse(options.prerelease)
new_prerelease = current_prerelease.bump_prerelease().__str__()
print(new_prerelease)
bump_file_versions(new_prerelease)
if options.version:
bump_file_versions(options.version)
print(f"Injected version {options.version} into the release")
if __name__ == "__main__":
main()