From 21ae9d5b7eb3a980a85c07d3e3b000568dce2f05 Mon Sep 17 00:00:00 2001 From: Anton Date: Wed, 11 Mar 2026 20:07:05 +0000 Subject: [PATCH] Rewrite CI from scratch: clean build + scheduled update, remove deb workflow --- .github/workflows/build.yaml | 188 +++++------------------- .github/workflows/deb.yaml | 77 ---------- .github/workflows/scheduled-update.yaml | 150 ++++--------------- deb/Dockerfile | 29 ---- deb/PACKAGE | 1 - deb/entrypoint.sh | 49 ------ deb/gpgparams | 8 - deb/install.sh | 16 -- 8 files changed, 65 insertions(+), 453 deletions(-) delete mode 100644 .github/workflows/deb.yaml delete mode 100644 deb/Dockerfile delete mode 100644 deb/PACKAGE delete mode 100644 deb/entrypoint.sh delete mode 100644 deb/gpgparams delete mode 100644 deb/install.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c7a5f2d..c84fefe 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,14 +1,15 @@ -name: build from source +name: Build and Push on: push: + branches: [master] paths: - .github/workflows/build.yaml - - build/* + - build/** pull_request: paths: - .github/workflows/build.yaml - - build/* + - build/** workflow_dispatch: permissions: @@ -17,181 +18,58 @@ permissions: security-events: write env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge + IMAGE: ghcr.io/${{ github.repository_owner }}/protonmail-bridge jobs: resolve-version: runs-on: ubuntu-latest outputs: - version: ${{ steps.resolve.outputs.version }} + version: ${{ steps.version.outputs.version }} steps: - name: Get latest upstream release - id: resolve + id: version run: | - latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "version=$latest" >> $GITHUB_OUTPUT + version=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "version=$version" >> $GITHUB_OUTPUT + echo "Resolved version: $version" - test: - runs-on: ubuntu-latest + build: needs: resolve-version - if: github.event_name == 'pull_request' + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} + - uses: docker/setup-buildx-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + if: github.event_name != 'pull_request' with: - driver: docker + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Build uses: docker/build-push-action@v6 with: context: ./build - file: ./build/Dockerfile - load: true - tags: "protonmail-bridge:test" - build-args: | - version=${{ needs.resolve-version.outputs.version }} - - - name: Run Trivy vulnerability scan - continue-on-error: true - run: | - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ - aquasec/trivy:latest image \ - --severity CRITICAL,HIGH \ - --exit-code 0 \ - protonmail-bridge:test - - build: - runs-on: ubuntu-latest - needs: resolve-version - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64/v8 - - linux/arm/v7 - - linux/riscv64 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push by digest - id: build - uses: docker/build-push-action@v6 - with: - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true - context: ./build - file: ./build/Dockerfile - provenance: false - sbom: false - build-args: | - version=${{ needs.resolve-version.outputs.version }} - - - name: Export digest - run: | - mkdir -p ${{ runner.temp }}/digests - digest="${{ steps.build.outputs.digest }}" - touch "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - resolve-version - - build - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/digests - pattern: digests-* - merge-multiple: true - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: network=host - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} + push: ${{ github.event_name != 'pull_request' }} + load: ${{ github.event_name == 'pull_request' }} tags: | - type=raw,enable=true,value=${{ needs.resolve-version.outputs.version }}-build - type=raw,enable=true,value=build - type=raw,enable=true,value=latest + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} + build-args: | + version=${{ needs.resolve-version.outputs.version }} - - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - - - name: Run Trivy vulnerability scan + - name: Trivy scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build" - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' + image-ref: ${{ env.IMAGE }}:${{ needs.resolve-version.outputs.version }} + format: sarif + output: trivy-results.sarif + severity: CRITICAL,HIGH - - name: Upload Trivy scan SARIF report + - name: Upload Trivy results uses: github/codeql-action/upload-sarif@v3 + if: always() with: - sarif_file: 'trivy-results.sarif' - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.resolve-version.outputs.version }}-build + sarif_file: trivy-results.sarif diff --git a/.github/workflows/deb.yaml b/.github/workflows/deb.yaml deleted file mode 100644 index b938d12..0000000 --- a/.github/workflows/deb.yaml +++ /dev/null @@ -1,77 +0,0 @@ -name: pack from deb - -on: - push: - paths: - - .github/workflows/deb.yaml - - deb/* - - VERSION - pull_request: - paths: - - .github/workflows/deb.yaml - - deb/* - workflow_dispatch: - -env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge - -jobs: - deb: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set version - run: echo "version=$(cat VERSION)" >> $GITHUB_ENV - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build image without push - uses: docker/build-push-action@v6 - with: - context: ./deb - file: ./deb/Dockerfile - load: true - tags: protonmail-bridge:latest - - - name: Run Trivy vulnerability scan - uses: aquasecurity/trivy-action@0.30.0 - with: - image-ref: protonmail-bridge:latest - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' - - - name: Upload Trivy scan SARIF report - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' - - - name: Login to GHCR - uses: docker/login-action@v3 - if: github.event_name != 'pull_request' - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Push image - uses: docker/build-push-action@v6 - if: github.event_name != 'pull_request' - with: - context: ./deb - file: ./deb/Dockerfile - tags: | - ${{ env.GHCR_REPO }}:latest - ${{ env.GHCR_REPO }}:${{ env.version }} - labels: ${{ steps.meta.outputs.labels }} - push: true diff --git a/.github/workflows/scheduled-update.yaml b/.github/workflows/scheduled-update.yaml index 34b19d4..6b8a331 100644 --- a/.github/workflows/scheduled-update.yaml +++ b/.github/workflows/scheduled-update.yaml @@ -1,4 +1,4 @@ -name: scheduled version check +name: Check for new upstream release on: schedule: @@ -10,156 +10,70 @@ permissions: security-events: write env: - GHCR_REPO: ghcr.io/trent-maetzold/protonmail-bridge + IMAGE: ghcr.io/${{ github.repository_owner }}/protonmail-bridge jobs: check: runs-on: ubuntu-latest outputs: version: ${{ steps.check.outputs.version }} - build_needed: ${{ steps.check.outputs.build_needed }} + needed: ${{ steps.check.outputs.needed }} steps: - - name: Check for new upstream version + - name: Compare upstream to registry id: check run: | - latest=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') - echo "Latest upstream: $latest" - echo "version=$latest" >> $GITHUB_OUTPUT + version=$(curl -s https://api.github.com/repos/ProtonMail/proton-bridge/releases/latest | jq -r '.tag_name') + echo "version=$version" >> $GITHUB_OUTPUT - token=$(curl -s "https://ghcr.io/token?scope=repository:trent-maetzold/protonmail-bridge:pull" | jq -r '.token') - tags=$(curl -s -H "Authorization: Bearer $token" "https://ghcr.io/v2/trent-maetzold/protonmail-bridge/tags/list" | jq -r '.tags[]?' 2>/dev/null || echo "") + token=$(curl -s "https://ghcr.io/token?scope=repository:${{ github.repository_owner }}/protonmail-bridge:pull" | jq -r '.token') + exists=$(curl -s -o /dev/null -w '%{http_code}' \ + -H "Authorization: Bearer $token" \ + "https://ghcr.io/v2/${{ github.repository_owner }}/protonmail-bridge/manifests/$version") - if echo "$tags" | grep -qx "${latest}-build"; then - echo "Version ${latest} already built" - echo "build_needed=false" >> $GITHUB_OUTPUT + if [ "$exists" = "200" ]; then + echo "needed=false" >> $GITHUB_OUTPUT + echo "$version already exists in registry" else - echo "New version ${latest} detected" - echo "build_needed=true" >> $GITHUB_OUTPUT + echo "needed=true" >> $GITHUB_OUTPUT + echo "New version $version — building" fi build: needs: check - if: needs.check.outputs.build_needed == 'true' - strategy: - fail-fast: false - matrix: - platform: - - linux/amd64 - - linux/arm64/v8 - - linux/arm/v7 - - linux/riscv64 + if: needs.check.outputs.needed == 'true' runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Prepare - run: | - platform=${{ matrix.platform }} - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - uses: docker/setup-buildx-action@v3 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - - - name: Login to GHCR - uses: docker/login-action@v3 + - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push by digest - id: build + - name: Build and push uses: docker/build-push-action@v6 with: - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} - outputs: type=image,"name=${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true context: ./build - file: ./build/Dockerfile - provenance: false - sbom: false + push: true + tags: | + ${{ env.IMAGE }}:latest + ${{ env.IMAGE }}:${{ needs.check.outputs.version }} build-args: | version=${{ needs.check.outputs.version }} - - name: Export digest - run: | - mkdir -p ${{ runner.temp }}/digests - digest="${{ steps.build.outputs.digest }}" - touch "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - runs-on: ubuntu-latest - needs: - - check - - build - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: ${{ runner.temp }}/digests - pattern: digests-* - merge-multiple: true - - - name: Login to GHCR - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - driver-opts: network=host - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.GHCR_REPO }} - tags: | - type=raw,enable=true,value=${{ needs.check.outputs.version }}-build - type=raw,enable=true,value=build - type=raw,enable=true,value=latest - - - name: Create manifest list and push - working-directory: ${{ runner.temp }}/digests - run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *) - - - name: Run Trivy vulnerability scan + - name: Trivy scan uses: aquasecurity/trivy-action@0.30.0 with: - image-ref: "${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build" - format: 'sarif' - exit-code: 0 - severity: 'CRITICAL,HIGH' - output: 'trivy-results.sarif' + image-ref: ${{ env.IMAGE }}:${{ needs.check.outputs.version }} + format: sarif + output: trivy-results.sarif + severity: CRITICAL,HIGH - - name: Upload Trivy scan SARIF report + - name: Upload Trivy results uses: github/codeql-action/upload-sarif@v3 + if: always() with: - sarif_file: 'trivy-results.sarif' - - - name: Inspect image - run: | - docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ needs.check.outputs.version }}-build + sarif_file: trivy-results.sarif diff --git a/deb/Dockerfile b/deb/Dockerfile deleted file mode 100644 index 383f8b7..0000000 --- a/deb/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -### The Deb install is just a repack of the official ProtonMail Bridge deb package with less dependencies. -### I recommend you don't use this. It's here for legacy reasons. - -FROM debian:trixie-slim AS build - -COPY install.sh PACKAGE / -RUN apt-get update && apt-get install -y wget binutils - -# Repack deb (removes unnecessary dependencies and produces /protonmail.deb) -RUN bash /install.sh - -FROM debian:trixie-slim -LABEL maintainer="Trent Maetzold " -LABEL org.opencontainers.image.source="https://github.com/trent-maetzold/protonmail-bridge-docker" - -EXPOSE 25/tcp -EXPOSE 143/tcp - -WORKDIR /protonmail - -# Copy bash scripts -COPY gpgparams entrypoint.sh PACKAGE /protonmail/ -COPY --from=build /protonmail.deb /tmp/protonmail.deb - -RUN apt-get update \ - && apt-get install -y --no-install-recommends /tmp/protonmail.deb socat pass libsecret-1-0 ca-certificates procps \ - && rm -rf /var/lib/apt/lists/* - -CMD ["bash", "/protonmail/entrypoint.sh"] diff --git a/deb/PACKAGE b/deb/PACKAGE deleted file mode 100644 index 6d4eacd..0000000 --- a/deb/PACKAGE +++ /dev/null @@ -1 +0,0 @@ -https://github.com/ProtonMail/proton-bridge/releases/download/v3.22.0/protonmail-bridge_3.22.0-1_amd64.deb \ No newline at end of file diff --git a/deb/entrypoint.sh b/deb/entrypoint.sh deleted file mode 100644 index 13637e5..0000000 --- a/deb/entrypoint.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -set -ex - -# Initialize -if [[ $1 == init ]]; then - - # # Parse parameters - # TFP="" # Default empty two factor passcode - # shift # skip `init` - # while [[ $# -gt 0 ]]; do - # key="$1" - # case $key in - # -u|--username) - # USERNAME="$2" - # ;; - # -p|--password) - # PASSWORD="$2" - # ;; - # -t|--twofactor) - # TWOFACTOR="$2" - # ;; - # esac - # shift - # shift - # done - - # Initialize pass - gpg --generate-key --batch /protonmail/gpgparams - pass init pass-key - - # Login - protonmail-bridge --cli - -else - - # socat will make the conn appear to come from 127.0.0.1 - # ProtonMail Bridge currently expects that. - # It also allows us to bind to the real ports :) - socat TCP-LISTEN:25,fork TCP:127.0.0.1:1025 & - socat TCP-LISTEN:143,fork TCP:127.0.0.1:1143 & - - # Start protonmail - # Fake a terminal, so it does not quit because of EOF... - rm -f faketty - mkfifo faketty - cat faketty | protonmail-bridge --cli - -fi diff --git a/deb/gpgparams b/deb/gpgparams deleted file mode 100644 index 355568e..0000000 --- a/deb/gpgparams +++ /dev/null @@ -1,8 +0,0 @@ -%no-protection -%echo Generating a basic OpenPGP key -Key-Type: RSA -Key-Length: 2048 -Name-Real: pass-key -Expire-Date: 0 -%commit -%echo done diff --git a/deb/install.sh b/deb/install.sh deleted file mode 100644 index 9593725..0000000 --- a/deb/install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -ex - -# Repack deb (remove unnecessary dependencies) -mkdir deb -wget -i /PACKAGE -O /deb/protonmail.deb -cd deb -ar x -v protonmail.deb -mkdir control -tar zxvf control.tar.gz -C control -sed -i "s/^Depends: .*$/Depends: libgl1, libc6, libsecret-1-0, libstdc++6, libgcc1/" control/control -cd control -tar zcvf ../control.tar.gz . -cd ../ - -ar rcs -v /protonmail.deb debian-binary control.tar.gz data.tar.gz