diff --git a/.github/actions/docker-build-platform/action.yml b/.github/actions/docker-build-platform/action.yml new file mode 100644 index 0000000..1ad27ff --- /dev/null +++ b/.github/actions/docker-build-platform/action.yml @@ -0,0 +1,70 @@ +name: 'Docker Build Platform' +description: 'Builds and pushes a single-platform Docker image by digest.' +runs: + using: 'composite' + steps: + - name: Prepare platform pair + id: prepare + shell: bash + run: | + platform="${{ inputs.platform }}" + echo "platform_pair=${platform//\//-}" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ inputs.ghcr_username }} + password: ${{ inputs.ghcr_token }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + env: + BUILDKIT_PROGRESS: plain + with: + context: ${{ inputs.context }} + file: ${{ inputs.file }} + platforms: ${{ inputs.platform }} + outputs: type=image,"name=${{ inputs.image_name }}",push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=build-${{ steps.prepare.outputs.platform_pair }} + cache-to: type=gha,mode=max,scope=build-${{ steps.prepare.outputs.platform_pair }} + + - name: Export digest + shell: bash + run: | + mkdir -p "${{ runner.temp }}/digests" + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v7 + with: + name: digests-${{ steps.prepare.outputs.platform_pair }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + +inputs: + ghcr_username: + required: true + description: 'GHCR username' + ghcr_token: + required: true + description: 'GHCR token' + context: + required: true + description: 'Build context' + file: + required: true + description: 'Dockerfile path' + platform: + required: true + description: 'Target platform (e.g. linux/amd64)' + image_name: + required: true + description: 'Image name without tag (e.g. ghcr.io/gameyfin/gameyfin)' + diff --git a/.github/actions/docker-build-push/action.yml b/.github/actions/docker-create-manifest/action.yml similarity index 53% rename from .github/actions/docker-build-push/action.yml rename to .github/actions/docker-create-manifest/action.yml index a2c2177..a0a3e33 100644 --- a/.github/actions/docker-build-push/action.yml +++ b/.github/actions/docker-create-manifest/action.yml @@ -1,8 +1,15 @@ -name: 'Docker Build and Push' -description: 'Builds and pushes Docker images to GHCR with flexible tagging.' +name: 'Docker Create Manifest' +description: 'Creates and pushes a multi-arch manifest from per-platform digests.' runs: using: 'composite' steps: + - name: Download digests + uses: actions/download-artifact@v8 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -24,16 +31,19 @@ runs: COMBINED_TAGS="$DEFAULT_TAGS,$UBUNTU_TAGS" echo "combined_tags=$COMBINED_TAGS" >> $GITHUB_OUTPUT - - name: Build and push Docker image (Ubuntu) - uses: docker/build-push-action@v5 - with: - context: ${{ inputs.context }} - file: docker/Dockerfile.ubuntu - platforms: ${{ inputs.platforms }} - push: true - tags: ${{ steps.combined_tags.outputs.combined_tags }} - cache-from: type=gha - cache-to: type=gha + - name: Create manifest list and push + shell: bash + working-directory: ${{ runner.temp }}/digests + run: | + TAG_ARGS=$(echo "${{ steps.combined_tags.outputs.combined_tags }}" | tr ',' '\n' | xargs -I {} echo "-t {}" | tr '\n' ' ') + docker buildx imagetools create $TAG_ARGS \ + $(printf '${{ inputs.image_name }}@sha256:%s ' *) + + - name: Inspect image + shell: bash + run: | + TAG=$(echo "${{ inputs.tags }}" | cut -d',' -f1) + docker buildx imagetools inspect "$TAG" inputs: ghcr_username: @@ -42,16 +52,10 @@ inputs: ghcr_token: required: true description: 'GHCR token' - context: - required: true - description: 'Build context' - dockerfile: - required: true - description: 'Dockerfile path' - platforms: - required: true - description: 'Platforms to build for' tags: required: true description: 'Comma-separated list of image tags' + image_name: + required: true + description: 'Image name without tag (e.g. ghcr.io/gameyfin/gameyfin)' diff --git a/.github/prompts/sonar.prompt.md b/.github/prompts/sonar.prompt.md new file mode 100644 index 0000000..a245bd8 --- /dev/null +++ b/.github/prompts/sonar.prompt.md @@ -0,0 +1,7 @@ +--- +description: Analyze and fix Sonar issues reported in this file +--- + +Sonar reported some issues in this file, please fix them. +Use the "list warnings/errors" command to get the list of issues, and then fix them one by one. + diff --git a/.github/workflows/docker-fix.yml b/.github/workflows/docker-fix.yml index fe6cef5..2b421b6 100644 --- a/.github/workflows/docker-fix.yml +++ b/.github/workflows/docker-fix.yml @@ -34,16 +34,24 @@ jobs: report_paths: '**/build/test-results/test/TEST-*.xml' - name: Upload build outputs - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: build-outputs path: | app/build/libs/** plugins/**/build/libs/**/*.jar - docker: + docker-build: needs: build - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-24.04 + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} permissions: packages: write steps: @@ -51,11 +59,30 @@ jobs: uses: actions/checkout@v6 - name: Download build outputs - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: build-outputs path: . + - name: Build platform image + uses: ./.github/actions/docker-build-platform + with: + ghcr_username: ${{ github.actor }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + context: . + file: docker/Dockerfile.ubuntu + platform: ${{ matrix.platform }} + image_name: ghcr.io/gameyfin/gameyfin + + docker-merge: + needs: [build, docker-build] + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + - name: Extract tag from branch name id: extract_tag run: | @@ -63,12 +90,10 @@ jobs: TAG="${BRANCH_NAME#fix/}" echo "tag=$TAG" >> $GITHUB_OUTPUT - - name: Build and push Docker image - uses: ./.github/actions/docker-build-push + - name: Create and push manifest + uses: ./.github/actions/docker-create-manifest with: ghcr_username: ${{ github.actor }} ghcr_token: ${{ secrets.GITHUB_TOKEN }} - context: . - dockerfile: docker/Dockerfile - platforms: linux/arm64/v8,linux/amd64 tags: ghcr.io/gameyfin/gameyfin:${{ steps.extract_tag.outputs.tag }} + image_name: ghcr.io/gameyfin/gameyfin diff --git a/.github/workflows/docker-preview.yml b/.github/workflows/docker-preview.yml index b3fbe77..f30c4b6 100644 --- a/.github/workflows/docker-preview.yml +++ b/.github/workflows/docker-preview.yml @@ -64,16 +64,24 @@ jobs: report_paths: '**/build/test-results/test/TEST-*.xml' - name: Upload build outputs - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: build-outputs path: | app/build/libs/** plugins/**/build/libs/**/*.jar - docker: + docker-build: needs: build - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-24.04 + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} permissions: packages: write steps: @@ -83,17 +91,36 @@ jobs: fetch-depth: 0 - name: Download build outputs - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: build-outputs path: . - - name: Build and push Docker image - uses: ./.github/actions/docker-build-push + - name: Build platform image + uses: ./.github/actions/docker-build-platform with: ghcr_username: ${{ github.actor }} ghcr_token: ${{ secrets.GITHUB_TOKEN }} context: . - dockerfile: docker/Dockerfile - platforms: linux/arm64/v8,linux/amd64 + file: docker/Dockerfile.ubuntu + platform: ${{ matrix.platform }} + image_name: ghcr.io/gameyfin/gameyfin + + docker-merge: + needs: [build, docker-build] + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Create and push manifest + uses: ./.github/actions/docker-create-manifest + with: + ghcr_username: ${{ github.actor }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} tags: ghcr.io/gameyfin/gameyfin:${{ needs.build.outputs.version }} + image_name: ghcr.io/gameyfin/gameyfin diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9675e7a..aa92261 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: jq ".version = \"$RELEASE_VERSION\"" app/package.json > app/package.json.tmp && mv app/package.json.tmp app/package.json - name: Upload modified files - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: modified-files path: | @@ -71,7 +71,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: modified-files @@ -95,16 +95,24 @@ jobs: report_paths: '**/build/test-results/test/TEST-*.xml' - name: Upload build outputs - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: build-outputs path: | app/build/libs/** plugins/**/build/libs/**/*.jar - docker: - needs: [ setup, build ] - runs-on: ubuntu-latest + docker-build: + needs: [setup, build] + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-24.04 + - platform: linux/arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} permissions: packages: write steps: @@ -114,16 +122,37 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: modified-files - name: Download build outputs - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: build-outputs path: . + - name: Build platform image + uses: ./.github/actions/docker-build-platform + with: + ghcr_username: ${{ github.actor }} + ghcr_token: ${{ secrets.GITHUB_TOKEN }} + context: . + file: docker/Dockerfile.ubuntu + platform: ${{ matrix.platform }} + image_name: ghcr.io/gameyfin/gameyfin + + docker-merge: + needs: [setup, docker-build] + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + - name: Generate container image tags id: docker_tags run: | @@ -138,15 +167,13 @@ jobs: TAGS="$GHCR_TAGS" echo "tags=$TAGS" >> $GITHUB_OUTPUT - - name: Build and push Docker image - uses: ./.github/actions/docker-build-push + - name: Create and push manifest + uses: ./.github/actions/docker-create-manifest with: ghcr_username: ${{ github.actor }} ghcr_token: ${{ secrets.GITHUB_TOKEN }} - context: . - dockerfile: docker/Dockerfile - platforms: linux/arm64/v8,linux/amd64 tags: ${{ steps.docker_tags.outputs.tags }} + image_name: ghcr.io/gameyfin/gameyfin plugin_api: needs: setup @@ -158,7 +185,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: modified-files @@ -180,7 +207,7 @@ jobs: ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVENCENTRAL_PASSWORD }} finalize: - needs: [ docker, plugin_api ] + needs: [ docker-merge, plugin_api ] runs-on: ubuntu-latest steps: - name: Checkout code @@ -189,7 +216,7 @@ jobs: fetch-depth: 0 - name: Download modified files - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: modified-files diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 2044cb6..18dea99 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -28,7 +28,7 @@ jobs: uses: gradle/actions/setup-gradle@v5 - name: Cache SonarCloud packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar diff --git a/.gitignore b/.gitignore index 4104262..2ad9e91 100644 --- a/.gitignore +++ b/.gitignore @@ -57,5 +57,6 @@ out/ *.state.json /plugins/data/ /plugins/state/ +/plugins/**/*.jar /plugindata/ /docker-debug/ diff --git a/.run/Gameyfin.run.xml b/.run/Gameyfin.run.xml index a58e849..b193d89 100644 --- a/.run/Gameyfin.run.xml +++ b/.run/Gameyfin.run.xml @@ -9,7 +9,7 @@