diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..72711dc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,67 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + +env: + POETRY_VERSION: 1.7.1 + GHCR_IMAGE_REPOSITORY: ghcr.io/${{ github.repository_owner }}/poetry + PLATFORMS: linux/amd64,linux/arm64/v8 + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python: + - "3.8" + - "3.9" + - "3.10" + - "3.11" + - "3.12" + variant: + - bookworm + - slim + steps: + - uses: actions/checkout@v4.1.1 + - name: Build Docker Image + uses: docker/build-push-action@v5.1.0 + with: + context: . + push: false + tags: test-image + target: test + build-args: POETRY_VERSION=${{ env.POETRY_VERSION }} + - name: Run Tests in Docker + run: | + docker run --rm \ + -e POETRY_VERSION=${{ env.POETRY_VERSION }} \ + test-image python3 /usr/src/app/tests.py + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up multiplatform builds + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ env.PLATFORMS }} + - name: Set up buildx + uses: docker/setup-buildx-action@v3 + - name: Build and Push Docker Image + uses: docker/build-push-action@v5.1.0 + with: + context: . + push: true + tags: ${{ env.GHCR_IMAGE_REPOSITORY }}:${{ github.sha }}-${{ matrix.python }}-${{ matrix.variant }} + platforms: ${{ env.PLATFORMS }} + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + POETRY_VERSION=${{ env.POETRY_VERSION }} + PYTHON_VERSION=${{ matrix.python }} + VARIANT=${{ matrix.variant }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 61afe3c..68bc801 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,11 +7,10 @@ on: env: POETRY_VERSION: 1.7.1 GHCR_IMAGE_REPOSITORY: ghcr.io/${{ github.repository_owner }}/poetry - PLATFORMS: linux/amd64,linux/arm64/v8 jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: matrix: python: @@ -29,58 +28,40 @@ jobs: - variant: bookworm is_default_variant: true steps: - - uses: actions/checkout@v3 - - uses: docker/setup-qemu-action@v2 - with: - platforms: ${{ env.PLATFORMS }} - - uses: docker/setup-buildx-action@v2 - - uses: docker/login-action@v2 + - uses: actions/checkout@v4.1.1 + - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Set image tags in env + run: | + TAG_SUFFIX="${{ matrix.python }}-${{ matrix.variant }}" + echo "GIT_SHA_TAG=${{ env.GHCR_IMAGE_REPOSITORY }}:${{ github.sha }}-${TAG_SUFFIX}" >> $GITHUB_ENV + echo "BASE_RELEASE_TAG=${{ env.GHCR_IMAGE_REPOSITORY }}:${{ env.POETRY_VERSION }}" >> $GITHUB_ENV - name: "Python + Variant: ${{ env.POETRY_VERSION }}-python-${{ matrix.python }}-${{ matrix.variant }}" - uses: docker/build-push-action@v3.1.0 - with: - push: true - tags: ${{ env.GHCR_IMAGE_REPOSITORY }}:${{ env.POETRY_VERSION }}-python-${{ matrix.python }}-${{ matrix.variant }} - cache-from: type=gha - cache-to: type=gha,mode=max - platforms: ${{ env.PLATFORMS }} - build-args: | - POETRY_VERSION=${{ env.POETRY_VERSION }} - PYTHON_VERSION=${{ matrix.python }} - VARIANT=${{ matrix.variant }} + run: | + RELEASE_TAG="${BASE_RELEASE_TAG}-python-${{ matrix.python }}-${{ matrix.variant }}" + docker pull $GIT_SHA_TAG + docker tag $GIT_SHA_TAG $RELEASE_TAG + docker push $RELEASE_TAG - name: "Python + Default Variant: ${{ env.POETRY_VERSION }}-python-${{ matrix.python }}" - uses: docker/build-push-action@v3.1.0 if: matrix.is_default_variant - with: - push: true - tags: ${{ env.GHCR_IMAGE_REPOSITORY }}:${{ env.POETRY_VERSION }}-python-${{ matrix.python }} - platforms: ${{ env.PLATFORMS }} - build-args: | - POETRY_VERSION=${{ env.POETRY_VERSION }} - PYTHON_VERSION=${{ matrix.python }} - VARIANT=${{ matrix.variant }} + run: | + RELEASE_TAG="${BASE_RELEASE_TAG}-python-${{ matrix.python }} + docker pull $GIT_SHA_TAG + docker tag $GIT_SHA_TAG $RELEASE_TAG + docker push $RELEASE_TAG - name: "Default Python + Variant: ${{ env.POETRY_VERSION }}-${{ matrix.variant }}" - uses: docker/build-push-action@v3.1.0 if: matrix.is_default_python - with: - push: true - tags: ${{ env.GHCR_IMAGE_REPOSITORY }}:${{ env.POETRY_VERSION }}-${{ matrix.variant }} - platforms: ${{ env.PLATFORMS }} - build-args: | - POETRY_VERSION=${{ env.POETRY_VERSION }} - PYTHON_VERSION=${{ matrix.python }} - VARIANT=${{ matrix.variant }} + run: | + RELEASE_TAG="${BASE_RELEASE_TAG}-${{ matrix.variant }}" + docker pull $GIT_SHA_TAG + docker tag $GIT_SHA_TAG $RELEASE_TAG + docker push $RELEASE_TAG - name: "Default Python + Default Variant: ${{ env.POETRY_VERSION }}" - uses: docker/build-push-action@v3.1.0 if: matrix.is_default_python && matrix.is_default_variant - with: - push: true - tags: ${{ env.GHCR_IMAGE_REPOSITORY }}:${{ env.POETRY_VERSION }} - platforms: ${{ env.PLATFORMS }} - build-args: | - POETRY_VERSION=${{ env.POETRY_VERSION }} - PYTHON_VERSION=${{ matrix.python }} - VARIANT=${{ matrix.variant }} + run: | + docker pull $GIT_SHA_TAG + docker tag $GIT_SHA_TAG $BASE_RELEASE_TAG + docker push $BASE_RELEASE_TAG diff --git a/Dockerfile b/Dockerfile index bfa0ea7..28a4985 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ ARG PYTHON_VERSION=3.12 ARG VARIANT=bookworm -FROM python:${PYTHON_VERSION}-${VARIANT} +FROM python:${PYTHON_VERSION}-${VARIANT} as base ENV PYTHONUNBUFFERED=1 @@ -16,4 +16,8 @@ RUN python3 -m venv ${POETRY_HOME} &&\ ${POETRY_HOME}/bin/pip install poetry==${POETRY_VERSION} &&\ poetry config virtualenvs.create false +FROM base as test +COPY ./tests/tests.py /usr/src/app/tests.py + +FROM base WORKDIR /usr/src/app diff --git a/tests/tests.py b/tests/tests.py new file mode 100644 index 0000000..32a4aa3 --- /dev/null +++ b/tests/tests.py @@ -0,0 +1,49 @@ +import os +import re +import subprocess +import unittest + + +class TestPoetrySetup(unittest.TestCase): + def test_poetry_binary_available(self): + """ + Test if Poetry binary is available. + """ + + result = subprocess.run(["which", "poetry"], capture_output=True, text=True) + self.assertEqual(result.returncode, 0, "Poetry binary is not available in PATH") + + def test_poetry_version(self): + """ + Test if the installed Poetry version is correct. + """ + + expected_version = os.environ.get("POETRY_VERSION") + result = subprocess.run(["poetry", "--version"], capture_output=True, text=True) + self.assertEqual(result.returncode, 0, "Error executing Poetry") + version_match = re.search(r"Poetry \(version (\S+)\)", result.stdout) + self.assertIsNotNone(version_match, "Unable to parse Poetry version") + self.assertEqual( + version_match.group(1), + expected_version, + f"Expected Poetry version {expected_version}, got {version_match.group(1)}", + ) + + def test_poetry_without_virtualenvs(self): + """ + Test if Poetry is configured to work without virtual environments. + """ + + result = subprocess.run( + ["poetry", "config", "virtualenvs.create"], capture_output=True, text=True + ) + self.assertEqual(result.returncode, 0, "Error executing Poetry config command") + self.assertEqual( + result.stdout.strip(), + "false", + "Poetry is not configured to work without virtual environments", + ) + + +if __name__ == "__main__": + unittest.main()