Skip to content

CI\CD

CI\CD #264

Workflow file for this run

name: CI\CD
on:
push:
branches:
- main
tags:
- '*'
pull_request:
workflow_dispatch:
# Update docker hub retention policy
schedule:
- cron: "21 7 8 * *"
env:
DOCKER_USERNAME: "yakim"
PROJECT_NAME: "difflume"
DOCKER_COMPOSE_SERVICE_NAME: "app"
MAIN_PY_VERSION: "3.11"
PIP_NO_CACHE_DIR: "off"
POETRY_VIRTUALENVS_IN_PROJECT: "true"
POETRY_NO_INTERACTION: "1"
REGISTRY: ""
DOCKER_BUILDKIT: "1"
COMPOSE_DOCKER_CLI_BUILD: "1"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: read-all
jobs:
check-code:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- run: echo "IMAGE_FULL_NAME=$(echo ${DOCKER_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=${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
env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
run: |
docker login "$REGISTRY" -u "$DOCKER_USERNAME" --password="${DOCKERHUB_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
- uses: actions/upload-artifact@v3
if: failure()
with:
name: snapshot-report-py${{ matrix.python-version }}
path: snapshot_report.html
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
# token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
- uses: actions/upload-artifact@v3
with:
name: built-package-py${{ matrix.python-version }}
path: dist/
release-package:
runs-on: ubuntu-latest
needs: [ check-code ]
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
name: built-package-py${{ env.MAIN_PY_VERSION }}
path: dist/
- run: echo "IMAGE_FULL_NAME=$(echo ${DOCKER_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=${IMAGE_FULL_NAME}:dev-${MAIN_PY_VERSION}-${DEV_VERSION}" >> $GITHUB_ENV
- name: Prepare Docker
env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
run: |
docker login "$REGISTRY" -u "$DOCKER_USERNAME" --password="${DOCKERHUB_TOKEN}"
docker buildx create --use --driver=docker-container
docker --version && docker compose --version
- name: Pull and spin dev container
run: |
docker pull ${DEV_IMAGE}
docker tag ${DEV_IMAGE} ${PROJECT_NAME}:dev
docker compose run --rm -d devtools sleep infinity
- run: echo "PROJECT_VERSION=$(docker compose exec devtools poetry version --short)" >> $GITHUB_ENV
- name: Login to PyPI
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
echo "Login"
docker compose exec devtools 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 compose exec devtools poetry publish --dry-run
- name: Build and publish
if: startsWith(github.ref, 'refs/tags/')
run: docker compose exec devtools poetry publish
release-image:
runs-on: ubuntu-latest
needs: [ check-code ]
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
name: built-package-py${{ env.MAIN_PY_VERSION }}
path: dist/
- run: echo "IMAGE_FULL_NAME=$(echo ${DOCKER_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=${IMAGE_FULL_NAME}:dev-${MAIN_PY_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
env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
run: |
docker login "$REGISTRY" -u "$DOCKER_USERNAME" --password="${DOCKERHUB_TOKEN}"
docker buildx create --use --driver=docker-container
docker --version && docker compose --version
- name: Pull and spin dev container
run: |
docker pull ${DEV_IMAGE}
docker tag ${DEV_IMAGE} ${PROJECT_NAME}:dev
docker compose run --rm -d devtools sleep infinity
- run: echo "PROJECT_VERSION=$(docker compose exec devtools poetry version --short)" >> $GITHUB_ENV
# https://docs.docker.com/build/cache/backends/gha/
- name: Expose GitHub Runtime
uses: crazy-max/ghaction-github-runtime@v3
- name: Create tag string
run: echo "TAG_ARGS=-t ${IMAGE_FULL_NAME}:latest" >> $GITHUB_ENV
- name: Add version from git tag
if: startsWith(github.ref, 'refs/tags/')
run: |
echo "TAG_ARGS=${TAGS} -t ${IMAGE_FULL_NAME}:${VERSION} -t ${IMAGE_FULL_NAME}:${SHORT_VERSION}" >> $GITHUB_ENV
- name: Set push flag
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main'
run: echo "PUSH_FLAG=--push" >> $GITHUB_ENV
- name: Build image
run: >
docker buildx build ${PUSH_FLAG:-}
--build-arg WHEEL=${PROJECT_NAME}-${PROJECT_VERSION}-py3-none-any.whl
--cache-to type=gha,mode=max --cache-from type=gha
--platform=linux/arm64,linux/amd64
${TAG_ARGS} .