Skip to content

Commit

Permalink
fix(ci): resolve Docker image build errors
Browse files Browse the repository at this point in the history
  • Loading branch information
0x1026 committed Dec 5, 2024
1 parent ea7b144 commit 332647b
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 50 deletions.
37 changes: 27 additions & 10 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,41 +51,55 @@ jobs:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

changes:
name: 🔄 Detect changes
foundation:
name: 🌱 Foundation setup
runs-on: ubuntu-latest
if: github.event.action != 'closed'
permissions:
pull-requests: read
outputs:
images: ${{ github.event_name == 'push' && '["all"]' || steps.filter.outputs.changes }}
version: ${{ (startsWith(github.ref, 'refs/tags/v') && github.ref) || github.sha }}
version: ${{ steps.version.outputs.version }}
steps:
# https://github.com/actions/checkout/tree/11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

# https://github.com/dorny/paths-filter/tree/de90cc6fb38fc0963ad72b210f1f284cd68cea36
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
- name: 🔄 Detect changes
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
id: filter
with:
filters: .github/file-filters.yml

- name: 📝 Set version
id: version
shell: bash
run: |
ref=${{ github.ref }}
sha=${{ github.sha }}
if [[ $ref =~ ^refs/tags/v ]]; then
echo "version=${ref#refs/tags/}" >> "$GITHUB_OUTPUT"
else
echo "version=${sha}" >> "$GITHUB_OUTPUT"
fi
tests:
name: 🧪 Tests
needs: changes
needs: foundation
uses: ./.github/workflows/tests.yml
with:
images: ${{ needs.changes.outputs.images }}
images: ${{ needs.foundation.outputs.images }}
secrets: inherit

build:
name: 🐳 Docker
runs-on: ubuntu-latest
needs: [changes, tests]
needs: [foundation, tests]
strategy:
fail-fast: false
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#example-adding-configurations
matrix:
image: ${{ fromJSON(needs.changes.outputs.images) }}
image: ${{ fromJSON(needs.foundation.outputs.images) }}
exclude:
- image: all
include:
Expand All @@ -101,7 +115,7 @@ jobs:
# with sigstore/fulcio when running outside of PRs.
id-token: write
outputs:
version: ${{ needs.changes.outputs.version }}
version: ${{ needs.foundation.outputs.version }}

steps:
# https://github.com/actions/checkout/tree/11bd71901bbe5b1630ceea73d27597364c9af683
Expand Down Expand Up @@ -164,7 +178,7 @@ jobs:
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
with:
build-args: |
IMAGE_VERSION=${{ needs.changes.outputs.version }}
IMAGE_VERSION=${{ needs.foundation.outputs.version }}
context: ${{ matrix.context }}
push: ${{ github.event_name != 'pull_request' }}
target: final
Expand Down Expand Up @@ -205,6 +219,9 @@ jobs:
if: ${{ github.event_name != 'pull_request' }}

steps:
# https://github.com/actions/checkout/tree/11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

# https://github.com/getsentry/action-release/tree/e769183448303de84c5a06aaaddf9da7be26d6c7
# - name: Release to Sentry
- name: 📟 Release to Sentry
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
if: ${{ contains(inputs.images, 'all') || contains(fromJSON(inputs.images), 'urbantree') }}
defaults:
run:
shell: bash
working-directory: app
steps:
# https://github.com/actions/checkout/tree/11bd71901bbe5b1630ceea73d27597364c9af683
Expand Down Expand Up @@ -45,7 +46,6 @@ jobs:
working_dir: app

- name: 🧪 Run PHPUnit tests with coverage
shell: bash
run: ./vendor/bin/phpunit --log-junit junit.xml --coverage-clover=coverage.xml

# https://github.com/codecov/test-results-action/tree/9739113ad922ea0a9abb4b2c0f8bf6a4aa8ef820
Expand All @@ -69,6 +69,7 @@ jobs:
if: ${{ contains(inputs.images, 'all') || contains(fromJSON(inputs.images), 'api') }}
defaults:
run:
shell: bash
working-directory: api
steps:
# https://github.com/actions/checkout/tree/11bd71901bbe5b1630ceea73d27597364c9af683
Expand All @@ -87,11 +88,9 @@ jobs:
python-version: "3.13.0"

- name: 📦 Install Python dependencies
shell: bash
run: pip install -r requirements-dev.txt

- name: 🧪 Run Python tests with coverage
shell: bash
run: pytest tests --cov=./src --cov-report=xml --junitxml=junit.xml

# https://github.com/codecov/test-results-action/tree/9739113ad922ea0a9abb4b2c0f8bf6a4aa8ef820
Expand Down
32 changes: 16 additions & 16 deletions api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# syntax=docker/dockerfile:1

ARG IMAGE_VERSION
ARG PYTHON_VERSION=3.13.0

# Download dependencies as a separate step to take advantage of Docker's caching.
Expand All @@ -21,28 +20,34 @@ RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=bind,source=requirements-dev.txt,target=requirements-dev.txt \
python -m pip install -r requirements-dev.txt

