diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7b49e97 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,33 @@ +# VCS / CI +.git +.github + +# Runtime data — config/ holds the live database (PHPSESSID session +# credential); it must never enter the build context +config +backend/data + +# Local environments and caches +env +backend/.venv +**/__pycache__ +backend/htmlcov +backend/.pytest_cache +backend/.ruff_cache +backend/steamselfgifter_backend.egg-info +backend/tests/scripts/output + +# Frontend build artifacts — node_modules from the host must not +# overwrite the container's npm ci output (different libc/binaries) +frontend/node_modules +frontend/dist +frontend/playwright-report +frontend/test-results +frontend/coverage + +# Editor / misc +.claude +.idea +.vscode +docker-compose.yml +Dockerfile diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index e81237d..ecf3302 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -4,16 +4,20 @@ on: push: branches: [master] tags: ['v*.*.*'] - pull_request: - branches: [master] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: + # The image is only published after the full test suite passes. + # (PR docker builds are covered by the docker-build job in test.yml.) + tests: + uses: ./.github/workflows/test.yml + build-and-push: runs-on: ubuntu-latest + needs: tests permissions: contents: read packages: write @@ -26,7 +30,6 @@ jobs: uses: docker/setup-buildx-action@v3 - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} @@ -40,7 +43,6 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=ref,event=branch - type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} @@ -51,9 +53,9 @@ jobs: uses: docker/build-push-action@v6 with: context: . - push: ${{ github.event_name != 'pull_request' }} + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - platforms: linux/amd64,linux/arm64 \ No newline at end of file + platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 45fa2ff..7423815 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,12 @@ name: Tests -on: [push, pull_request] +on: + push: + # master is covered by the docker-publish workflow, which calls this + # one before building the image + branches-ignore: [master] + pull_request: + workflow_call: jobs: backend-tests: diff --git a/Dockerfile b/Dockerfile index 1098028..0a8b948 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,10 +29,12 @@ WORKDIR /app COPY backend/src/ ./src/ COPY backend/pyproject.toml backend/README.md ./ -# Install dependencies into a virtual environment +# Install dependencies into a virtual environment, then remove the project +# itself: the app runs from /app/src in the runtime image, and a second copy +# in site-packages would shadow-fight with it. RUN python -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" -RUN pip install --no-cache-dir . +RUN pip install --no-cache-dir . && pip uninstall -y steamselfgifter-backend # ----------------------------------------------------------------------------- # Stage 3: Final Runtime Image diff --git a/docker-compose.yml b/docker-compose.yml index 390555d..af6b151 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,8 @@ -version: '3.8' - services: steamselfgifter: + # `docker compose up` pulls the published image; use + # `docker compose up -d --build` to build from source instead. + image: ghcr.io/kernelcoffee/steamselfgifter:latest build: context: . dockerfile: Dockerfile