Skip to content

Commit b8f457a

Browse files
Add comprehensive test suite covering core functionality and edge cases (#1182)
* Enable GitHub issues for projects with retry logic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * refactor: reorganize test suite with fixtures and business-focused tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * chore: replace black/isort/flake8 with ruff for code formatting and linting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ci: add coverage file path configuration to test workflow * update CI config and use official Ruff Docker image for linting * simplify Makefile targets and improve CI workflow with better coverage handling * remove hardcoded coverage.xml file * optimize Docker build with layer caching and artifact sharing between jobs * fix coverage.xml path * standardize Dockerfile AS syntax to uppercase * add Codecov coverage reporting to test workflow * fix coverage report upload by copying XML from Docker container * simplify CI workflow by removing build job and using docker compose directly * update Docker coverage handling in CI workflow and simplify Makefile * refactor Docker setup by introducing base and application Dockerfiles, enhancing caching mechanisms, and updating docker-compose configuration for improved CI integration * update GitHub Actions workflow to include permissions for contents and packages * enhance GitHub Actions workflow by adding optional Personal Access Token usage and enriching image metadata with source and description labels * more fixes. * Add login step for Container Registry in GitHub Actions workflow * Update coverage file paths in GitHub Actions workflow to use /tmp directory * Refactor coverage handling in GitHub Actions workflow to create a dedicated output directory and simplify XML file copying from mounted volume * Update coverage file paths in GitHub Actions workflow to use /app directory for consistency with container structure * Refactor utility functions in jazzband.utils module for improved type hinting and code clarity. Add comprehensive unit tests for utility functions, including URL safety validation, cache header management, and redirect target handling. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Formatting. * Add comprehensive unit tests for exception handling, custom headers, mixins, and renderer functionality. Introduce new fixtures for testing and enhance existing ones for better coverage. * Update pre-commit configuration to use --unsafe-fixes for ruff and remove unnecessary result assignments in CSP header tests. * Add Codecov badge to README for improved visibility of test coverage --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 89abd78 commit b8f457a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4313
-190
lines changed

.codecov.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
codecov:
2+
require_ci_to_pass: true
3+
4+
coverage:
5+
precision: 2
6+
round: down
7+
range: "70...100"
8+
status:
9+
project:
10+
default:
11+
target: auto
12+
threshold: 1%
13+
patch:
14+
default:
15+
target: auto
16+
threshold: 1%
17+
18+
parsers:
19+
gcov:
20+
branch_detection:
21+
conditional: true
22+
loop: true
23+
method: false
24+
macro: false
25+
26+
comment:
27+
layout: "reach,diff,flags,files,footer"
28+
behavior: default
29+
require_changes: false

.env.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FLASK_ENV=testing
2+
OAUTHLIB_INSECURE_TRANSPORT=1
3+
# Test environment settings for GitHub OAuth
4+
GITHUB_ORG_NAME=test-org-name
5+
GITHUB_CLIENT_ID=test-client-id
6+
GITHUB_CLIENT_SECRET=test-client-secret

.flake8

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Cleanup Old Cache Images
2+
3+
on:
4+
schedule:
5+
# Run weekly on Sundays at 2 AM UTC
6+
- cron: '0 2 * * 0'
7+
workflow_dispatch:
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
BASE_IMAGE_NAME: ${{ github.repository }}/base
12+
13+
jobs:
14+
cleanup:
15+
runs-on: ubuntu-latest
16+
if: github.repository_owner == 'jazzband'
17+
18+
steps:
19+
- name: Log in to Container Registry
20+
uses: docker/login-action@v3
21+
with:
22+
registry: ${{ env.REGISTRY }}
23+
username: ${{ github.actor }}
24+
password: ${{ secrets.GITHUB_TOKEN }}
25+
26+
- name: Delete old images
27+
run: |
28+
# Get all image versions
29+
PACKAGE_NAME=$(echo "${{ env.BASE_IMAGE_NAME }}" | cut -d'/' -f2-)
30+
31+
# Get all versions of the base image package
32+
VERSIONS=$(gh api \
33+
-H "Accept: application/vnd.github.v3+json" \
34+
"/orgs/${{ github.repository_owner }}/packages/container/$PACKAGE_NAME/versions" \
35+
--jq '.[].id' | head -n -5) # Keep the 5 most recent versions
36+
37+
# Delete old versions (keep the latest 5)
38+
for version_id in $VERSIONS; do
39+
echo "Deleting version ID: $version_id"
40+
gh api \
41+
--method DELETE \
42+
-H "Accept: application/vnd.github.v3+json" \
43+
"/orgs/${{ github.repository_owner }}/packages/container/$PACKAGE_NAME/versions/$version_id" || true
44+
done
45+
env:
46+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test-and-deploy.yml

Lines changed: 129 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
name: Test & Deploy
2+
3+
permissions:
4+
contents: read
5+
packages: write
6+
27
on:
38
push:
49
branches:
@@ -10,9 +15,86 @@ on:
1015
types:
1116
- published
1217

18+
env:
19+
REGISTRY: ghcr.io
20+
BASE_IMAGE_NAME: ${{ github.repository }}/base
21+
1322
jobs:
23+
build-base-image:
24+
runs-on: ubuntu-latest
25+
outputs:
26+
image-tag: ${{ steps.meta.outputs.tags }}
27+
image-digest: ${{ steps.build.outputs.digest }}
28+
cache-hit: ${{ steps.cache-check.outputs.cache-hit }}
29+
deps-hash: ${{ steps.deps-hash.outputs.hash }}
30+
steps:
31+
- name: Checkout
32+
uses: actions/checkout@v4
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v3
36+
37+
- name: Log in to Container Registry
38+
uses: docker/login-action@v3
39+
with:
40+
registry: ${{ env.REGISTRY }}
41+
username: ${{ github.actor }}
42+
password: ${{ secrets.GITHUB_TOKEN }}
43+
# Alternative: Use a Personal Access Token if GITHUB_TOKEN doesn't work
44+
# password: ${{ secrets.GHCR_TOKEN }}
45+
46+
- name: Generate dependency hash
47+
id: deps-hash
48+
run: |
49+
DEPS_HASH=$(cat requirements.txt package.json package-lock.json | sha256sum | cut -d' ' -f1)
50+
echo "hash=$DEPS_HASH" >> $GITHUB_OUTPUT
51+
52+
- name: Check if base image exists
53+
id: cache-check
54+
run: |
55+
# Check if an image with this dependency hash already exists
56+
if docker manifest inspect ${{ env.REGISTRY }}/${{ env.BASE_IMAGE_NAME }}:deps-${{ steps.deps-hash.outputs.hash }} > /dev/null 2>&1; then
57+
echo "cache-hit=true" >> $GITHUB_OUTPUT
58+
echo "Base image cache hit!"
59+
else
60+
echo "cache-hit=false" >> $GITHUB_OUTPUT
61+
echo "Base image cache miss, will build new image"
62+
fi
63+
64+
- name: Extract metadata
65+
id: meta
66+
uses: docker/metadata-action@v5
67+
with:
68+
images: ${{ env.REGISTRY }}/${{ env.BASE_IMAGE_NAME }}
69+
tags: |
70+
type=raw,value=deps-${{ steps.deps-hash.outputs.hash }}
71+
type=raw,value=latest
72+
type=ref,event=branch
73+
type=ref,event=pr
74+
type=sha
75+
labels: |
76+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
77+
org.opencontainers.image.description=Base image with dependencies for Jazzband website
78+
79+
- name: Build and push base image
80+
if: steps.cache-check.outputs.cache-hit != 'true'
81+
id: build
82+
uses: docker/build-push-action@v5
83+
with:
84+
context: .
85+
file: Dockerfile.base
86+
platforms: linux/amd64
87+
push: true
88+
tags: ${{ steps.meta.outputs.tags }}
89+
labels: ${{ steps.meta.outputs.labels }}
90+
cache-from: type=gha
91+
cache-to: type=gha,mode=max
92+
build-args: |
93+
DEPS_HASH=${{ steps.deps-hash.outputs.hash }}
94+
1495
test:
1596
runs-on: ubuntu-latest
97+
needs: build-base-image
1698

1799
steps:
18100
- name: Cancel Previous Runs
@@ -22,18 +104,61 @@ jobs:
22104

23105
- uses: actions/checkout@v4
24106

107+
- name: Log in to Container Registry
108+
uses: docker/login-action@v3
109+
with:
110+
registry: ${{ env.REGISTRY }}
111+
username: ${{ github.actor }}
112+
password: ${{ secrets.GITHUB_TOKEN }}
113+
25114
- uses: actions/setup-node@v4
26115
with:
27116
node-version: "15"
28117
check-latest: true
29118

30-
- run: make envvar
119+
- name: Create .env file
120+
run: make envvar
121+
122+
- name: Pull base image
123+
run: |
124+
docker pull ${{ env.REGISTRY }}/${{ env.BASE_IMAGE_NAME }}:deps-${{ needs.build-base-image.outputs.deps-hash }}
125+
126+
- name: Build application image
127+
env:
128+
BASE_IMAGE: ${{ env.REGISTRY }}/${{ env.BASE_IMAGE_NAME }}:deps-${{ needs.build-base-image.outputs.deps-hash }}
129+
run: make build-app
31130

32-
- run: make pull
131+
- name: Run tests
132+
env:
133+
JAZZBAND_IMAGE: jazzband-website:latest
134+
COVERAGE_FILE: /app/.coverage
135+
COVERAGE_XML: /app/coverage.xml
136+
run: |
137+
# Create coverage output directory
138+
mkdir -p $PWD/coverage-data
139+
chmod 777 $PWD/coverage-data
140+
141+
# Run tests with volume mount for coverage output
142+
docker compose run --rm \
143+
-e COVERAGE_FILE \
144+
-e COVERAGE_XML \
145+
-v $PWD/coverage-data:/app/coverage-data \
146+
-u root \
147+
web sh -c "
148+
pytest tests/ --cov=jazzband --cov-report=xml --cov-report=term
149+
cp /app/coverage.xml /app/coverage-data/coverage.xml
150+
chmod 644 /app/coverage-data/coverage.xml
151+
"
33152
34-
- run: make image
153+
# Copy coverage XML from mounted volume
154+
- name: Copy coverage XML from container
155+
run: |
156+
cp coverage-data/coverage.xml ./coverage.xml || echo "Failed to copy coverage.xml"
35157
36-
- run: make test
158+
- name: Upload coverage reports to Codecov with GitHub Action
159+
uses: codecov/codecov-action@v5
160+
with:
161+
file: ./coverage.xml
37162

38163
deploy:
39164
if: github.event.action == 'published' && github.repository == 'jazzband/website'

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ node_modules
1111
.local/
1212
.parcel-cache
1313
.vscode
14+
.coverage
15+
coverage.xml

.isort.cfg

Lines changed: 0 additions & 6 deletions
This file was deleted.

.pre-commit-config.yaml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
repos:
2-
- repo: https://github.com/psf/black
3-
rev: 25.1.0
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.6.5
44
hooks:
5-
- id: black
6-
- repo: https://github.com/PyCQA/isort
7-
rev: 6.0.1
8-
hooks:
9-
- id: isort
10-
- repo: https://github.com/PyCQA/flake8
11-
rev: 7.2.0
12-
hooks:
13-
- id: flake8
5+
- id: ruff
6+
args: [--fix, --unsafe-fixes]
7+
- id: ruff-format

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node as npm
1+
FROM node AS npm
22

33
WORKDIR /tmp
44

Dockerfile.app

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Application image that uses the cached base image
2+
ARG BASE_IMAGE
3+
FROM node AS npm
4+
5+
WORKDIR /tmp
6+
7+
# Copy package files (should already be cached in base image)
8+
COPY package.json package-lock.json /tmp/
9+
10+
# Install dependencies (this layer should be cached from base image build)
11+
RUN npm update -g npm && npm install
12+
13+
# Copy application code and build frontend assets
14+
COPY . /tmp/
15+
RUN npm run build
16+
17+
# -----------------------------------------------------------------------------
18+
# Use the cached base image
19+
FROM ${BASE_IMAGE}
20+
21+
# Switch to root temporarily to copy files
22+
USER root
23+
24+
# Copy application code
25+
COPY . /app/
26+
27+
# Copy built frontend assets from the npm stage
28+
COPY --from=npm /tmp/jazzband/static/dist /app/jazzband/static/dist/
29+
30+
# Ensure proper ownership
31+
RUN chown -R 10001:10001 /app
32+
33+
# Switch back to app user
34+
USER 10001
35+
36+
EXPOSE 5000
37+
38+
ENTRYPOINT ["/app/docker-entrypoint.sh", "--"]

0 commit comments

Comments
 (0)