From 83ccdc9d0a731310d8f75d5745571b3461aef295 Mon Sep 17 00:00:00 2001 From: CMGS Date: Mon, 19 Oct 2026 13:59:02 +0800 Subject: [PATCH] ci: add PR CI, SHA256SUMS and immutable tag releases --- .github/workflows/build.yaml | 134 +++++++++++++++++++++ .github/workflows/ci.yaml | 15 +++ .github/workflows/master-release.yaml | 92 +++++++++++++++ .github/workflows/release.yaml | 161 ++++---------------------- README.md | 17 ++- 5 files changed, 278 insertions(+), 141 deletions(-) create mode 100644 .github/workflows/build.yaml create mode 100644 .github/workflows/ci.yaml create mode 100644 .github/workflows/master-release.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..499bc4d --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,134 @@ +name: Build + +on: + workflow_call: + +permissions: + contents: read + +jobs: + binaries: + name: Build ${{ matrix.arch }} + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: arm64 + platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v7.0.1 + + - uses: docker/setup-buildx-action@v4.4.1 + + - name: Build builder image (cached FFmpeg layer) + uses: docker/build-push-action@v7.4.0 + with: + context: . + file: docker/Dockerfile.builder + platforms: ${{ matrix.platform }} + load: true + tags: scrcpy-rfb-builder:${{ matrix.arch }} + build-args: | + UBUNTU_PORTS_MIRROR=http://mirror.us.leaseweb.net/ubuntu-ports + cache-from: type=gha,scope=builder-${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=builder-${{ matrix.arch }} + + - name: Build Ubuntu 22.04 binary and run self-test + run: | + docker run --rm \ + --platform "${{ matrix.platform }}" \ + -v "$PWD:/src" \ + "scrcpy-rfb-builder:${{ matrix.arch }}" + + - name: Verify artifact architecture and dependencies + run: | + artifact="dist/scrcpy-rfb-linux-${{ matrix.arch }}" + file "$artifact" + test -x "$artifact" + grep -F "scrcpy-rfb-linux-${{ matrix.arch }}" "$artifact.sha256" + + - name: Build su1000 helper (runs the scrcpy server as the system uid) + run: | + # The builder container writes dist/ as root; take it back so gcc (runner user) can write. + sudo chown -R "$(id -u):$(id -g)" dist + su1000="dist/su1000-linux-${{ matrix.arch }}" + gcc -static -O2 -s -o "$su1000" server/su1000.c + file "$su1000" + ( cd dist && sha256sum "su1000-linux-${{ matrix.arch }}" > "su1000-linux-${{ matrix.arch }}.sha256" ) + + - uses: actions/upload-artifact@v7.0.2 + with: + name: part-scrcpy-rfb-linux-${{ matrix.arch }} + path: | + dist/scrcpy-rfb-linux-${{ matrix.arch }} + dist/scrcpy-rfb-linux-${{ matrix.arch }}.sha256 + dist/su1000-linux-${{ matrix.arch }} + dist/su1000-linux-${{ matrix.arch }}.sha256 + + server: + name: Build patched scrcpy-server + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v7.0.1 + + - name: Build patched scrcpy-server (secure FLAG_SECURE mirror) + run: | + mkdir dist + sudo apt-get update + sudo apt-get install -y --no-install-recommends smali default-jre-headless python3 unzip zip + curl -fsSL https://github.com/Genymobile/scrcpy/releases/download/v4.1/scrcpy-server-v4.1 \ + -o dist/scrcpy-server-secure.jar + echo "deacb991ed2509715160ffdc7907e47b4160eb30d1566217e9047fd5b8850cae dist/scrcpy-server-secure.jar" | sha256sum -c - + cp dist/scrcpy-server-secure.jar dist/scrcpy-server.jar + bash server/patch-scrcpy-secure.sh dist/scrcpy-server-secure.jar + ( cd dist && sha256sum scrcpy-server-secure.jar > scrcpy-server-secure.jar.sha256 \ + && sha256sum scrcpy-server.jar > scrcpy-server.jar.sha256 ) + + - uses: actions/upload-artifact@v7.0.2 + with: + name: part-scrcpy-server + path: | + dist/scrcpy-server-secure.jar + dist/scrcpy-server-secure.jar.sha256 + dist/scrcpy-server.jar + dist/scrcpy-server.jar.sha256 + + dist: + name: Assemble dist + needs: [binaries, server] + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v7.0.1 + + - uses: actions/download-artifact@v8.0.2 + with: + pattern: part-* + path: dist + merge-multiple: true + + - name: Add provenance and checksums + run: | + set -euo pipefail + ffmpeg_commit=$(sed -n 's/^ARG FFMPEG_COMMIT=//p' docker/Dockerfile.builder) + cat > dist/build-info.json < SHA256SUMS) + cat dist/SHA256SUMS + + - uses: actions/upload-artifact@v7.0.2 + with: + name: dist + path: dist/ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..8adf916 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,15 @@ +name: CI + +on: + pull_request: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build: + uses: ./.github/workflows/build.yaml diff --git a/.github/workflows/master-release.yaml b/.github/workflows/master-release.yaml new file mode 100644 index 0000000..f367b85 --- /dev/null +++ b/.github/workflows/master-release.yaml @@ -0,0 +1,92 @@ +name: Build and Release Master + +on: + push: + branches: [master] + workflow_dispatch: + +permissions: + contents: write + packages: write + +concurrency: + group: scrcpy-rfb-master-release + cancel-in-progress: true + +jobs: + build: + uses: ./.github/workflows/build.yaml + + release: + name: Update master prerelease + needs: build + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v7.0.1 + with: + fetch-depth: 0 + + - uses: actions/download-artifact@v8.0.2 + with: + name: dist + path: dist + + - name: Create master release + uses: softprops/action-gh-release@v3.0.3 + with: + tag_name: master + target_commitish: ${{ github.sha }} + name: Master Build + body: | + Branch: `${{ github.ref_name }}` + Commit: `${{ github.sha }}` + Workflow Run: `${{ github.run_id }}` + files: dist/* + prerelease: true + make_latest: false + overwrite_files: true + fail_on_unmatched_files: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Move master tag to current commit + run: | + git tag -f master "${GITHUB_SHA}" + git push origin refs/tags/master --force + + docker: + name: Push container image + needs: build + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v7.0.1 + + - uses: actions/download-artifact@v8.0.2 + with: + name: dist + path: dist + + - name: Make binaries executable + run: chmod +x dist/scrcpy-rfb-linux-* + + - uses: docker/setup-qemu-action@v4.4.0 + + - uses: docker/setup-buildx-action@v4.4.1 + + - uses: docker/login-action@v4.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: docker/build-push-action@v7.4.0 + with: + context: . + file: docker/Dockerfile.runtime + platforms: linux/amd64,linux/arm64 + push: true + build-args: | + UBUNTU_PORTS_MIRROR=http://mirror.us.leaseweb.net/ubuntu-ports + tags: | + ghcr.io/${{ github.repository }}:master + ghcr.io/${{ github.repository }}:${{ github.sha }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index cb1038d..0497b8b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,186 +1,74 @@ -name: Build and Release Master +name: Release on: push: - branches: [master] - workflow_dispatch: + tags: ['master-*'] permissions: contents: write packages: write concurrency: - group: scrcpy-rfb-master-release - cancel-in-progress: true + group: release-${{ github.ref }} + cancel-in-progress: false jobs: build: - name: Build ${{ matrix.arch }} - strategy: - fail-fast: false - matrix: - include: - - arch: amd64 - platform: linux/amd64 - runner: ubuntu-24.04 - - arch: arm64 - platform: linux/arm64 - runner: ubuntu-24.04-arm - runs-on: ${{ matrix.runner }} - steps: - - uses: actions/checkout@v7 - - - uses: docker/setup-buildx-action@v3 - - - name: Build builder image (cached FFmpeg layer) - uses: docker/build-push-action@v6 - with: - context: . - file: docker/Dockerfile.builder - platforms: ${{ matrix.platform }} - load: true - tags: scrcpy-rfb-builder:${{ matrix.arch }} - build-args: | - UBUNTU_PORTS_MIRROR=http://mirror.us.leaseweb.net/ubuntu-ports - cache-from: type=gha,scope=builder-${{ matrix.arch }} - cache-to: type=gha,mode=max,scope=builder-${{ matrix.arch }} - - - name: Build Ubuntu 22.04 binary - run: | - docker run --rm \ - --platform "${{ matrix.platform }}" \ - -v "$PWD:/src" \ - "scrcpy-rfb-builder:${{ matrix.arch }}" - - - name: Verify artifact architecture and dependencies - run: | - artifact="dist/scrcpy-rfb-linux-${{ matrix.arch }}" - file "$artifact" - test -x "$artifact" - grep -F "scrcpy-rfb-linux-${{ matrix.arch }}" "$artifact.sha256" - - - name: Build su1000 helper (runs the scrcpy server as the system uid) - run: | - # The builder container writes dist/ as root; take it back so gcc (runner user) can write. - sudo chown -R "$(id -u):$(id -g)" dist - su1000="dist/su1000-linux-${{ matrix.arch }}" - gcc -static -O2 -s -o "$su1000" server/su1000.c - file "$su1000" - ( cd dist && sha256sum "su1000-linux-${{ matrix.arch }}" > "su1000-linux-${{ matrix.arch }}.sha256" ) - - - uses: actions/upload-artifact@v7 - with: - name: scrcpy-rfb-linux-${{ matrix.arch }} - path: | - dist/scrcpy-rfb-linux-${{ matrix.arch }} - dist/scrcpy-rfb-linux-${{ matrix.arch }}.sha256 - dist/su1000-linux-${{ matrix.arch }} - dist/su1000-linux-${{ matrix.arch }}.sha256 + uses: ./.github/workflows/build.yaml release: - name: Update master prerelease + name: Publish ${{ github.ref_name }} needs: build runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v7 - with: - fetch-depth: 0 - - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@v8.0.2 with: - pattern: scrcpy-rfb-linux-* + name: dist path: dist - merge-multiple: true - - - name: Generate build metadata - run: | - ffmpeg_commit=$(sed -n 's/^ARG FFMPEG_COMMIT=//p' docker/Dockerfile.builder) - cat > dist/build-info.json < scrcpy-server-secure.jar.sha256 \ - && sha256sum scrcpy-server.jar > scrcpy-server.jar.sha256 ) - - - name: Create master release - uses: softprops/action-gh-release@v3 + - name: Create release + uses: softprops/action-gh-release@v3.0.3 with: - tag_name: master - target_commitish: ${{ github.sha }} - name: Master Build + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} body: | - Branch: `${{ github.ref_name }}` + Tag: `${{ github.ref_name }}` Commit: `${{ github.sha }}` Workflow Run: `${{ github.run_id }}` - files: | - dist/scrcpy-rfb-linux-amd64 - dist/scrcpy-rfb-linux-amd64.sha256 - dist/scrcpy-rfb-linux-arm64 - dist/scrcpy-rfb-linux-arm64.sha256 - dist/su1000-linux-amd64 - dist/su1000-linux-amd64.sha256 - dist/su1000-linux-arm64 - dist/su1000-linux-arm64.sha256 - dist/scrcpy-server-secure.jar - dist/scrcpy-server-secure.jar.sha256 - dist/scrcpy-server.jar - dist/scrcpy-server.jar.sha256 - dist/build-info.json - prerelease: true + files: dist/* + prerelease: false make_latest: false - overwrite_files: true + overwrite_files: false fail_on_unmatched_files: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Move master tag to current commit - run: | - git tag -f master "${GITHUB_SHA}" - git push origin refs/tags/master --force - docker: name: Push container image needs: build runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v7.0.1 - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@v8.0.2 with: - pattern: scrcpy-rfb-linux-* + name: dist path: dist - merge-multiple: true - name: Make binaries executable run: chmod +x dist/scrcpy-rfb-linux-* - - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-qemu-action@v4.4.0 - - uses: docker/setup-buildx-action@v3 + - uses: docker/setup-buildx-action@v4.4.1 - - uses: docker/login-action@v3 + - uses: docker/login-action@v4.6.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: docker/build-push-action@v6 + - uses: docker/build-push-action@v7.4.0 with: context: . file: docker/Dockerfile.runtime @@ -189,5 +77,4 @@ jobs: build-args: | UBUNTU_PORTS_MIRROR=http://mirror.us.leaseweb.net/ubuntu-ports tags: | - ghcr.io/${{ github.repository }}:master - ghcr.io/${{ github.repository }}:${{ github.sha }} + ghcr.io/${{ github.repository }}:${{ github.ref_name }} diff --git a/README.md b/README.md index 2a9c6b1..00082fd 100644 --- a/README.md +++ b/README.md @@ -36,13 +36,22 @@ make # cmake configure + build into build/ make test # build + run the self tests ``` -Pushes to `master` publish, via GitHub Actions: +Every pull request builds both architectures and runs the self tests. Pushes +to `master` publish, via GitHub Actions: - `scrcpy-rfb-linux-amd64` / `-arm64` binaries, `su1000`, the patched - `scrcpy-server-secure.jar` and the unpatched `scrcpy-server.jar`, checksums - and `build-info.json` to the moving `master` prerelease; + `scrcpy-server-secure.jar` and the unpatched `scrcpy-server.jar`, plus + `SHA256SUMS` and `build-info.json`, to the moving `master` prerelease; - a multi-arch container image at `ghcr.io/cocoonstack/scrcpy-rfb:master` - (also tagged with the commit SHA): + (also tagged with the commit SHA). + +Pushing a tag `master-<9-char sha>` publishes the same assets once to a release +of that name and never replaces them; pin that tag, never the moving `master` +release, and verify the files against its `SHA256SUMS`. The container image is +tagged with the release tag. + +The moving release's tag and the default branch are both named `master`; scripts +that push or reset the branch must spell it `refs/heads/master`. ```sh docker run --rm --network host ghcr.io/cocoonstack/scrcpy-rfb:master \