FROM dev-deps AS development
ENV APP_ENV=development
FROM python:${PYTHON_VERSION}-slim AS base
ARG IMAGE_VERSION=dev
ENV IMAGE_VERSION=$IMAGE_VERSION
# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1
# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1
WORKDIR /app
# Copy the source code into the container.
COPY . .
# Expose the port that the application listens on.
EXPOSE 8000

FROM base AS development
ENV APP_ENV=development
COPY --from=dev-deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
WORKDIR /app
CMD ["python3", "-m", "uvicorn", "src.main:app", "--host=0.0.0.0", "--port=8000"]

FROM development AS test
ENV APP_ENV=test
WORKDIR /app
CMD ["pytest", "tests", "--cov=src"]
CMD ["python3", "-m", "pytest", "tests", "--cov=src"]

FROM prod-deps AS final
FROM base AS final
ENV APP_ENV=production
ENV IMAGE_VERSION=$IMAGE_VERSION
# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1
# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1
COPY --from=prod-deps /usr/local/lib/python3.13/site-packages /usr/local/lib/python3.13/site-packages
WORKDIR /app
# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
Expand All @@ -57,10 +62,5 @@ RUN adduser \
appuser
# Switch to the non-privileged user to run the application.
USER appuser
# Copy the source code into the container.
COPY . .
# Expose the port that the application listens on.
EXPOSE 8000
# Run the application.
CMD ["python3", "-m", "uvicorn", "src.main:app", "--host=0.0.0.0", "--port=8000"]
# CMD ["python", "src/main.py"]
7 changes: 3 additions & 4 deletions api/src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Settings(BaseSettings):
APP_PACKAGE: str = "api"
APP_ENV: str = "development"

IMAGE_VERSION: str | None = None
IMAGE_VERSION: str = "dev"

MARIADB_SERVER: str
MARIADB_PORT: int = 3306
Expand Down Expand Up @@ -66,9 +66,8 @@ def SQLALCHEMY_DATABASE_URI(self) -> MariaDBDsn:

@computed_field
@property
def SENTRY_RELEASE(self) -> str | None:
if self.IMAGE_VERSION:
return f"{self.APP_PACKAGE}@{self.IMAGE_VERSION}"
def SENTRY_RELEASE(self) -> str:
return f"{self.APP_PACKAGE}@{self.IMAGE_VERSION}"


# If the APP_ENV environment variable is not set to test, the settings object is created.
Expand Down
2 changes: 1 addition & 1 deletion api/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ def hello():

@app.get("/health")
def health_check():
return {"status": "healthy"}
return {"status": "healthy", "version": settings.SENTRY_RELEASE}
16 changes: 3 additions & 13 deletions api/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test_settings_defaults():
assert settings.APP_NAME is None
assert settings.APP_PACKAGE == "api"
assert settings.APP_ENV == "test"
assert settings.IMAGE_VERSION is None
assert settings.IMAGE_VERSION == "dev"
assert settings.MARIADB_SERVER == "localhost"
assert settings.MARIADB_PORT == 3306
assert settings.MARIADB_USER == "user"
Expand All @@ -26,7 +26,7 @@ def test_settings_defaults():
str(settings.SQLALCHEMY_DATABASE_URI)
== "mysql+pymysql://user:password@localhost:3306/test_db"
)
assert settings.SENTRY_RELEASE is None
assert settings.SENTRY_RELEASE == "api@dev"


def test_settings_missing_password():
Expand Down Expand Up @@ -102,7 +102,7 @@ def test_settings_with_custom_port():
)


def test_sentry_release_with_image_version():
def test_sentry_release_with_custom_image_version():
settings = Settings(
IMAGE_VERSION="1.0.0",
MARIADB_SERVER="localhost",
Expand All @@ -111,13 +111,3 @@ def test_sentry_release_with_image_version():
MARIADB_DB="test_db",
)
assert settings.SENTRY_RELEASE == "[email protected]"


def test_sentry_release_without_image_version():
settings = Settings(
MARIADB_SERVER="localhost",
MARIADB_USER="user",
MARIADB_PASSWORD="password",
MARIADB_DB="test_db",
)
assert settings.SENTRY_RELEASE is None
5 changes: 2 additions & 3 deletions app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# syntax=docker/dockerfile:1

ARG IMAGE_VERSION

#* Create a prod stage for installing app dependencies defined in Composer.
FROM composer:lts AS prod-deps
WORKDIR /app
Expand All @@ -20,6 +18,8 @@ RUN --mount=type=bind,source=./composer.json,target=composer.json \

#* Create a base stage for building the app image.
FROM php:8.4-apache AS base
ARG IMAGE_VERSION=dev
ENV IMAGE_VERSION=$IMAGE_VERSION
RUN docker-php-ext-install pdo pdo_mysql
RUN a2enmod rewrite
COPY ./src /var/www/html
Expand All @@ -46,7 +46,6 @@ CMD ["./vendor/bin/phpunit"]
#* Create a production stage.
FROM base AS final
ENV APP_ENV=production
ENV IMAGE_VERSION=$IMAGE_VERSION
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY --from=prod-deps app/vendor/ /var/www/html/vendor
# Switch to a non-privileged user (defined in the base image) that the app will run under.
Expand Down

0 comments on commit 332647b

Please sign in to comment.