diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 7f5def3..281d245 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: status: "Started" init: true build-images: + needs: [pre-run] runs-on: ubuntu-latest strategy: matrix: @@ -27,10 +28,10 @@ jobs: - name: Set image metadata id: image-metadata run: | - echo "image-tag=$(./script/get-tag.sh)" >> $GITHUB_OUTPUT - echo "full-image-name=${{ matrix.image-name }}:$(./script/get-tag.sh)" >> $GITHUB_OUTPUT + echo "image-tag=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + echo "full-image-name=${{ matrix.image-name }}:$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - name: Build image - run: ./script/build-image.sh ${{ matrix.image-name }} ${{ steps.image-metadata.outputs.image-tag }} + run: python ./build_image.py ${{ steps.image-metadata.full-image-name }} ./images/${{ matrix.image-name }}/Dockerfile - name: Tag image as latest run: podman tag ${{ steps.image-metadata.outputs.full-image-name }} ${{ matrix.image-name }}:latest - name: List images diff --git a/build_image.py b/build_image.py new file mode 100644 index 0000000..bb5b434 --- /dev/null +++ b/build_image.py @@ -0,0 +1,94 @@ +""" +Builds a container image with the provided image name and tag. + +Usage: + python build_image.py [] +""" + +import subprocess +import pathlib +import logging +import typing +import sys +import os +import re + +logger = logging.getLogger("build-image") + +def get_tag(is_ci: bool) -> str: + """ + Gets an image tag composed of the short sha of the current commit + and, depending on the is_ci flag, a "-dev" suffix. + """ + + result = subprocess.run( + "git rev-parse --short HEAD", shell=True, capture_output=True, check=True + ) + + sha = re.sub(r"\n", "", str(result.stdout.decode('utf-8'))) + + if not is_ci: + return f"{sha}-dev" + + return sha + + +def build_image(image_name: str, tag: str, image_path: typing.Optional[pathlib.Path]): + """ + Calls Podman to build the container image defined at image_path, which defaults to + the current directory. + + The built image is named and tagged using image_name and tag. + """ + + if image_path is None: + image_path = pathlib.Path("./Dockerfile") + + cwd = image_path.parent + image_path = image_path.relative_to(cwd) + + subprocess.run( + f"podman build -t {image_name}:{tag} -f {str(image_path)}", + shell=True, + check=True, + cwd=cwd, + ) + + +def run(args: list[str]): + """ + CLI entrypoint. + """ + + if len(args) < 1: + raise ValueError( + "There should be at least one argument. " + "Correct usage: python build_image.py [image-path]" + ) + + if len(args) > 2: + raise ValueError( + "Unrecognized arguments. " + "Correct usage: python build_image.py [image-path]" + ) + + tagged_image_name = args[0] + image_name_parts = tagged_image_name.split(":") + + name = image_name_parts[0] + tag = ( + image_name_parts[1] + if len(image_name_parts) == 2 + else get_tag(bool(os.environ.get("CI", False))) + ) + + image_path = args[1] if len(args) == 2 else None + + build_image(name, tag, pathlib.Path(image_path)) + + +if __name__ == "__main__": + try: + run(sys.argv[1:]) + except Exception as e: # pylint: disable=broad-exception-caught + logger.error(e) diff --git a/script/build-image.sh b/script/build-image.sh deleted file mode 100755 index e8c3f72..0000000 --- a/script/build-image.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -image_name=$1 -image_tag=$2 - -if [[ -z $image_name ]]; then - echo "An image name must be provided." - exit 1 -fi - -if [[ -z $image_tag ]]; then - echo "An image tag must be provided." - exit 1 -fi - -( - cd "images/$image_name" - podman build -t "$image_name:$image_tag" -f ./Dockerfile -) || exit 1 diff --git a/script/get-tag.sh b/script/get-tag.sh deleted file mode 100755 index a949293..0000000 --- a/script/get-tag.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -has_changes=$(git status --short) -head_sha=$(git rev-parse --short HEAD) - -tag=$head_sha - -if [[ -n $has_changes ]]; then - tag="$tag-dev" -fi - -echo "$tag"