Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docker image publishing #6

Merged
merged 3 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"package_name": "package_name",
"repository_github_url": "https://github.com/reef-technologies/package-name",
"is_django_package": "n",
"build_docker_image": "n",
"_jinja2_env_vars": {
"block_start_string": "# COOKIECUTTER{%",
"block_end_string": "%}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.git
*.pyc
*.sqlite3
*~
*.egg-info/
/.idea/
.env
.venv
venv
media/
.backups/
.envrc
.pdm-python
.terraform.lock.hcl
.terraform/
.nox/
__pycache__
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}-alpine AS builder

WORKDIR /app

RUN apk add --no-cache \
curl \
gcc \
musl-dev \
libffi-dev \
openssl-dev

ENV PDM_VERSION=2.18.1
RUN curl -sSL https://raw.githubusercontent.com/pdm-project/pdm/main/install-pdm.py | python3 -

ENV PATH="/root/.local/bin:$PATH"

COPY . .

ENV PDM_CHECK_UPDATE=false
RUN pdm export > /tmp/requirements.txt

ARG PDM_BUILD_SCM_VERSION="0.0.1"
RUN pdm build -d /tmp/wheelhouse

RUN pip install --no-cache-dir -r /tmp/requirements.txt
RUN pip install --no-cache-dir /tmp/wheelhouse/*.whl

FROM python:${PYTHON_VERSION}-alpine

COPY --from=builder /usr/local/lib/python${PYTHON_VERSION%.*}/site-packages /usr/local/lib/python${PYTHON_VERSION%.*}/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin

ENV PATH="/usr/local/bin:$PATH"

ENTRYPOINT ["{{ cookiecutter.package_name | replace('_', '-') }}"]
107 changes: 94 additions & 13 deletions {{cookiecutter.package_name}}/.github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ env:

jobs:
# COOKIECUTTER{%- raw %}
publish:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
id-token: write # allows publishing to PyPI
contents: write # allows uploading a GitHub release
# Job to get version from tag
get-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get-version.outputs.version }}
draft: ${{ steps.get-version.outputs.draft }}
prerelease: ${{ steps.get-version.outputs.prerelease }}
is_latest_version: ${{ steps.highest-version.outputs.is_latest_version }}
steps:
- name: Get version from tag
id: get-version
Expand All @@ -41,6 +42,32 @@ jobs:
with:
fetch-depth: 0

- name: Get the highest version in the repository
id: highest-version
run: |
git fetch --tags
highest_version=$(git tag --sort=-v:refname | grep -E '^v[0-9]+' | head -n 1)
echo "highest_version=${highest_version#v}" >> "$GITHUB_OUTPUT"
if [[ ${{ steps.get-version.outputs.version }} == "${highest_version#v}" ]] && [ "${{ steps.get-version.outputs.draft }}" == "false" ]; then
echo "is_latest_version=true" >> "$GITHUB_OUTPUT"
else
echo "is_latest_version=false" >> "$GITHUB_OUTPUT"
fi

# Job for Python package publishing
publish-python:
needs: get-version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
id-token: write # allows publishing to PyPI
contents: write # allows uploading a GitHub release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python ${{ env.PYTHON_DEFAULT_VERSION }}
uses: actions/setup-python@v5
with:
Expand All @@ -53,9 +80,9 @@ jobs:
id: read-changelog
uses: mindsers/changelog-reader-action@v2
with:
version: ${{ steps.get-version.outputs.version }}
version: ${{ needs.get-version.outputs.version }}
path: ./CHANGELOG.md
continue-on-error: ${{ fromJSON(steps.get-version.outputs.draft) }}
continue-on-error: ${{ fromJSON(needs.get-version.outputs.draft) }}

- name: Build
run: pdm build
Expand All @@ -71,10 +98,10 @@ jobs:
id: create-release
uses: softprops/action-gh-release@v2
with:
name: ${{ steps.get-version.outputs.version }}
name: ${{ needs.get-version.outputs.version }}
body: ${{ steps.read-changelog.outputs.changes }}
draft: ${{ fromJSON(steps.get-version.outputs.draft)}}
prerelease: ${{ fromJSON(steps.get-version.outputs.prerelease) }}
draft: ${{ fromJSON(needs.get-version.outputs.draft) }}
prerelease: ${{ fromJSON(needs.get-version.outputs.prerelease) }}
files: >-
dist/*.tar.gz
dist/*.whl
Expand All @@ -84,12 +111,66 @@ jobs:
run: rm -f dist/*.sigstore

- name: Publish distribution 📦 to TestPyPI
if: ${{ steps.get-version.outputs.draft == 'true' }}
if: ${{ needs.get-version.outputs.draft == 'true' }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

- name: Publish distribution 📦 to PyPI
if: ${{ steps.get-version.outputs.draft == 'false' }}
if: ${{ needs.get-version.outputs.draft == 'false' }}
uses: pypa/gh-action-pypi-publish@release/v1
# COOKIECUTTER{%- endraw %}

# COOKIECUTTER{% if cookiecutter.build_docker_image == "y" %}
# COOKIECUTTER{%- raw %}
publish-docker:
needs:
- get-version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
packages: write # allows publishing to GitHub Container Registry
contents: read # required for the Docker build context
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Determine Docker image tags
id: docker-tags
run: |
if [ "${{ needs.get-version.outputs.draft }}" = "true" ]; then
DOCKER_TAGS="ghcr.io/${{ github.repository }}:draft-${{ needs.get-version.outputs.version }}"
else
DOCKER_TAGS="ghcr.io/${{ github.repository }}:${{ needs.get-version.outputs.version }}"
if [ "${{ needs.get-version.outputs.is_latest_version }}" = "true" ]; then
DOCKER_TAGS="$DOCKER_TAGS,ghcr.io/${{ github.repository }}:latest"
fi
fi
echo "tags<<EOF" >> $GITHUB_OUTPUT
echo "$DOCKER_TAGS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Log in to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
env:
IMAGE_NAME: ${{ github.repository }} # Defaults to the repo name for the Docker image
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: doesn't multi-arch builds require qemu? The docs says:

If you want support for more platforms, you can use QEMU with the Docker Setup QEMU action.

But I couldn't find for which platforms you need qemu 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only thing I can say to that is that I tested this workflow and it correctly built images for these archs on default GHA runner

push: true
tags: ${{ steps.docker-tags.outputs.tags }}
# COOKIECUTTER{%- endraw %}
# COOKIECUTTER{%- endif %}