Skip to content

Lab07

Lab07 #33

Workflow file for this run

name: Python CI
on:
push:
# Run CI only if something has changed in the application folder or in the workflow itself
paths:
- "app_python/**/*.py"
- "app_python/requirements*.txt"
- "app_python/Dockerfile"
- ".github/workflows/python-ci.yml"
pull_request:
paths:
- "app_python/**/*.py"
- "app_python/requirements*.txt"
- "app_python/Dockerfile"
- ".github/workflows/python-ci.yml"
# Prevents old launches from replaying when new pushes are made
concurrency:
group: python-ci-${{ github.ref }}
cancel-in-progress: true
# Minimum required privileges are provided
permissions:
contents: read
env:
# To avoid duplicating paths/versions throughout the file
APP_DIR: app_python
PYTHON_VERSION: "3.12"
# Image repository on Docker Hub (tags added separately)
IMAGE_NAME: ${{ secrets.DOCKER_USERNAME }}/app_python
# SNYK token
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# We're grabbing the repository code for the runner
- name: Checkout
uses: actions/checkout@v4
# Prepare the required version of Python and enable the pip cache (to speed up the work during subsequent launches)
- name: Setup Python (pip cache)
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: "pip"
cache-dependency-path: |
app_python/requirements.txt
app_python/requirements-dev.txt
# Installing dependencies
- name: Install deps
working-directory: ${{ env.APP_DIR }}
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
# Code Quality Check: Style + Typical Errors (Before Testing)
- name: Lint (flake8)
working-directory: ${{ env.APP_DIR }}
run: flake8 app.py tests
# Running unit tests
- name: Tests (pytest)
working-directory: ${{ env.APP_DIR }}
run: pytest -q
# Security scan
- name: Setup Snyk
# Run Snyk only on the push branches we need and only if SNYK_TOKEN is specified (otherwise skip this step)
if: ${{ github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || startsWith(github.ref_name, 'lab')) && env.SNYK_TOKEN != '' }}
uses: snyk/actions/setup@master
# Checking dependencies for vulnerabilities (build stops at high+)
- name: Snyk dependency scan (fail on high+)
if: ${{ github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || startsWith(github.ref_name, 'lab')) && env.SNYK_TOKEN != '' }}
working-directory: ${{ env.APP_DIR }}
env:
SNYK_TOKEN: ${{ env.SNYK_TOKEN }}
run: snyk test --severity-threshold=high
# Checking code for vulnerabilities (build stops at high+)
- name: Snyk code scan (SAST)
if: ${{ github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || startsWith(github.ref_name, 'lab')) && env.SNYK_TOKEN != '' }}
working-directory: ${{ env.APP_DIR }}
env:
SNYK_TOKEN: ${{ env.SNYK_TOKEN }}
run: snyk code test --severity-threshold=high
docker:
# Docker job is started only if tests/linter passed
needs: [test]
runs-on: ubuntu-latest
timeout-minutes: 15
# push image only on push
if: ${{ github.event_name == 'push' && (github.ref_name == 'main' || github.ref_name == 'master' || startsWith(github.ref_name, 'lab')) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx (for GHA cache)
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
install: true
# CalVer - version by date
# SHA — a unique tag for each commit
- name: Generate CalVer + SHA tag
run: |
echo "CALVER=$(date -u +'%Y.%m.%d')" >> $GITHUB_ENV
echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
# Authorization in Docker Hub using a token from GitHub Secrets
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
# Build and push the image (Layers are cached to make rebuilds faster)
- name: Build and push (with cache)
uses: docker/build-push-action@v6
with:
context: ./${{ env.APP_DIR }}
push: true
tags: |
${{ env.IMAGE_NAME }}:${{ env.CALVER }}
${{ env.IMAGE_NAME }}:sha-${{ env.SHORT_SHA }}
${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max