Release v2.2.0 (#741)

* Migrate to TailwindCSS v4 (#740)

* Remove "material-tailwind" dependencies due to incompatibility of Stepper component with Tailwind v4

* Clean up Tailwind configs before upgrade

* Run HeroUI upgrade

* Run TailwindCSS upgrade

* Replace PostCSS with Vite

* Migrate custom styles to v4

* Remove tailwind.config.ts

* Add heroui.ts
Add tailwind vite plugin

* Fix small UI color inconsistency

* Fix theming system
Rename purple theme to pink

* Re-implement stepper in HeroUI

* Fix RoleChip colors

* Migrate icon names (#743)

* Add migration script for phosphor-icons

* Migrate icon usages

* Update version to 2.2.0-preview

* Revert accidental rename of menu title

* Bump stefanzweifel/git-auto-commit-action from 6 to 7 (#750)

Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 6 to 7.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Improve library scanning (#749)

* Update script to generate example libraries using SteamSpy API

* Refactor library scanning process

* Display Flyway startup log by default

* Fix race condition in CompanyService

* Fix race condition in ImageService
Remove obsolete table

* Fix SMTP config requiring an email as username (#755)

* Disable length limit for config values (#757)

* Deprecate DockerHub image (#759)

* Remove deprecation warning from web UI

* Reworked the CICD pipelines

* Optimize container image (#761)

* Fix Gradle warning

* Rework Docker image to improve layer caching

* Bump stefanzweifel/git-auto-commit-action from 6 to 7 (#765)

Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 6 to 7.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Multi platform support (#764)

* Remove migrate-phosphor-icons.js since migration has been successful
* Refactor GameMetadata into separate files
* Add Platform enum
* Implement platform support in Plugin API
* Implement platform support in Steam Plugin
* Implement platform support in IGDB Plugin
* Add database migration for platform support
* Implement platform support in GameService
* Implement platform support on most endpoints and features, some are still missing
Implemented platform support in all bundled plugins (although not finished polishing yet)
* Implement platforms in UI
* Make GameRequest platform aware
* Return headerImages from IGDB
* Implement proper PlatformMapper for IGDB plugin
* Fix various smaller issues and inconsistencies

* Replace placeholder in LibraryOverviewCard (#767)

* Bump actions/download-artifact from 5 to 6 (#769)

* Bump actions/upload-artifact from 4 to 5 (#770)

* Multi platform support (#773)

* Fix bug in Plugin API related to state loading/saving

* Hide Flyway query logs by default

* Extend migration script for multi platform tables

* Plugins now store their data and state in ./plugindata

* Add "plugindata" directory to entrypoint scripts

* Improve download handling (#756)

* Process download in background thread to avoid session timeout affecting it

* Increase default session timeout to 24h

* Use virtual thread pool for download task in background

* Make KSP extensions.idx generation more robust

* Implement download bandwidth limiter
Implement SliderInput
Refactor NumberInput

* Implement download bandwidth throttling
Implement real-time download monitoring

* Improve UI for DownloadManagement
Track more stats in SessionStats

* Update Hilla
Use React 19

* Implement real-time graph to track bandwidth usage
Implement downloaded data sum over last day
Small bug fixes
Small refactorings

* Update docker-compose.example.yml

* Improve DownloadSessionCard (#784)

* Fix unit on y-axis of download graph

* Show game size and library in tooltip
Make game chips interactive in DownloadSessionCard (leads to game page when clicked)
Optimize graph settings

* Migrate torrent plugin to libtorrent (#775)

* Disable TorrentDownloadPlugin in Alpine based Docker image

* Improve test coverage (#785)

* Fix potential divide by zero bug

* Add mockk dependency

* Add tests for org.gameyfin.app.core.download

* Add tests for Filesytem package
Fix DownloadServiceTest

* Fix FilesystemServiceTest

* Add tests for "job" package

* Upgrade Gradle wrapper
Enable Gradle config cache

* Added more tests

* Added tests for the "security" package

* Add tests for "game" package

* Fix AsyncFileTailer not shutting down properly on Windows

* Fix GameServiceTest

* Added tests for "libraries" package

* Added tests for "media" package

* Fix warning in ImageService

* Add tests fpr "messages" package
Make sure transport is closed even in case an exception is thrown

* Add tests for "platforms" package

* Add tests for "requests" package

* Moved "token" package to "core" package (from "shared")

* Add tests for "token" package

* Fix issue in RoleEnum.safeValueOf() throwing Exception

* Fix potential issue in UserEndpoint.getUserInfo() when auth is null

* Added tests for "user" package

* Migrate package for "token" in FE

* Publish test report in CI

* Fix workflow permissions

* Remove test because of timing issue in CI

* Replaced "unmatched paths" with "ignored paths" (#791)

* Use new "AutoComplete" component (#793)

* Use ArrayInputAutocomplete in EditGameMetadataModal

* Add test for getEnumPropertyValues

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Simon
2025-11-17 08:45:39 +01:00
committed by GitHub
parent dd3b18e5e3
commit 717a423449
357 changed files with 39213 additions and 7918 deletions
+9 -14
View File
@@ -1,18 +1,12 @@
name: 'Docker Build and Push'
description: 'Builds and pushes Docker images to Docker Hub and GHCR with flexible tagging.'
description: 'Builds and pushes Docker images to GHCR with flexible tagging.'
runs:
using: 'composite'
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ inputs.dockerhub_username }}
password: ${{ inputs.dockerhub_token }}
- name: Log in to GitHub Container Registry
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
@@ -21,6 +15,7 @@ runs:
- name: Prepare Ubuntu tags
id: ubuntu_tags
if: ${{ inputs.variant != 'alpine' }}
shell: bash
run: |
TAGS="${{ inputs.tags }}"
@@ -28,6 +23,7 @@ runs:
echo "ubuntu_tags=$UBUNTU_TAGS" >> $GITHUB_OUTPUT
- name: Build and push Docker image (Alpine)
if: ${{ inputs.variant != 'ubuntu' }}
uses: docker/build-push-action@v5
with:
context: ${{ inputs.context }}
@@ -39,6 +35,7 @@ runs:
cache-to: type=gha
- name: Build and push Docker image (Ubuntu)
if: ${{ inputs.variant != 'alpine' }}
uses: docker/build-push-action@v5
with:
context: ${{ inputs.context }}
@@ -50,12 +47,6 @@ runs:
cache-to: type=gha
inputs:
dockerhub_username:
required: true
description: 'Docker Hub username'
dockerhub_token:
required: true
description: 'Docker Hub token'
ghcr_username:
required: true
description: 'GHCR username'
@@ -74,3 +65,7 @@ inputs:
tags:
required: true
description: 'Comma-separated list of image tags'
variant:
required: true
default: 'both'
description: 'Image variant to build: alpine, ubuntu, or both'
@@ -1,4 +1,4 @@
name: Delete Docker Tag on Merge
name: Delete Image Tags on Merge
on:
pull_request:
@@ -9,10 +9,11 @@ jobs:
delete-docker-tag:
if: startsWith(github.event.pull_request.head.ref, 'fix/') || startsWith(github.event.pull_request.head.ref, 'release/')
runs-on: ubuntu-latest
name: Cleanup Image Tags from GHCR
permissions:
packages: write
steps:
- name: Extract merged branch name and tag
- name: Extract tag from branch name
id: extract_branch
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
@@ -26,50 +27,8 @@ jobs:
echo "tag=$TAG" >> $GITHUB_OUTPUT
shell: bash
- name: Delete image tag from Docker Hub
- name: Delete tags
if: steps.extract_branch.outputs.tag != ''
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
TAG: ${{ steps.extract_branch.outputs.tag }}
run: |
echo "Deleting Docker tag from Docker Hub: $TAG"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -u "$DOCKERHUB_USERNAME:$DOCKERHUB_TOKEN" \
"https://hub.docker.com/v2/repositories/grimsi/gameyfin/tags/$TAG/")
if [ "$RESPONSE" != "204" ]; then
echo "Failed to delete Docker Hub tag: $TAG (HTTP $RESPONSE)" >&2
exit 1
fi
shell: bash
- name: Delete image tag from GHCR
if: steps.extract_branch.outputs.tag != ''
env:
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.extract_branch.outputs.tag }}
REPO: gameyfin/gameyfin
OWNER: ${{ github.repository_owner }}
run: |
echo "Deleting Docker tag from GHCR: $TAG"
# Get the package ID
PACKAGE_ID=$(curl -s -H "Authorization: Bearer $GHCR_TOKEN" \
"https://api.github.com/users/$OWNER/packages/container/$REPO" | jq -r '.id')
if [ "$PACKAGE_ID" = "null" ] || [ -z "$PACKAGE_ID" ]; then
echo "Failed to get GHCR package ID for $REPO" >&2
exit 1
fi
# Get the version ID for the tag
VERSION_ID=$(curl -s -H "Authorization: Bearer $GHCR_TOKEN" \
"https://api.github.com/users/$OWNER/packages/container/$REPO/versions" | jq -r ".[] | select(.metadata.container.tags[]? == \"$TAG\") | .id")
if [ -z "$VERSION_ID" ]; then
echo "Failed to find GHCR version for tag: $TAG" >&2
exit 1
fi
# Delete the version
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: Bearer $GHCR_TOKEN" \
"https://api.github.com/users/$OWNER/packages/container/$REPO/versions/$VERSION_ID")
if [ "$RESPONSE" != "204" ]; then
echo "Failed to delete GHCR tag: $TAG (HTTP $RESPONSE)" >&2
exit 1
fi
shell: bash
uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: ${{ steps.extract_branch.outputs.tag }},${{ steps.extract_branch.outputs.tag }}-ubuntu
-44
View File
@@ -1,44 +0,0 @@
name: Build and Push Docker Image
on:
push:
branches:
- main
workflow_dispatch:
inputs:
image_tag:
description: 'Docker image tag'
required: false
default: 'develop'
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '21'
- name: Run production build
env:
GAMEYFIN_KEYSTORE_PASSWORD: ${{ secrets.GAMEYFIN_KEYSTORE_PASSWORD }}
run: ./gradlew clean build -Pvaadin.productionMode=true
- name: Build and push Docker image
uses: ./.github/actions/docker-build-push
with:
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
ghcr_username: ${{ github.actor }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
context: .
dockerfile: docker/Dockerfile
platforms: linux/arm64/v8,linux/amd64
tags: grimsi/gameyfin:${{ inputs.image_tag || 'develop' }},ghcr.io/gameyfin/gameyfin:${{ inputs.image_tag || 'develop' }}
+39 -5
View File
@@ -6,10 +6,12 @@ on:
- 'fix/*'
jobs:
build-and-push:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
checks: write
steps:
- name: Checkout code
uses: actions/checkout@v5
@@ -25,6 +27,39 @@ jobs:
GAMEYFIN_KEYSTORE_PASSWORD: ${{ secrets.GAMEYFIN_KEYSTORE_PASSWORD }}
run: ./gradlew clean build -Pvaadin.productionMode=true
- name: Publish Test Report
uses: mikepenz/action-junit-report@v6
if: success() || failure() # always run even if the previous step fails
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
- name: Upload build outputs
uses: actions/upload-artifact@v4
with:
name: build-outputs
path: |
app/build/libs/**
plugins/**/build/libs/**/*.jar
docker:
needs: build
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
fail-fast: false
matrix:
variant: [ alpine, ubuntu ]
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Download build outputs
uses: actions/download-artifact@v5
with:
name: build-outputs
path: .
- name: Extract tag from branch name
id: extract_tag
run: |
@@ -32,14 +67,13 @@ jobs:
TAG="${BRANCH_NAME#fix/}"
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Build and push Docker image
- name: Build and push Docker image (${{ matrix.variant }})
uses: ./.github/actions/docker-build-push
with:
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
ghcr_username: ${{ github.actor }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
context: .
dockerfile: docker/Dockerfile
platforms: linux/arm64/v8,linux/amd64
tags: grimsi/gameyfin:${{ steps.extract_tag.outputs.tag }},ghcr.io/gameyfin/gameyfin:${{ steps.extract_tag.outputs.tag }}
tags: ghcr.io/gameyfin/gameyfin:${{ steps.extract_tag.outputs.tag }}
variant: ${{ matrix.variant }}
+70 -11
View File
@@ -6,13 +6,19 @@ on:
- 'release/*'
jobs:
build-and-push:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
checks: write
outputs:
version: ${{ steps.extract_version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v5
@@ -20,26 +26,79 @@ jobs:
distribution: 'temurin'
java-version: '21'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Extract version from branch name
id: extract_version
run: |
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
VERSION="${BRANCH_NAME#release/}-preview"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Update version in build.gradle.kts
run: |
sed -i "s/^version = .*/version = \"${{ steps.extract_version.outputs.version }}\"/" build.gradle.kts
- name: Update version in app/package.json
run: |
jq ".version = \"${{ steps.extract_version.outputs.version }}\"" app/package.json > app/package.json.tmp && mv app/package.json.tmp app/package.json
- name: Commit version bump (only if changes)
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: 'chore: bump version to v${{ steps.extract_version.outputs.version }}'
file_pattern: |
build.gradle.kts
app/package.json
- name: Run production build
env:
GAMEYFIN_KEYSTORE_PASSWORD: ${{ secrets.GAMEYFIN_KEYSTORE_PASSWORD }}
run: ./gradlew clean build -Pvaadin.productionMode=true
- name: Extract tag from branch name
id: extract_tag
run: |
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
TAG="${BRANCH_NAME#release/}-preview"
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Publish Test Report
uses: mikepenz/action-junit-report@v6
if: success() || failure() # always run even if the previous step fails
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
- name: Build and push Docker image
- name: Upload build outputs
uses: actions/upload-artifact@v4
with:
name: build-outputs
path: |
app/build/libs/**
plugins/**/build/libs/**/*.jar
docker:
needs: build
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
fail-fast: false
matrix:
variant: [ alpine, ubuntu ]
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Download build outputs
uses: actions/download-artifact@v5
with:
name: build-outputs
path: .
- name: Build and push Docker image (${{ matrix.variant }})
uses: ./.github/actions/docker-build-push
with:
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
ghcr_username: ${{ github.actor }}
ghcr_token: ${{ secrets.GITHUB_TOKEN }}
context: .
dockerfile: docker/Dockerfile
platforms: linux/arm64/v8,linux/amd64
tags: grimsi/gameyfin:${{ steps.extract_tag.outputs.tag }},ghcr.io/gameyfin/gameyfin:${{ steps.extract_tag.outputs.tag }}
tags: ghcr.io/gameyfin/gameyfin:${{ needs.build.outputs.version }}
variant: ${{ matrix.variant }}
@@ -0,0 +1,35 @@
name: GHCR Image Registry Maintenance
on:
workflow_dispatch:
inputs:
older_than:
description: 'Only remove images older than (e.g. "1 year", leave empty to remove all untagged images)'
required: false
dry_run:
description: 'Dry run?'
required: true
default: true
type: boolean
validate:
description: 'Validate all multi-architecture images in the registry after cleanup?'
required: true
default: false
type: boolean
jobs:
delete-untagged-images:
runs-on: ubuntu-latest
name: Delete Untagged Images from GHCR
permissions:
packages: write
steps:
- name: Delete untagged, ghost, and orphaned images
uses: dataaxiom/ghcr-cleanup-action@v1
with:
older-than: ${{ github.event.inputs.older_than }}
dry-run: ${{ github.event.inputs.dry_run }}
validate: ${{ github.event.inputs.validate }}
delete-untagged: true
delete-ghost-images: true
delete-orphaned-images: true
+52 -13
View File
@@ -50,18 +50,20 @@ 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@v4
uses: actions/upload-artifact@v5
with:
name: modified-files
path: |
build.gradle.kts
app/package.json
docker:
build:
needs: setup
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
checks: write
steps:
- name: Checkout code
uses: actions/checkout@v5
@@ -69,7 +71,7 @@ jobs:
fetch-depth: 0
- name: Download modified files
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
name: modified-files
@@ -86,33 +88,70 @@ jobs:
GAMEYFIN_KEYSTORE_PASSWORD: ${{ secrets.GAMEYFIN_KEYSTORE_PASSWORD }}
run: ./gradlew clean build -Pvaadin.productionMode=true
- name: Publish Test Report
uses: mikepenz/action-junit-report@v6
if: success() || failure() # always run even if the previous step fails
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
- name: Upload build outputs
uses: actions/upload-artifact@v4
with:
name: build-outputs
path: |
app/build/libs/**
plugins/**/build/libs/**/*.jar
docker:
needs: [ setup, build ]
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
fail-fast: false
matrix:
variant: [ alpine, ubuntu ]
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Download modified files
uses: actions/download-artifact@v5
with:
name: modified-files
- name: Download build outputs
uses: actions/download-artifact@v5
with:
name: build-outputs
path: .
- name: Generate container image tags
id: docker_tags
run: |
VERSION="${{ needs.setup.outputs.release_version }}"
DOCKERHUB_TAGS="grimsi/gameyfin:$VERSION"
VERSION='${{ needs.setup.outputs.release_version }}'
GHCR_TAGS="ghcr.io/gameyfin/gameyfin:$VERSION"
if [[ "$VERSION" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
DOCKERHUB_TAGS="grimsi/gameyfin:latest,grimsi/gameyfin:develop,grimsi/gameyfin:$VERSION,grimsi/gameyfin:$MAJOR.$MINOR,grimsi/gameyfin:$MAJOR"
GHCR_TAGS="ghcr.io/gameyfin/gameyfin:latest,ghcr.io/gameyfin/gameyfin:develop,ghcr.io/gameyfin/gameyfin:$VERSION,ghcr.io/gameyfin/gameyfin:$MAJOR.$MINOR,ghcr.io/gameyfin/gameyfin:$MAJOR"
fi
TAGS="$DOCKERHUB_TAGS,$GHCR_TAGS"
TAGS="$GHCR_TAGS"
echo "tags=$TAGS" >> $GITHUB_OUTPUT
- name: Build and push Docker image
- name: Build and push Docker image (${{ matrix.variant }})
uses: ./.github/actions/docker-build-push
with:
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
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 }}
variant: ${{ matrix.variant }}
plugin_api:
needs: setup
@@ -124,7 +163,7 @@ jobs:
fetch-depth: 0
- name: Download modified files
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
name: modified-files
@@ -155,13 +194,13 @@ jobs:
fetch-depth: 0
- name: Download modified files
uses: actions/download-artifact@v5
uses: actions/download-artifact@v6
with:
name: modified-files
- name: Commit version bump
if: ${{ github.event.inputs.update_version }}
uses: stefanzweifel/git-auto-commit-action@v6
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: 'chore: release v${{ github.event.inputs.version }}'
tagging_message: v${{ github.event.inputs.version }}