From e38d9d8bff1dc51aedbfbf933449a7c74f142205 Mon Sep 17 00:00:00 2001 From: Mark Joshwel Date: Mon, 4 Sep 2023 15:47:07 +0000 Subject: [PATCH] s+,releaser,ci(build): implement #20 s+: add new constants and change version print meta: add releaser.py ci(build): seperate auto and manual + use releaser --- .github/workflows/publish-slsa3-auto.yml | 60 +++++++++++++ ...ish-slsa3.yml => publish-slsa3-manual.yml} | 13 +-- releaser.py | 84 +++++++++++++++++++ surplus/surplus.py | 19 ++++- 4 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/publish-slsa3-auto.yml rename .github/workflows/{publish-slsa3.yml => publish-slsa3-manual.yml} (85%) create mode 100644 releaser.py diff --git a/.github/workflows/publish-slsa3-auto.yml b/.github/workflows/publish-slsa3-auto.yml new file mode 100644 index 0000000..a63c920 --- /dev/null +++ b/.github/workflows/publish-slsa3-auto.yml @@ -0,0 +1,60 @@ +name: automated tagged release with slsa 3 compliance + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + permissions: + contents: write + outputs: + hashes: ${{ steps.hash.outputs.hashes }} + + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: install devbox + uses: jetpack-io/devbox-install-action@v0.3.0 + + - name: install dependencies + run: devbox run poetry install + + - name: run releaser.py + run: devbox run python releaser.py + + - name: build project + id: build + run: devbox run poetry build + + - name: duplicate non-versioned wheel + run: cp dist/surplus-*.whl dist/surplus-latest-py3-none-any.whl + + - name: generate provenance subjects + id: hash + run: | + cd dist + HASHES=$(sha256sum * | base64 -w0) + echo "hashes=$HASHES" >> "$GITHUB_OUTPUT" + + - name: release + uses: softprops/action-gh-release@v0.1.15 + if: startsWith(github.ref, 'refs/tags/') + with: + files: | + dist/*.whl + + provenance: + needs: [build] + permissions: + actions: read + id-token: write + contents: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.6.0 + with: + base64-subjects: "${{ needs.build.outputs.hashes }}" + upload-assets: true diff --git a/.github/workflows/publish-slsa3.yml b/.github/workflows/publish-slsa3-manual.yml similarity index 85% rename from .github/workflows/publish-slsa3.yml rename to .github/workflows/publish-slsa3-manual.yml index b77021f..4d34c54 100644 --- a/.github/workflows/publish-slsa3.yml +++ b/.github/workflows/publish-slsa3-manual.yml @@ -1,9 +1,7 @@ -name: release with slsa 3 compliance +name: manual release with slsa 3 compliance on: - push: - tags: - - '*' + workflow_dispatch: jobs: build: @@ -17,13 +15,16 @@ jobs: - name: checkout uses: actions/checkout@v3 - - name: install devbox + - name: install devbox uses: jetpack-io/devbox-install-action@v0.3.0 - name: install dependencies run: devbox run poetry install - - name: install dependencies + - name: run releaser.py + run: devbox run python releaser.py + + - name: build project id: build run: devbox run poetry build diff --git a/releaser.py b/releaser.py new file mode 100644 index 0000000..e25c151 --- /dev/null +++ b/releaser.py @@ -0,0 +1,84 @@ +""" +surplus: Google Maps Plus Code to iOS Shortcuts-like shareable text +------------------------------------------------------------------- +by mark + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" + +from datetime import datetime, timedelta, timezone +from pathlib import Path +from subprocess import run + +# NOTE: change this if surplus has moved +path_surplus = Path(__file__).parent.joinpath("./surplus/surplus.py") + +build_time = datetime.now(timezone(timedelta(hours=8))) # using SGT +insert_build_branch: str = run( + "git rev-parse --abbrev-ref HEAD", capture_output=True, text=True, shell=True +).stdout.strip("\n") +insert_build_commit: str = run( + "git rev-parse HEAD", capture_output=True, text=True, shell=True +).stdout.strip("\n") +insert_build_datetime: str = repr(build_time).replace("datetime.", "") + +# NOTE: change this if the respective lines in surplus.py have changed +targets: list[tuple[str, str]] = [ + ( + 'VERSION_SUFFIX: Final[str] = "-local"', + 'VERSION_SUFFIX: Final[str] = ""', + ), + ( + 'BUILD_BRANCH: Final[str] = "future"', + f'BUILD_BRANCH: Final[str] = "{insert_build_branch}"', + ), + ( + 'BUILD_COMMIT: Final[str] = "latest"', + f'BUILD_COMMIT: Final[str] = "{insert_build_commit}"', + ), + ( + "BUILD_DATETIME: Final[datetime] = datetime.now(timezone(timedelta(hours=8))) # using SGT", + f"BUILD_DATETIME: Final[datetime] = {insert_build_datetime}", + ), +] + + +def main() -> int: + assert path_surplus.is_file() and path_surplus.exists(), f"{path_surplus} not found" + + source_surplus: str = path_surplus.read_text(encoding="utf-8") + + for old, new in targets: + print(f"new: {new}\nold: {old}\n") + source_surplus = source_surplus.replace(old, new) + + path_surplus.write_text(source_surplus, encoding="utf-8") + + return 0 + + +if __name__ == "__main__": + exit(main()) diff --git a/surplus/surplus.py b/surplus/surplus.py index 3fc3a20..e2db26c 100644 --- a/surplus/surplus.py +++ b/surplus/surplus.py @@ -31,6 +31,7 @@ For more information, please refer to from argparse import ArgumentParser from collections import OrderedDict +from datetime import datetime, timedelta, timezone from enum import Enum from sys import stderr, stdout from typing import ( @@ -56,7 +57,11 @@ from pluscodes.openlocationcode import ( # type: ignore # isort: skip # constants -VERSION: Final[tuple[int, int, int]] = (2, 0, 0) +VERSION: Final[tuple[int, int, int]] = (2, 1, 0) +VERSION_SUFFIX: Final[str] = "-local" +BUILD_BRANCH: Final[str] = "future" +BUILD_COMMIT: Final[str] = "latest" +BUILD_DATETIME: Final[datetime] = datetime.now(timezone(timedelta(hours=8))) # using SGT USER_AGENT: Final[str] = "surplus" SHAREABLE_TEXT_LINE_0_KEYS: Final[tuple[str, ...]] = ( "emergency", @@ -1062,8 +1067,16 @@ def cli() -> int: behaviour = handle_args() print( - f"surplus version {'.'.join([str(v) for v in VERSION])}" - + (f", debug mode" if behaviour.debug else ""), + f"surplus version {'.'.join([str(v) for v in VERSION])}{VERSION_SUFFIX}" + + (f", debug mode" if behaviour.debug else "") + + ( + ( + f" ({BUILD_COMMIT[:10]}@{BUILD_BRANCH}, " + f'{BUILD_DATETIME.strftime("%a %d %b %Y %H:%M:%S %z")})' + ) + if behaviour.debug or behaviour.version_header + else "" + ), file=behaviour.stdout if behaviour.version_header else behaviour.stderr, )