CI\CD #477
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI\CD | |
on: | |
push: | |
branches: | |
- main | |
tags: | |
- '*' | |
pull_request: | |
workflow_dispatch: | |
# Update docker hub retention policy | |
schedule: | |
- cron: "21 7 8 * *" | |
env: | |
PIP_NO_CACHE_DIR: "off" | |
POETRY_VIRTUALENVS_IN_PROJECT: "true" | |
POETRY_NO_INTERACTION: "1" | |
DOCKER_BUILDKIT: "1" | |
COMPOSE_DOCKER_CLI_BUILD: "1" | |
PROJECT_NAME: "picodi" | |
REGISTRY: "docker.io" | |
REGISTRY_USERNAME: "yakimka" | |
REGISTRY_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
CACHE_REGISTRY: "ghcr.io" | |
CACHE_REGISTRY_USERNAME: "yakimka" | |
CACHE_REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
DOCKER_COMPOSE_SERVICE_NAME: "devtools" | |
MAIN_PY_VERSION: "3.11" | |
POETRY_DOCKER_IMAGE: "yakimka/poetry:1.8.2-py3.11-slim" | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
permissions: read-all | |
jobs: | |
check-code: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
strategy: | |
matrix: | |
python-version: ['3.10', '3.11', '3.12', '3.13'] | |
steps: | |
- uses: actions/checkout@v4 | |
- run: echo "DEV_IMAGE_FULL_NAME=$(echo ${CACHE_REGISTRY}/${CACHE_REGISTRY_USERNAME}/${PROJECT_NAME})" >> $GITHUB_ENV | |
- run: echo "DEV_VERSION=`(cat Dockerfile-dev; cat .github/workflows/workflow-ci.yml)|sha1sum |cut -c 1-8`" >> $GITHUB_ENV | |
- run: echo "DEV_IMAGE=${DEV_IMAGE_FULL_NAME}:dev-${{ matrix.python-version }}-${DEV_VERSION}" >> $GITHUB_ENV | |
- run: echo "VERSION=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV | |
- run: echo "SHORT_VERSION=$(echo ${VERSION%.*})" >> $GITHUB_ENV | |
- name: Prepare Docker | |
run: | | |
docker login "$CACHE_REGISTRY" -u "$CACHE_REGISTRY_USERNAME" --password="${CACHE_REGISTRY_TOKEN}" | |
docker buildx create --use --driver=docker-container | |
docker --version && docker compose --version | |
- name: Load cached venv and cache | |
id: cached-venv-and-cache | |
uses: actions/cache@v4 | |
with: | |
path: | | |
.venv | |
.cache | |
key: py${{ matrix.python-version }}-${{ hashFiles('./poetry.lock') }} | |
- name: Build docker dev image | |
run: | | |
docker pull ${DEV_IMAGE} || ( | |
PYTHON_VERSION=${{ matrix.python-version }} docker compose build ${DOCKER_COMPOSE_SERVICE_NAME} ; | |
docker tag ${PROJECT_NAME}:dev ${DEV_IMAGE} ; | |
docker push ${DEV_IMAGE} | |
) | |
docker tag ${DEV_IMAGE} ${PROJECT_NAME}:dev | |
- name: Run checks | |
run: docker compose run -e CI=1 --user=$(id -u) --rm devtools ./ci.sh | |
- name: Upload coverage reports to Codecov | |
uses: codecov/[email protected] | |
with: | |
files: ./coverage.xml | |
token: ${{ secrets.CODECOV_TOKEN }} | |
slug: yakimka/picodi | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: built-package-py${{ matrix.python-version }} | |
path: dist/ | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: benchmark-results${{ matrix.python-version }} | |
include-hidden-files: true | |
path: .benchmarks/*/*.json | |
pypy-test: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
strategy: | |
matrix: | |
pypy-version: ['3.10'] | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Prepare Docker | |
run: | | |
docker login "$CACHE_REGISTRY" -u "$CACHE_REGISTRY_USERNAME" --password="${CACHE_REGISTRY_TOKEN}" | |
docker buildx create --use --driver=docker-container | |
docker --version && docker compose --version | |
- name: Load cached venv | |
id: cached-venv | |
uses: actions/cache@v4 | |
with: | |
path: | | |
.venv | |
key: pypy${{ matrix.pypy-version }}-${{ hashFiles('./poetry.lock') }} | |
- name: Pull docker image | |
run: | | |
docker pull pypy:${{ matrix.pypy-version }}-slim | |
docker tag pypy:${{ matrix.pypy-version }}-slim pypy-image | |
- name: Run checks | |
run: > | |
docker run -e VIRTUAL_ENV=/opt/code/.venv --rm -v $(pwd):/opt/code -w /opt/code | |
pypy-image bash -c " | |
if [ ! -d .venv ]; then | |
python -m venv .venv; | |
fi | |
&& .venv/bin/pip install poetry | |
&& .venv/bin/poetry install | |
&& .venv/bin/pip install --no-deps -e . | |
&& .venv/bin/pytest | |
" | |
free-threading-test: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
packages: write | |
strategy: | |
matrix: | |
image-name: ['quay.io/pypa/manylinux_2_28_x86_64'] | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Prepare Docker | |
run: | | |
docker login "$CACHE_REGISTRY" -u "$CACHE_REGISTRY_USERNAME" --password="${CACHE_REGISTRY_TOKEN}" | |
docker buildx create --use --driver=docker-container | |
docker --version && docker compose --version | |
- name: Load cached venv | |
id: cached-venv | |
uses: actions/cache@v4 | |
with: | |
path: | | |
.venv | |
key: free-threading${{ matrix.image-name }}-${{ hashFiles('./poetry.lock') }} | |
- name: Pull docker image | |
run: | | |
docker pull ${{ matrix.image-name }} | |
docker tag ${{ matrix.image-name }} free-threading-image | |
- name: Run checks | |
run: > | |
docker run -e VIRTUAL_ENV=/opt/code/.venv --rm -v $(pwd):/opt/code -w /opt/code | |
free-threading-image bash -c " | |
if [ ! -d .venv ]; then | |
python3.13t -m venv .venv; | |
fi | |
&& .venv/bin/pip install pytest pytest-asyncio pytest-cov pytest-randomly pytest-race pytest-repeat pytest-benchmark | |
&& .venv/bin/pip install --no-deps -e . | |
&& .venv/bin/python -VV | |
&& .venv/bin/pytest --ignore=tests/test_integrations | |
" | |
release-package: | |
runs-on: ubuntu-latest | |
needs: [check-code, pypy-test, free-threading-test] | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/download-artifact@v4 | |
with: | |
name: built-package-py${{ env.MAIN_PY_VERSION }} | |
path: dist/ | |
- name: Prepare Docker | |
run: | | |
docker login "$REGISTRY" -u "$REGISTRY_USERNAME" --password="${REGISTRY_TOKEN}" || true | |
- name: Pull and spin dev container | |
run: | | |
docker run -v $(pwd):/code -w /code --rm -d --name=poetry ${POETRY_DOCKER_IMAGE} sleep infinity | |
- run: echo "PROJECT_VERSION=$(docker exec poetry poetry version --short)" >> $GITHUB_ENV | |
- name: Login to PyPI | |
env: | |
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} | |
run: | | |
echo "Login" | |
docker exec poetry poetry config pypi-token.pypi $PYPI_TOKEN || true | |
- name: Check if tag version matches project version | |
if: startsWith(github.ref, 'refs/tags/') | |
run: | | |
TAG=${GITHUB_REF:10} | |
echo $TAG | |
echo $PROJECT_VERSION | |
if [[ "$TAG" != "$PROJECT_VERSION" ]]; then exit 1; fi | |
- name: Build and publish (dry-run) | |
if: github.actor != 'dependabot[bot]' | |
run: docker exec poetry poetry publish --dry-run | |
- name: Build and publish | |
if: startsWith(github.ref, 'refs/tags/') | |
run: docker exec poetry poetry publish |