chore(deps-dev): bump pnpm from 11.1.2 to 11.2.2 in /frontend #1640
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: CI and Auto Merge for imgcompress | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - next_rc | |
| - feature/* | |
| - bugfix/* | |
| - enhancements/* | |
| - release/* | |
| - prepare-rc-* | |
| - prepair-rc-* | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| upload_e2e_artifacts: | |
| description: "Upload E2E test results artifact?" | |
| required: false | |
| default: "false" | |
| upload_feature_flags_artifacts: | |
| description: "Upload feature-flags matrix screenshots / videos artifact? (default on)" | |
| required: false | |
| default: "true" | |
| deploy_nightly: | |
| description: "After E2E tests succeed, trigger the nightly deployment workflow" | |
| type: boolean | |
| required: false | |
| default: false | |
| permissions: | |
| contents: read | |
| # Cancel superseded runs on the same PR / branch so we don't waste minutes | |
| # building stale commits and so auto-merge always acts on the latest CI. | |
| concurrency: | |
| group: ci-auto-merge-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint-python: | |
| name: lint Python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.11" | |
| - name: Install Ruff | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install ruff==0.15.14 | |
| - name: Run Ruff | |
| run: ruff check backend tests healthcheck.py update_dockerhub_description.py | |
| scan-image: | |
| name: scan local image | |
| needs: lint-python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Authenticate to dhi.io for DHI base images | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: dhi.io | |
| username: ${{ vars.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build local application image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| load: true | |
| tags: karimz1/imgcompress:local-scan | |
| cache-from: type=gha,scope=app-linux/amd64 | |
| cache-to: type=gha,mode=max,scope=app-linux/amd64 | |
| - name: Run Trivy image scan | |
| continue-on-error: true | |
| env: | |
| IMAGE_REF: karimz1/imgcompress:local-scan | |
| SCAN_OUTPUT: scan-result.log | |
| run: ./scripts/runTrivyImageScan.sh | |
| - name: Upload Trivy scan result | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: trivy-scan-result | |
| path: scan-result.log | |
| retention-days: 7 | |
| test-backend: | |
| needs: lint-python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: [ "linux/amd64", "linux/arm64" ] | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Authenticate to dhi.io for DHI base images | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: dhi.io | |
| username: ${{ vars.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build Dev Container for ${{ matrix.platform }} | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: .devcontainer/ | |
| platforms: ${{ matrix.platform }} | |
| load: true | |
| tags: devcontainer:local-test | |
| cache-from: type=gha,scope=devcontainer-${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=devcontainer-${{ matrix.platform }} | |
| - name: Run Backend Unit Tests on ${{ matrix.platform }} | |
| run: | | |
| docker run --rm \ | |
| --platform=${{ matrix.platform }} \ | |
| --entrypoint /bin/sh \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "$HOME/.docker/config.json:/root/.docker/config.json:ro" \ | |
| -v "$(pwd):/app/" \ | |
| -e IS_RUNNING_IN_GITHUB_ACTIONS=$IS_RUNNING_IN_GITHUB_ACTIONS \ | |
| --name devcontainer \ | |
| devcontainer:local-test /app/scripts/runUnitTests.sh | |
| env: | |
| IS_RUNNING_IN_GITHUB_ACTIONS: true | |
| - name: Run Backend Integration (Docker) Tests on ${{ matrix.platform }} | |
| run: | | |
| docker run --rm \ | |
| --platform=${{ matrix.platform }} \ | |
| --entrypoint /bin/sh \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "$HOME/.docker/config.json:/root/.docker/config.json:ro" \ | |
| -v "$(pwd):/app/" \ | |
| -e IS_RUNNING_IN_GITHUB_ACTIONS=$IS_RUNNING_IN_GITHUB_ACTIONS \ | |
| --name devcontainer \ | |
| devcontainer:local-test /app/scripts/runIntegrationTests.sh | |
| env: | |
| IS_RUNNING_IN_GITHUB_ACTIONS: true | |
| test-e2e: | |
| needs: lint-python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| platform: [ "linux/amd64" ] # works only on amd64 for now; a fix for arm64 is in progress | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Authenticate to dhi.io for DHI base images | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: dhi.io | |
| username: ${{ vars.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build Application Container for ${{ matrix.platform }} | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: ${{ matrix.platform }} | |
| load: true | |
| tags: karimz1/imgcompress:local-test | |
| cache-from: type=gha,scope=app-${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=app-${{ matrix.platform }} | |
| - name: Run Application Container (Host Networking) for ${{ matrix.platform }} | |
| run: | | |
| docker run --rm -d \ | |
| --platform ${{ matrix.platform }} \ | |
| --network host \ | |
| --name app \ | |
| karimz1/imgcompress:local-test web | |
| - name: Wait for Application to be Ready (using localhost) for ${{ matrix.platform }} | |
| run: | | |
| BASE_URL="http://localhost:5000" | |
| echo "Waiting for the application to be ready on ${BASE_URL}..." | |
| max_attempts=120 | |
| attempt_num=1 | |
| until curl -s --fail "$BASE_URL" > /dev/null; do | |
| if [ "$attempt_num" -eq "$max_attempts" ]; then | |
| echo "Application failed to start after $max_attempts attempts." | |
| exit 1 | |
| fi | |
| echo "Waiting for app... attempt $attempt_num" | |
| attempt_num=$((attempt_num+1)) | |
| sleep 1 | |
| done | |
| echo "Application is up! Continuing..." | |
| - name: Build Dev Container for ${{ matrix.platform }} | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: .devcontainer/ | |
| platforms: ${{ matrix.platform }} | |
| load: true | |
| tags: devcontainer:local-test | |
| cache-from: type=gha,scope=devcontainer-${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=devcontainer-${{ matrix.platform }} | |
| - name: Make E2E script executable | |
| run: chmod +x ./scripts/run-e2e.sh | |
| - name: Run E2E Tests in Dev Container (Host Networking) | |
| run: | | |
| docker run --rm \ | |
| --platform ${{ matrix.platform }} \ | |
| --entrypoint /bin/sh \ | |
| --network host \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "$HOME/.docker/config.json:/root/.docker/config.json:ro" \ | |
| -v "$(pwd):/app/" \ | |
| -e IS_RUNNING_IN_GITHUB_ACTIONS=true \ | |
| -e PLAYWRIGHT_BASE_URL=http://localhost:5000 \ | |
| --name devcontainer_e2e \ | |
| devcontainer:local-test -c "/app/scripts/run-e2e.sh" | |
| - name: Get CPU Architecture | |
| run: echo "ARCH=$(uname -m | sed 's/[^a-zA-Z0-9]//g')" >> $GITHUB_ENV | |
| - name: Ensure E2E Test Results Directory Exists | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.upload_e2e_artifacts == 'true' | |
| run: mkdir -p frontend/e2e-test-results | |
| - name: Zip E2E Test Results for ${{ env.ARCH }} | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.upload_e2e_artifacts == 'true' | |
| run: | | |
| if [ -d "frontend/e2e-test-results" ] && [ "$(ls -A frontend/e2e-test-results)" ]; then | |
| zip -r e2e-test-results-${{ env.ARCH }}.zip frontend/e2e-test-results | |
| else | |
| echo "No test results found, creating an empty zip." | |
| touch e2e-test-results-${{ env.ARCH }}.zip | |
| fi | |
| - name: Upload E2E Test Results Artifact for ${{ env.ARCH }} | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.upload_e2e_artifacts == 'true' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: e2e-test-results-${{ env.ARCH }} | |
| path: e2e-test-results-${{ env.ARCH }}.zip | |
| retention-days: 3 | |
| test-feature-flags-matrix: | |
| # Job display name reads as the actual user-facing UI state instead of | |
| # a confusing tuple of `disable_* = true/false` (double negative). | |
| name: feature-flags (${{ matrix.scenario }}) | |
| needs: lint-python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # logo hidden + storage hidden (DISABLE_LOGO=true, DISABLE_STORAGE_MANAGEMENT=true) | |
| - disable_logo: "true" | |
| disable_storage_management: "true" | |
| scenario: "logo HIDDEN | storage HIDDEN" | |
| label: "logo-hidden_storage-hidden" | |
| # logo hidden + storage shown (DISABLE_LOGO=true, DISABLE_STORAGE_MANAGEMENT=false) | |
| - disable_logo: "true" | |
| disable_storage_management: "false" | |
| scenario: "logo HIDDEN | storage SHOWN" | |
| label: "logo-hidden_storage-shown" | |
| # logo shown + storage hidden (DISABLE_LOGO=false, DISABLE_STORAGE_MANAGEMENT=true) | |
| - disable_logo: "false" | |
| disable_storage_management: "true" | |
| scenario: "logo SHOWN | storage HIDDEN" | |
| label: "logo-shown_storage-hidden" | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Build Application Container | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| load: true | |
| tags: karimz1/imgcompress:local-test | |
| cache-from: type=gha,scope=app-linux/amd64 | |
| cache-to: type=gha,mode=max,scope=app-linux/amd64 | |
| - name: Start app — ${{ matrix.scenario }} | |
| run: | | |
| echo "::group::Feature flag configuration for this matrix entry" | |
| echo "Scenario: ${{ matrix.scenario }}" | |
| echo "DISABLE_LOGO: ${{ matrix.disable_logo }} -> Logo $([ '${{ matrix.disable_logo }}' = 'true' ] && echo 'HIDDEN' || echo 'SHOWN')" | |
| echo "DISABLE_STORAGE_MANAGEMENT: ${{ matrix.disable_storage_management }} -> Storage management button $([ '${{ matrix.disable_storage_management }}' = 'true' ] && echo 'HIDDEN' || echo 'SHOWN')" | |
| echo "::endgroup::" | |
| docker run --rm -d \ | |
| --platform linux/amd64 \ | |
| --network host \ | |
| --name app \ | |
| -e DISABLE_LOGO=${{ matrix.disable_logo }} \ | |
| -e DISABLE_STORAGE_MANAGEMENT=${{ matrix.disable_storage_management }} \ | |
| karimz1/imgcompress:local-test web | |
| - name: Wait for Application to be Ready (using localhost) | |
| run: | | |
| BASE_URL="http://localhost:5000" | |
| echo "Waiting for the application to be ready on ${BASE_URL}..." | |
| max_attempts=120 | |
| attempt_num=1 | |
| until curl -s --fail "$BASE_URL" > /dev/null; do | |
| if [ "$attempt_num" -eq "$max_attempts" ]; then | |
| echo "Application failed to start after $max_attempts attempts." | |
| docker logs --tail 200 app || true | |
| exit 1 | |
| fi | |
| echo "Waiting for app... attempt $attempt_num" | |
| attempt_num=$((attempt_num+1)) | |
| sleep 1 | |
| done | |
| echo "Application is up! Continuing..." | |
| - name: Build Dev Container | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: .devcontainer/ | |
| platforms: linux/amd64 | |
| load: true | |
| tags: devcontainer:local-test | |
| cache-from: type=gha,scope=devcontainer-linux/amd64 | |
| cache-to: type=gha,mode=max,scope=devcontainer-linux/amd64 | |
| - name: Make E2E script executable | |
| run: chmod +x ./scripts/run-e2e.sh | |
| - name: Run feature-flags spec — ${{ matrix.scenario }} | |
| run: | | |
| docker run --rm \ | |
| --platform linux/amd64 \ | |
| --entrypoint /bin/sh \ | |
| --network host \ | |
| -v /var/run/docker.sock:/var/run/docker.sock \ | |
| -v "$(pwd):/app/" \ | |
| -e IS_RUNNING_IN_GITHUB_ACTIONS=true \ | |
| -e PLAYWRIGHT_BASE_URL=http://localhost:5000 \ | |
| --name devcontainer_flags \ | |
| devcontainer:local-test -c "/app/scripts/run-e2e.sh tests/e2e/featureFlagsRuntime_Test.spec.ts" | |
| - name: Stop Application Container | |
| if: always() | |
| run: | | |
| docker stop app || true | |
| docker rm app || true | |
| - name: Ensure feature-flags results directory exists | |
| if: always() && github.event.inputs.upload_feature_flags_artifacts != 'false' | |
| run: mkdir -p frontend/e2e-test-results | |
| - name: Zip feature-flags results — ${{ matrix.scenario }} | |
| if: always() && github.event.inputs.upload_feature_flags_artifacts != 'false' | |
| run: | | |
| if [ -d "frontend/e2e-test-results" ] && [ "$(ls -A frontend/e2e-test-results)" ]; then | |
| zip -r "feature-flags-${{ matrix.label }}.zip" frontend/e2e-test-results | |
| else | |
| echo "No feature-flags results found, creating an empty zip." | |
| touch "feature-flags-${{ matrix.label }}.zip" | |
| fi | |
| - name: Upload feature-flags artifact — ${{ matrix.scenario }} | |
| if: always() && github.event.inputs.upload_feature_flags_artifacts != 'false' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: feature-flags-${{ matrix.label }} | |
| path: feature-flags-${{ matrix.label }}.zip | |
| retention-days: 3 | |
| test-unverified-formats-api: | |
| # Reader test for the long tail of "Other possible formats" advertised | |
| # by the UI. Brings up the app container, then for each unverified | |
| # extension generates an input file with Pillow, POSTs it to | |
| # /api/compress, downloads the resulting PNG, and asserts it is real | |
| # and non-blank. Blocking — if a format the UI claims to support stops | |
| # working through the public HTTP API in the running image, deploys | |
| # are gated. Read-only formats (no Pillow writer) are skipped with a | |
| # documented reason; skips are not failures. | |
| name: unverified-formats API reader | |
| needs: lint-python | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check out code | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v4 | |
| with: | |
| platforms: all | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Build Application Container | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| load: true | |
| tags: karimz1/imgcompress:local-test | |
| cache-from: type=gha,scope=app-linux/amd64 | |
| cache-to: type=gha,mode=max,scope=app-linux/amd64 | |
| - name: Run Application Container (Host Networking) | |
| run: | | |
| docker run --rm -d \ | |
| --platform linux/amd64 \ | |
| --network host \ | |
| --name app \ | |
| karimz1/imgcompress:local-test web | |
| - name: Wait for Application to be Ready | |
| run: | | |
| BASE_URL="http://localhost:5000" | |
| echo "Waiting for the application to be ready on ${BASE_URL}..." | |
| max_attempts=120 | |
| attempt_num=1 | |
| until curl -s --fail "$BASE_URL/api/health/backend" > /dev/null; do | |
| if [ "$attempt_num" -eq "$max_attempts" ]; then | |
| echo "Application failed to start after $max_attempts attempts." | |
| docker logs --tail 200 app || true | |
| exit 1 | |
| fi | |
| echo "Waiting for app... attempt $attempt_num" | |
| attempt_num=$((attempt_num+1)) | |
| sleep 1 | |
| done | |
| echo "Application is up! Continuing..." | |
| - name: Build Dev Container | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: .devcontainer/ | |
| platforms: linux/amd64 | |
| load: true | |
| tags: devcontainer:local-test | |
| cache-from: type=gha,scope=devcontainer-linux/amd64 | |
| cache-to: type=gha,mode=max,scope=devcontainer-linux/amd64 | |
| - name: Run unverified-formats API reader test | |
| run: | | |
| docker run --rm \ | |
| --platform linux/amd64 \ | |
| --entrypoint /bin/sh \ | |
| --network host \ | |
| -v "$(pwd):/app/" \ | |
| -e IMGCOMPRESS_API_BASE=http://localhost:5000 \ | |
| -e IS_RUNNING_IN_GITHUB_ACTIONS=true \ | |
| --name devcontainer_unverified_api \ | |
| devcontainer:local-test \ | |
| -c ". /venv/bin/activate && pytest tests/integration/test_unverified_formats_api.py -s --tb=short -ra" | |
| - name: Stop Application Container | |
| if: always() | |
| run: | | |
| docker stop app || true | |
| docker rm app || true | |
| deploy-nightly: | |
| needs: | |
| - test-backend | |
| - test-e2e | |
| - test-feature-flags-matrix | |
| - test-unverified-formats-api | |
| if: > | |
| (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| (github.event_name == 'workflow_dispatch' && inputs.deploy_nightly == true) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Trigger Deployment Workflow (nightly) | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPOSITORY: ${{ github.repository }} | |
| DEPLOY_REF: ${{ github.head_ref || github.ref_name }} | |
| run: | | |
| gh api \ | |
| --method POST \ | |
| "repos/${REPOSITORY}/dispatches" \ | |
| -f event_type=deploy \ | |
| -f "client_payload[ref]=${DEPLOY_REF}" | |
| auto-merge-dependabot: | |
| needs: | |
| - test-backend | |
| - test-e2e | |
| - test-feature-flags-matrix | |
| - test-unverified-formats-api | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| # Same-branch sibling job: gates on the PR's author (always | |
| # `dependabot[bot]` for a Dependabot PR), so it stays correct even when | |
| # `imgcompress-chan[bot]` is the actor of the most recent push after | |
| # `/chan-fix` has repaired the branch. Also restricted to same-repo PRs | |
| # so fork PRs can't trigger an auto-merge with the chan App token. | |
| if: > | |
| github.event_name == 'pull_request' && | |
| github.event.pull_request.user.login == 'dependabot[bot]' && | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - name: Mint imgcompress-chan token | |
| id: app-token | |
| uses: actions/create-github-app-token@v3 | |
| with: | |
| app-id: ${{ secrets.IMGCOMPRESS_CHAN_APP_ID }} | |
| private-key: ${{ secrets.IMGCOMPRESS_CHAN_PRIVATE_KEY }} | |
| permission-contents: write | |
| permission-pull-requests: write | |
| - name: Squash-merge Dependabot PR | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| PR_URL: ${{ github.event.pull_request.html_url }} | |
| run: gh pr merge --squash --delete-branch "$PR_URL" | |
| - name: Trigger Deployment Workflow | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| REPOSITORY: ${{ github.repository }} | |
| run: | | |
| gh api \ | |
| --method POST \ | |
| "repos/${REPOSITORY}/dispatches" \ | |
| -f event_type=deploy \ | |
| -f "client_payload[ref]=main" |