Skip to content

Commit 1ea01fe

Browse files
Merge pull request #3 from FrancescoSaverioZuppichini/dev
Dev
2 parents 5174a4b + e85219d commit 1ea01fe

File tree

6 files changed

+121
-7
lines changed

6 files changed

+121
-7
lines changed

.github/workflows/build.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#
2+
name: Create and publish a Docker image
3+
4+
# Configures this workflow to run every time a change is pushed to the branch called `release` or a new release is created.
5+
on:
6+
release:
7+
types: [published]
8+
push:
9+
branches: ["release"]
10+
11+
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
12+
env:
13+
REGISTRY: ghcr.io
14+
IMAGE_NAME: ${{ github.repository }}
15+
16+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
17+
jobs:
18+
build-and-push-image:
19+
runs-on: ubuntu-latest
20+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
21+
permissions:
22+
contents: read
23+
packages: write
24+
attestations: write
25+
id-token: write
26+
#
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
31+
- name: Log in to the Container registry
32+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
33+
with:
34+
registry: ${{ env.REGISTRY }}
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
38+
- name: Extract metadata (tags, labels) for Docker
39+
id: meta
40+
uses: docker/metadata-action@v5
41+
with:
42+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
43+
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
44+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
45+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
46+
- name: Build and push Docker image
47+
id: push
48+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
49+
with:
50+
context: .
51+
push: true
52+
tags: ${{ steps.meta.outputs.tags }}
53+
labels: ${{ steps.meta.outputs.labels }}
54+
55+
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
56+
- name: Generate artifact attestation
57+
uses: actions/attest-build-provenance@v2
58+
with:
59+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
60+
subject-digest: ${{ steps.push.outputs.digest }}
61+
push-to-registry: true

.github/workflows/publish.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
branches:
55
- main
66
jobs:
7-
build:
7+
build-format-and-publish-to-pypi:
88
runs-on: ubuntu-latest
99

1010
steps:
@@ -28,5 +28,4 @@ jobs:
2828
- name: 🚀 Publish
2929
run: |
3030
uv build
31-
3231
uv publish --token ${{ secrets.UV_PUBLISH_TOKEN }}

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
branches: [main, dev]
55

66
jobs:
7-
build:
7+
build-lint-format-and-test:
88
runs-on: ubuntu-latest
99

1010
steps:

Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Build stage
2+
FROM python:3.12-slim AS builder
3+
4+
# Update image
5+
RUN apt-get update && apt-get install -y --no-install-recommends \
6+
build-essential \
7+
&& rm -rf /var/lib/apt/lists/*
8+
# Install uv
9+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
10+
11+
# Set working directory
12+
WORKDIR /app
13+
14+
# Install the project without the the source code (only dependencies)
15+
RUN --mount=type=cache,target=/root/.cache/uv \
16+
--mount=type=bind,source=uv.lock,target=uv.lock \
17+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
18+
uv sync --frozen --no-install-project --no-dev --compile-bytecode
19+
20+
# Install the project's source packages
21+
ADD .python-version pyproject.toml uv.lock src/ /app/
22+
23+
RUN --mount=type=cache,target=/root/.cache/uv \
24+
uv pip install --compile-bytecode .
25+
26+
# Use alpine for the final image to reduce the total size
27+
FROM python:3.12-alpine
28+
29+
# Copy the installed environment from builder
30+
COPY --from=builder --chown=app:app /app /app
31+
32+
# Set working directory
33+
WORKDIR /app
34+
35+
# Configure PATH for executables, packages are in the /app/.venv folder
36+
ENV PATH="/app/.venv/bin:$PATH"
37+
38+
# Run command
39+
CMD ["make_me_laugh"]

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Features:
66
- [x] 💅 [`ruff`](https://docs.astral.sh/ruff/) for linting and formatting
77
- [x] 🧪 [`pytest`](https://docs.pytest.org/en/stable/)
88
- [x] 🧹 [`Makefile`](Makefile) with code quality checks
9-
- [ ] 🐳 Optimized Docker Image
9+
- [x] 🐳 CI/CD Optimized Docker Image runs when a new *release* is created pushing to gh registry
1010
- [x] 🦾 GitHub actions:
1111
- [x] auto publish to [`pypi`](https://pypi.org/) on push on `main`
1212
- [ ] auto creating a new tag on push on `main`, sync versions
@@ -67,4 +67,19 @@ ruff format
6767
Tests inside `/tests` are run using [`pytest`](https://docs.pytest.org/en/stable/) on PR both on `dev` and `main`
6868

6969
### Publish Package
70-
In order to publish to [pypi](https://pypi.org/) you need to create a secret called `UV_PUBLISH_TOKEN` with your [pypi access token](https://pypi.org/manage/account/) under **API tokens**.
70+
In order to publish to [pypi](https://pypi.org/) you need to create a secret called `UV_PUBLISH_TOKEN` with your [pypi access token](https://pypi.org/manage/account/) under **API tokens**.
71+
72+
73+
### Docker
74+
[`Dockerfile`](Dockerfile) contains a multi stage build that uses `--compile-bytecode` to compite your package. For this example, the resulting image is just
75+
76+
```bash
77+
docker build -t python-template .
78+
```
79+
80+
```
81+
REPOSITORY TAG IMAGE ID CREATED SIZE
82+
python-template latest 1ded7d260b1c 58 seconds ago 55.4MB
83+
```
84+
85+
The image is build using the [`build`](.github/workflows/build.yml) workflow when a new *relaese* is created

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)