codex-v2 #225
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| types: [opened, synchronize] | |
| branches: [main, develop] | |
| env: | |
| CI_IMAGE: ghcr.io/${{ github.repository }}-ci | |
| CI_IMAGE_TAG: ghcr.io/${{ github.repository }}-ci:latest | |
| CI_CONTAINER: ${{ github.event.repository.name }}-ci | |
| IMAGE: ghcr.io/${{ github.repository }} | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Lint, test, and build the Python wheel (amd64 only) | |
| # --------------------------------------------------------------------------- | |
| test: | |
| name: Lint, Test & Build Dist | |
| runs-on: ubuntu-24.04 | |
| if: | | |
| github.ref_name == 'main' && github.event_name == 'push' || | |
| github.base_ref == 'main' || | |
| (github.base_ref == 'develop' && (github.head_ref == 'pre-release' || startsWith(github.head_ref, 'v'))) | |
| permissions: | |
| contents: read | |
| packages: write | |
| checks: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| # Only fetch full history for the main push gate | |
| fetch-depth: ${{ (github.ref_name == 'main' && github.event_name == 'push') && 0 || 1 }} | |
| - name: Check for Redundant Tests & Existing Dist | |
| id: gate | |
| if: github.ref_name == 'main' && github.event_name == 'push' | |
| env: | |
| GH_REPO: ${{ github.repository }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bin/ci-download-dist-if-identical.sh | |
| - name: Set up Docker Buildx | |
| if: steps.gate.outputs.dist_found != 'true' | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to GHCR | |
| if: steps.gate.outputs.dist_found != 'true' | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build dist-builder image | |
| id: build-ci | |
| if: steps.gate.outputs.dist_found != 'true' | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| target: codex-ci | |
| load: true | |
| tags: ${{ env.CI_IMAGE_TAG }} | |
| cache-from: type=registry,ref=${{ env.CI_IMAGE }}:cache | |
| cache-to: type=registry,ref=${{ env.CI_IMAGE }}:cache,mode=max | |
| - name: Start Services | |
| id: start-services | |
| if: steps.build-ci.outcome == 'success' | |
| run: | | |
| mkdir -p dist test-results | |
| docker compose up -d ci | |
| - name: Lint | |
| id: lint | |
| if: steps.start-services.outcome == 'success' | |
| run: docker exec ${{ env.CI_CONTAINER }} make lint | |
| - name: Build for Tests & Dist | |
| id: build-for-tests | |
| if: steps.lint.outcome == 'success' | |
| run: docker exec ${{ env.CI_CONTAINER }} make build-choices build-frontend collectstatic | |
| - name: Tests | |
| id: tests | |
| if: steps.build-for-tests.outcome == 'success' | |
| run: docker exec ${{ env.CI_CONTAINER }} make test-frontend django-check test-python -o build-choices | |
| - name: Upload Test Results | |
| id: upload-tests | |
| if: "!cancelled() && steps.tests.outcome != 'skipped'" | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-results | |
| path: "**/test-results/pytest/*.xml" | |
| - name: Publish Test Report | |
| if: "!cancelled() && steps.upload-tests.outcome == 'success'" | |
| uses: mikepenz/action-junit-report@v6 | |
| with: | |
| report_paths: "**/test-results/pytest/*.xml" | |
| - name: Build Distribution | |
| id: build-dist | |
| if: steps.tests.outcome == 'success' | |
| run: docker exec ${{ env.CI_CONTAINER }} make build-only | |
| - name: Stop Services | |
| if: steps.start-services.outcome == 'success' | |
| run: | | |
| touch .env.package # hack because down is too promiscuous | |
| docker compose down | |
| - name: Upload dist artifact | |
| if: "!cancelled() && steps.gate.outputs.dist_found == 'true' || steps.build-dist.outcome =='success'" | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| retention-days: 2 | |
| - name: Discord notification (Test Results) | |
| if: "!cancelled() && false" | |
| uses: sarisia/actions-status-discord@v1 | |
| with: | |
| webhook: ${{ secrets.DISCORD_WEBHOOK }} | |
| status: ${{ job.status }} | |
| title: Lint & Test | |
| description: "Tests for ${{ github.ref_name }} #${{ github.run_number }} ${{ job.status == 'success' && 'passed' || 'FAILED' }}" | |
| color: ${{ job.status == 'success' && '0x28a745' || '0xd73a49' }} | |
| url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| # --------------------------------------------------------------------------- | |
| # Build per-arch Docker images natively | |
| # --------------------------------------------------------------------------- | |
| build: | |
| name: Build Image (${{ matrix.arch }}) | |
| needs: test | |
| if: github.event_name == 'push' || | |
| (github.base_ref == 'develop' && github.head_ref == 'pre-release') | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| runner: ubuntu-24.04 | |
| - arch: arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Download dist artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| - name: Set Build Context | |
| run: | | |
| VERSION=$(grep -Po '(?<=^version = ")[^"]+' pyproject.toml) | |
| echo "CODEX_VERSION=${VERSION}" >> "$GITHUB_ENV" | |
| echo "CODEX_WHEEL=$(find dist -name '*.whl' -print0 | xargs basename)" >> "$GITHUB_ENV" | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: linux/${{ matrix.arch }} | |
| push: true | |
| build-args: | | |
| CODEX_VERSION=${{ env.CODEX_VERSION }} | |
| CODEX_WHEEL=${{ env.CODEX_WHEEL }} | |
| tags: ${{ env.IMAGE }}:${{ env.CODEX_VERSION }}-${{ matrix.arch }} | |
| cache-from: type=gha,scope=build-${{ matrix.arch }} | |
| cache-to: type=gha,scope=build-${{ matrix.arch }},mode=max | |
| # --------------------------------------------------------------------------- | |
| # Create multi-arch manifest and publish | |
| # --------------------------------------------------------------------------- | |
| deploy: | |
| name: Deploy | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Setup uv | |
| uses: astral-sh/[email protected] | |
| - name: Download dist artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: python-dist | |
| path: dist/ | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create and push manifest | |
| run: | | |
| VERSION=$(uv version --short) | |
| TAG_ARGS=("-t" "${IMAGE}:${VERSION}") | |
| # Positive regex check for Final versions (e.g., 1.2.3) | |
| if [[ $VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| TAG_ARGS+=("-t" "${IMAGE}:latest") | |
| fi | |
| docker buildx imagetools create \ | |
| --annotation "index:org.opencontainers.image.title=Codex" \ | |
| --annotation "index:org.opencontainers.image.description=Codex Comic Server" \ | |
| --annotation "index:org.opencontainers.image.version=${VERSION}" \ | |
| --annotation "index:org.opencontainers.image.authors=AJ Slater <[email protected]>" \ | |
| --annotation "index:org.opencontainers.image.url=https://codex-reader.app" \ | |
| --annotation "index:org.opencontainers.image.source=https://github.com/ajslater/codex" \ | |
| --annotation "index:org.opencontainers.image.licenses=GPL-3.0-only" \ | |
| "${TAG_ARGS[@]}" \ | |
| "${IMAGE}:${VERSION}-amd64" \ | |
| "${IMAGE}:${VERSION}-arm64" | |
| - name: Publish to PyPI | |
| run: uv publish dist/* | |
| env: | |
| UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }} | |
| - name: Discord notification (Deploy Results) | |
| if: "!cancelled() && false" | |
| uses: sarisia/actions-status-discord@v1 | |
| with: | |
| webhook: ${{ secrets.DISCORD_WEBHOOK }} | |
| status: ${{ job.status }} | |
| title: Deploy | |
| description: "Deploy ${{ github.ref_name }} #${{ github.run_number }} ${{ job.status == 'success' && 'succeeded' || 'FAILED' }}" | |
| color: ${{ job.status == 'success' && '0x28a745' || '0xd73a49' }} | |
| url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" |