From 3a932d953f9416c34bbc1e130dabd0a1da097d17 Mon Sep 17 00:00:00 2001 From: Simon <9295182+grimsi@users.noreply.github.com> Date: Fri, 13 Mar 2026 15:34:06 +0100 Subject: [PATCH] Release 2.4.0 (#870) * chore: bump version to v2.4.0-preview * Bump actions/cache from 4 to 5 (#865) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Increase maximum DB connection pool size (#876) Increase DB connection timeout * Disable length limit for DB field PLUGIN_CONFIG.value (#875) * Bump actions/cache from 4 to 5 (#871) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/download-artifact from 7 to 8 (#882) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/upload-artifact from 6 to 7 (#881) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/cache from 4 to 5 (#878) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Dont perform scans if no metadata plugins are enabled (#877) * Dont perform scans if no metadata plugins are enabled * Fix tests * Add PluginServiceTest.kt * Fix Sonar finding * Fix malformed external links (#886) * Fix external links being treated as internal * chore: bump version to v856-malformed-external-links-preview * Update JVM in Dockerfile to Java 25 * Revert incorrect version update * Allow loading .jar plugins in development mode (#885) * Allow loading .jar plugins in development mode * Remove unnecessary mock * Fix unit test * Add unit tests * Fix/879 add info and reset to config options (#887) * Fix gog.sh script * Add "description" property to ConfigProperties.kt Add InfoPopup.tsx and ResetToDefaultButton.tsx in UI * Bump actions/download-artifact from 7 to 8 (#891) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/cache from 4 to 5 (#890) Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump actions/upload-artifact from 6 to 7 (#889) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Improve memory usage and performance (#888) mprove memory usage and performance by: * Using AOT cache * Using tuned JAVA_OPTIONS * Session timeout * Jetty threadpool * DB batch size * DB pool size * Library scanning * Make scan-concurrency configurable * Log retention * Off-load image processing to disk instead of RAM * Fix bug in PluginState * Update dependency version for ksp * Fix race condition preventing plugins from starting * Show remaining time (estimation) for library scans * Add unit test for plugin loading bugfix * Add unit tests for ImageService calculateBlurHash * Make username claim configurable (#895) Add fallbacks to resolve username * Fix sonar issues (#894) * Add custom "/sonar" command to GH copilot * Add Sonar plugin integration * Fix issues reported by Sonar * Ignore Sonar warning about AES/ECB * Add unit tests for GameyfinPluginManager * Add unit tests for GameService * Add more unit tests for GameService * Improve library card layout (#896) * Fix title not being centered * Add buttons to scan all libraries * Disable AVX for AOT cache training * Improve AOT cache training * Fix tests * Change output type of Docker Build CI action * Increase MAX_WAIT of aot-training to 5min * Optimize Docker CI pipeline * Add Sonar badges to README.md * Add custom metrics (downloads & scans) * Optimize DB connection & add cache for images * Adjusted logging on startup * * Show message on start page when no libraries/games are available * Disable "Scan" buttons when no metadata plugin is enabled * Fix thread pinning causing deadlocks * Pre-populate image cache at startup * Show "Loading" spinner while loading * Optimize static file serving (images) * Switch back to Tomcat (from Jetty) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../actions/docker-build-platform/action.yml | 70 + .../action.yml | 46 +- .github/prompts/sonar.prompt.md | 7 + .github/workflows/docker-fix.yml | 43 +- .github/workflows/docker-preview.yml | 43 +- .github/workflows/release.yml | 59 +- .github/workflows/sonar.yml | 2 +- .gitignore | 1 + .run/Gameyfin.run.xml | 2 +- .sonarlint/connectedMode.json | 5 + README.md | 21 +- app/build.gradle.kts | 17 +- app/package-lock.json | 1992 ++++++++--------- app/package.json | 228 +- app/src/main/bundles/prod.bundle | Bin 1970352 -> 2235847 bytes app/src/main/frontend/App.tsx | 10 +- .../administration/ConfigFormField.tsx | 54 +- .../administration/GameManagement.tsx | 26 +- .../components/administration/InfoPopup.tsx | 33 + .../administration/ProfileManagement.tsx | 29 +- .../administration/ResetToDefaultButton.tsx | 47 + .../administration/SecurityManagement.tsx | 7 +- .../administration/withConfigPage.tsx | 27 +- .../general/ScanProgressPopover.tsx | 55 +- .../general/cards/LibraryOverviewCard.tsx | 12 +- .../components/general/input/ArrayInput.tsx | 28 +- .../general/input/CheckboxInput.tsx | 42 +- .../general/input/DatePickerInput.tsx | 15 +- .../general/input/GameCoverPicker.tsx | 12 +- .../general/input/GameHeaderPicker.tsx | 12 +- .../components/general/input/Input.tsx | 40 +- .../components/general/input/NumberInput.tsx | 38 +- .../components/general/input/SelectInput.tsx | 29 +- .../components/general/input/SliderInput.tsx | 38 +- .../general/input/TextAreaInput.tsx | 15 +- .../general/modals/LibraryCreationModal.tsx | 32 +- .../general/modals/PluginDetailsModal.tsx | 2 +- app/src/main/frontend/state/PluginState.ts | 17 +- .../frontend/views/AdministrationView.tsx | 3 +- app/src/main/frontend/views/HomeView.tsx | 70 +- .../app/collections/CollectionEndpoint.kt | 6 +- .../app/collections/CollectionService.kt | 8 +- .../gameyfin/app/config/ConfigProperties.kt | 86 +- .../org/gameyfin/app/config/ConfigService.kt | 1 + .../gameyfin/app/config/dto/ConfigEntryDto.kt | 1 + .../kotlin/org/gameyfin/app/core/Utils.kt | 34 +- .../gameyfin/app/core/config/CacheConfig.kt | 24 + .../{JpaConfiguration.kt => JpaConfig.kt} | 2 +- .../bandwidth/SessionMonitoredOutputStream.kt | 19 +- .../bandwidth/SessionThrottledOutputStream.kt | 21 +- .../core/download/files/DownloadService.kt | 13 +- .../app/core/filesystem/FilesystemService.kt | 6 +- .../gameyfin/app/core/logging/LogService.kt | 6 +- .../app/core/metrics/DownloadMetrics.kt | 84 + .../gameyfin/app/core/metrics/ScanMetrics.kt | 110 + .../app/core/plugins/PluginService.kt | 14 +- .../core/plugins/config/PluginConfigEntry.kt | 1 + .../management/GameyfinJarPluginLoader.kt | 4 +- .../GameyfinManifestPluginDescriptorFinder.kt | 6 +- .../management/GameyfinPluginClassLoader.kt | 2 + .../management/GameyfinPluginDescriptor.kt | 2 +- .../management/GameyfinPluginManager.kt | 115 +- .../plugins/management/PluginManagerConfig.kt | 4 +- .../management/PluginSignatureVerifier.kt | 77 + .../management/PluginsLoadedIndicator.kt | 25 + .../app/core/security/EncryptionUtils.kt | 6 +- .../app/core/security/OidcUserExtensions.kt | 25 + .../app/core/security/SecurityConfig.kt | 20 +- .../SsoAuthenticationSuccessHandler.kt | 20 +- .../serialization/DisplayableSerializer.kt | 2 +- .../org/gameyfin/app/games/GameService.kt | 241 +- .../org/gameyfin/app/games/entities/Game.kt | 2 +- .../app/libraries/LibraryCoreService.kt | 2 + .../app/libraries/LibraryScanService.kt | 92 +- .../gameyfin/app/libraries/LibraryService.kt | 5 +- .../app/libraries/LibraryWatcherService.kt | 4 +- .../app/libraries/entities/IgnoredPath.kt | 4 +- .../extensions/IgnoredPathExtensions.kt | 2 +- .../gameyfin/app/media/FileStorageService.kt | 10 + .../kotlin/org/gameyfin/app/media/Image.kt | 2 + .../org/gameyfin/app/media/ImageEndpoint.kt | 63 +- .../org/gameyfin/app/media/ImageService.kt | 128 +- .../gameyfin/app/messages/MessageService.kt | 4 +- .../templates/MessageTemplateService.kt | 6 +- .../app/requests/GameRequestService.kt | 10 +- .../org/gameyfin/app/users/UserEndpoint.kt | 11 +- .../org/gameyfin/app/users/UserService.kt | 23 +- .../EmailConfirmationEndpoint.kt | 2 +- .../org/gameyfin/app/users/entities/User.kt | 8 + .../app/users/entities/UserEntityListener.kt | 2 +- .../passwordreset/PasswordResetService.kt | 9 +- .../preferences/UserPreferencesService.kt | 2 +- .../users/registration/InvitationService.kt | 7 +- .../gameyfin/app/util/EntityManagerHolder.kt | 2 +- .../org/gameyfin/db/h2/BlurhashMigration.kt | 1 + .../resources/application-aot-training.yml | 24 + app/src/main/resources/application-dev.yml | 4 +- app/src/main/resources/application.yml | 65 +- ...ctor_token_primary_key_for_encryption.sql} | 23 +- ...e_length_limit_for_plugin_config_value.sql | 7 + .../gameyfin/app/config/ConfigServiceTest.kt | 2 +- .../download/files/DownloadServiceTest.kt | 5 +- .../app/core/plugins/PluginServiceTest.kt | 528 +++++ .../management/GameyfinPluginManagerTest.kt | 228 +- .../management/PluginManagerConfigTest.kt | 4 +- .../management/PluginSignatureVerifierTest.kt | 220 ++ .../core/security/OidcUserExtensionsTest.kt | 137 ++ .../SsoAuthenticationSuccessHandlerTest.kt | 433 ++++ .../app/core/token/TokenTypeUserTypeTest.kt | 58 +- .../org/gameyfin/app/games/GameServiceTest.kt | 957 +++++++- .../app/libraries/LibraryScanServiceTest.kt | 39 +- .../gameyfin/app/media/ImageEndpointTest.kt | 206 +- .../gameyfin/app/media/ImageServiceTest.kt | 168 +- .../app/users/entities/UserEntityTest.kt | 104 + app/tsconfig.json | 1 + build.gradle.kts | 4 +- docker/Dockerfile.ubuntu | 62 +- docker/aot-training.sh | 124 + docker/docker-compose.example.yml | 10 + docker/entrypoint.ubuntu.sh | 48 +- gradle.properties | 12 +- .../plugins/download/torrent/TorrentClient.kt | 32 +- scripts/gog.sh | 52 +- 123 files changed, 6169 insertions(+), 2003 deletions(-) create mode 100644 .github/actions/docker-build-platform/action.yml rename .github/actions/{docker-build-push => docker-create-manifest}/action.yml (53%) create mode 100644 .github/prompts/sonar.prompt.md create mode 100644 .sonarlint/connectedMode.json create mode 100644 app/src/main/frontend/components/administration/InfoPopup.tsx create mode 100644 app/src/main/frontend/components/administration/ResetToDefaultButton.tsx create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/config/CacheConfig.kt rename app/src/main/kotlin/org/gameyfin/app/core/config/{JpaConfiguration.kt => JpaConfig.kt} (96%) create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/metrics/DownloadMetrics.kt create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/metrics/ScanMetrics.kt create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/plugins/management/PluginSignatureVerifier.kt create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/plugins/management/PluginsLoadedIndicator.kt create mode 100644 app/src/main/kotlin/org/gameyfin/app/core/security/OidcUserExtensions.kt create mode 100644 app/src/main/resources/application-aot-training.yml rename app/src/main/resources/db/migration/{V2.4.0__Refactor_token_primary_key_for_encryption.sql => V2.4.0.1__Refactor_token_primary_key_for_encryption.sql} (73%) create mode 100644 app/src/main/resources/db/migration/V2.4.0.2__Disable_length_limit_for_plugin_config_value.sql create mode 100644 app/src/test/kotlin/org/gameyfin/app/core/plugins/management/PluginSignatureVerifierTest.kt create mode 100644 app/src/test/kotlin/org/gameyfin/app/core/security/OidcUserExtensionsTest.kt create mode 100644 app/src/test/kotlin/org/gameyfin/app/core/security/SsoAuthenticationSuccessHandlerTest.kt create mode 100644 app/src/test/kotlin/org/gameyfin/app/users/entities/UserEntityTest.kt create mode 100755 docker/aot-training.sh 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 @@