Repository navigation
fix: Add permissions for contents in prepare-release job #26
Workflow file for this run
This file contains hidden or 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: Release Pipeline | |
| on: | |
| push: | |
| branches: | |
| - 'release/**' | |
| pull_request: | |
| branches: | |
| - 'release/**' | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| prepare-release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| release_version: ${{ steps.version.outputs.release_version }} | |
| build_number: ${{ steps.version.outputs.build_number }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract and bump version | |
| id: version | |
| run: | | |
| # Extract version from branch name (release/0.1.build -> 0.1) | |
| BRANCH_NAME=${GITHUB_REF#refs/heads/} | |
| RELEASE_VERSION=$(echo $BRANCH_NAME | grep -oP 'release/\K[0-9]+\.[0-9]+' || echo "0.1") | |
| # Read current full version or start from release.1 | |
| BUILD_FILE=".github/workflows/.build" | |
| if [ -f "$BUILD_FILE" ]; then | |
| CURRENT_VERSION=$(cat $BUILD_FILE) | |
| # Extract current release version from stored version | |
| CURRENT_RELEASE_VERSION=$(echo $CURRENT_VERSION | grep -oP '^[0-9]+\.[0-9]+' || echo "0.0") | |
| if [ "$RELEASE_VERSION" = "$CURRENT_RELEASE_VERSION" ]; then | |
| # Same release version - increment build number | |
| BUILD_NUMBER=$(echo $CURRENT_VERSION | grep -oP '\.[0-9]+$' | sed 's/\.//') | |
| BUILD_NUMBER=$((BUILD_NUMBER + 1)) | |
| echo "Incrementing build number for release $RELEASE_VERSION" | |
| else | |
| # Different release version - reset build number to 1 | |
| BUILD_NUMBER=1 | |
| echo "New release version $RELEASE_VERSION detected (was $CURRENT_RELEASE_VERSION) - resetting build number to 1" | |
| fi | |
| else | |
| BUILD_NUMBER=1 | |
| echo "No previous version found - starting with build number 1" | |
| fi | |
| # Create full version string | |
| FULL_VERSION="${RELEASE_VERSION}.${BUILD_NUMBER}" | |
| # Update build file with full version | |
| echo $FULL_VERSION > $BUILD_FILE | |
| echo "version=$FULL_VERSION" >> $GITHUB_OUTPUT | |
| echo "release_version=$RELEASE_VERSION" >> $GITHUB_OUTPUT | |
| echo "build_number=$BUILD_NUMBER" >> $GITHUB_OUTPUT | |
| echo "Release version: $FULL_VERSION (Release: $RELEASE_VERSION, Build: $BUILD_NUMBER)" | |
| - name: Commit build number update | |
| if: github.event_name == 'push' | |
| run: | | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| git add .github/workflows/.build | |
| git commit -m "Bump version to ${{ steps.version.outputs.version }}" || exit 0 | |
| git push | |
| run-tests: | |
| needs: prepare-release | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ['3.10', '3.11', '3.12'] | |
| services: | |
| postgres: | |
| image: postgres:15 | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: test_db | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| redis: | |
| image: redis:7 | |
| options: >- | |
| --health-cmd "redis-cli ping" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 6379:6379 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Run tests | |
| env: | |
| DATABASE_URL: postgres://postgres:postgres@localhost:5432/test_db | |
| REDIS_URL: redis://localhost:6379/0 | |
| run: | | |
| python -m pytest --cov=. --cov-report=xml --cov-report=term-missing -v | |
| - name: Upload coverage to Codecov | |
| if: matrix.python-version == '3.12' | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| test-migrations: | |
| needs: prepare-release | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15 | |
| env: | |
| POSTGRES_PASSWORD: postgres | |
| POSTGRES_DB: test_migrations_db | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| ports: | |
| - 5432:5432 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| - name: Test migrations | |
| env: | |
| DATABASE_URL: postgres://postgres:postgres@localhost:5432/test_migrations_db | |
| run: | | |
| python manage.py migrate --check | |
| python manage.py makemigrations --check --dry-run | |
| build-and-test-container: | |
| needs: [prepare-release, run-tests, test-migrations] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v5 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=raw,value=${{ needs.prepare-release.outputs.version }} | |
| type=raw,value=${{ needs.prepare-release.outputs.release_version }} | |
| type=raw,value=latest | |
| - name: Build Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: false | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| outputs: type=docker,dest=/tmp/image.tar | |
| - name: Load and test Docker image | |
| run: | | |
| docker load --input /tmp/image.tar | |
| # Test if container starts properly | |
| CONTAINER_ID=$(docker run -d -p 8000:8000 \ | |
| -e DEBUG=False \ | |
| -e SECRET_KEY=test-secret-key-for-container-test \ | |
| -e DATABASE_URL=sqlite:///db.sqlite3 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.version }}) | |
| # Wait for container to start | |
| sleep 10 | |
| # Check if container is running | |
| if [ "$(docker inspect -f '{{.State.Running}}' $CONTAINER_ID)" = "true" ]; then | |
| echo "✅ Container is running successfully" | |
| # Test health endpoint if available | |
| if curl -f http://localhost:8000/health/ 2>/dev/null; then | |
| echo "✅ Health check passed" | |
| else | |
| echo "⚠️ Health endpoint not available, but container is running" | |
| fi | |
| else | |
| echo "❌ Container failed to start" | |
| docker logs $CONTAINER_ID | |
| exit 1 | |
| fi | |
| # Cleanup | |
| docker stop $CONTAINER_ID | |
| docker rm $CONTAINER_ID | |
| - name: Push Docker image to registry | |
| if: github.event_name == 'push' | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| create-release-summary: | |
| needs: [prepare-release, run-tests, test-migrations, build-and-test-container] | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' | |
| steps: | |
| - name: Create release summary | |
| run: | | |
| echo "🚀 Release Pipeline Completed Successfully!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Full Version:** ${{ needs.prepare-release.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Release Version:** ${{ needs.prepare-release.outputs.release_version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Build Number:** ${{ needs.prepare-release.outputs.build_number }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Branch:** ${GITHUB_REF#refs/heads/}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Container Tags:**" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.version }}\` (full version)" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare-release.outputs.release_version }}\` (release version)" >> $GITHUB_STEP_SUMMARY | |
| echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### ✅ Completed Steps" >> $GITHUB_STEP_SUMMARY | |
| echo "- Version bumped to ${{ needs.prepare-release.outputs.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- Tests passed on Python 3.10, 3.11, 3.12" >> $GITHUB_STEP_SUMMARY | |
| echo "- Database migrations verified" >> $GITHUB_STEP_SUMMARY | |
| echo "- Code coverage uploaded to Codecov" >> $GITHUB_STEP_SUMMARY | |
| echo "- Docker container built and tested" >> $GITHUB_STEP_SUMMARY | |
| echo "- Container uploaded to GitHub Container Registry" >> $GITHUB_STEP_SUMMARY |