diff --git a/README.md b/README.md index 6418962..b91b199 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -**tip** is a Docker GitHub Action written in Python. **tip** allows to keep a pre-release and its artifacts up to date with latest builds. Combined with a workflow that is executed periodically, **tip** allows to provide a fixed release name for users willing to use daily/nightly artifacts of a project. +**tip** is a Docker GitHub Action written in Python. + +**tip** allows to keep a GitHub Release of type pre-release and its artifacts up to date with latest builds. Combined with a workflow that is executed periodically, **tip** allows to provide a fixed release name for users willing to use daily/nightly artifacts of a project. + +Furthermore, when any [semver](https://semver.org) compilant tagged commit is pushed, **tip** can create a release and upload assets. # Usage @@ -35,11 +39,9 @@ jobs: README.md ``` -Note that the tag and the pre-release need to be created manually the first time. The workflow above will fail if the release does not exist. - # Options -All options can be optionally provided as environment variables: `INPUT_TOKEN`, `INPUT_FILES`, `INPUT_TAG` and/or `INPUT_RM`. +All options can be optionally provided as environment variables: `INPUT_TOKEN`, `INPUT_FILES`, `INPUT_TAG`, `INPUT_RM` and/or `INPUT_SNAPSHOTS`. ## token (required) @@ -56,3 +58,7 @@ The default tag name for the tip/nightly pre-release is `tip`, but it can be opt ## rm Set option `rm` to `true` for systematically removing previous artifacts (e.g. old versions). Otherwise (by default), all previours artifacts are preserved or overwritten. + +## snapshots + +Whether to create releases from any tag or to treat some as snapshots. By default, all the tags with non-empty `prerelease` field (see [semver.org: Is there a suggested regular expression (RegEx) to check a SemVer string?](https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string)) are considered snapshots; neither a release is created nor assets are uploaded. diff --git a/action.yml b/action.yml index 014aa7e..07729a0 100644 --- a/action.yml +++ b/action.yml @@ -15,6 +15,10 @@ inputs: description: 'Whether to delete all the previous artifacts, or only replacing the ones with the same name' required: false default: false + snapshots: + description: 'Whether to create releases from any tag or to treat some as snapshots' + required: false + default: true runs: using: 'docker' image: 'Dockerfile' diff --git a/tip.py b/tip.py index 62a2451..a31ac7e 100755 --- a/tip.py +++ b/tip.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 -from os import environ, getenv +import re +import sys from sys import argv, stdout +from os import environ, getenv from subprocess import check_call from glob import glob from pathlib import Path @@ -55,14 +57,45 @@ print("· Get Release handler") tag = getenv('INPUT_TAG', 'tip') +env_tag = None +gh_ref = environ['GITHUB_REF'] +is_prerelease = True +is_draft = False + +if gh_ref[0:10] == 'refs/tags/': + env_tag = gh_ref[10:] + if env_tag != tag: + semver = re.search(r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", env_tag) + if semver.group('prerelease') is None: + # is a regular semver compilant tag + is_prerelease = False + tag = env_tag + elif getenv('INPUT_SNAPSHOTS', 'true') == 'true': + # is semver compilant prerelease tag, thus a snapshot (we skip it) + sys.exit() + +gh_tag = None try: gh_tag = gh_repo.get_git_ref('tags/%s' % tag) except Exception as e: stdout.flush() - # TODO: create the tag/release, instead of raising an exception - raise(Exception("Tag '%s' does not exist!" % tag)) - -gh_release = gh_repo.get_release(tag) + pass +if gh_tag: + try: + gh_release = gh_repo.get_release(tag) + except Exception as e: + gh_release = gh_repo.create_git_release(tag, tag, "", draft=True, prerelease=is_prerelease) + is_draft = True + pass +else: + err_msg = "Tag/release '%s' does not exist and could not create it!" % tag + if 'GITHUB_SHA' not in environ: + raise(Exception(err_msg)) + try: + gh_release = gh_repo.create_git_tag_and_release(tag, "", tag, "", environ['GITHUB_SHA'], 'commit', draft=True, prerelease=is_prerelease) + is_draft = True + except Exception as e: + raise(Exception(err_msg)) print("· Upload artifacts") @@ -99,17 +132,19 @@ for artifact in artifacts: stdout.flush() print("· Update Release reference (force-push tag)") -if ('GITHUB_SHA' in environ) and ('GITHUB_REF' in environ) and environ['GITHUB_REF'] != 'refs/tags/%s' % tag: - sha = environ['GITHUB_SHA'] - print("force-push '%s' to %s" % (tag, sha)) - gh_repo.get_git_ref('tags/%s' % tag).edit(sha) +if is_draft: + # Unfortunately, it seems not possible to update fields 'created_at' or 'published_at'. + print(" > Update (pre-)release") + gh_release.update_release( + gh_release.title, + "" if gh_release.body is None else gh_release.body, + draft=False, + prerelease=is_prerelease, + tag_name=gh_release.tag_name, + target_commitish=gh_release.target_commitish + ) - # TODO: alternatively, update the title/body of the release (while keeping the tag or not) - # gh_release.update_release( - # gh_release.title, - # gh_release.body, - # draft=False, - # prerelease=True, - # tag_name=gh_release.tag_name, - # target_commitish=gh_release.target_commitish - # ) +if ('GITHUB_SHA' in environ) and (env_tag is None): + sha = environ['GITHUB_SHA'] + print(" > Force-push '%s' to %s" % (tag, sha)) + gh_repo.get_git_ref('tags/%s' % tag).edit(sha)