Release 2.58 (#5952)

* bump version
* fix formatting locale reset after embedded controller sub-requests (#5944)
* fix GHSA-c6w6-57jj-62vh
* fix GHSA-m492-gv72-xvxj
* fix GHSA-jr9p-4h4j-6c58
* make sure to only use JS logic to call API endpoints
* fixes GHSA-r8vr-m544-qh4h
* make sure to only use JS logic to call API endpoints
* fix GHSA-rw46-qg69-vg6h
* fix GHSA-pj8j-p4g4-4vw8 - prevent kimai from rendering images via markdown
* fix GHSA-pj8j-p4g4-4vw8 - use a safe network client to prevent SSRF via images
* fix GHSA-xv4r-4885-gwpg
* fix GHSA-pgcc-vfmc-7cw5 - move GET routes to API with POST method to prevent CSRF
* fix tooltip survives page reload
* updated wizard images
* split wizard and password reset subscriber into two classes
* relax upper php limit
* added zizmor workflow scans and apply findings
* user permissions <name>_other_profile  now respect teams
* move all linting steps to new job
* updated docker image version names
* use .env.local for storing APP_SECRET
* improve build order and use given tag as ref for checkout, not default main branch
* improved APP_SECRET handling, see entrypoint.sh
* use local code for building the image for more flexibility, added dockerignore
This commit is contained in:
Kevin Papst
2026-05-25 15:39:47 +02:00
committed by GitHub
parent 8d245ae223
commit 31a8f887a5
85 changed files with 2737 additions and 472 deletions

View File

@@ -9,32 +9,28 @@ on:
release:
types: [released]
concurrency:
group: docker-build
cancel-in-progress: true
permissions: {}
jobs:
build:
name: Docker images
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install buildx
uses: docker/setup-buildx-action@v4
- name: Login to DockerHub
uses: docker/login-action@v4
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_PASSWORD}}
- name: Determine version
env:
GITHUB_EVENT_INPUTS_KIMAI_TAG: ${{ github.event.inputs.kimai_tag }}
GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
input="${{ github.event.inputs.kimai_tag }}"
input="${GITHUB_EVENT_INPUTS_KIMAI_TAG}"
# Determine between manual trigger and release event
if [ -z "$input" ]; then
echo "Using release tag: ${{ github.event.release.tag_name }}"
version="${{ github.event.release.tag_name }}"
echo "Using release tag: ${GITHUB_EVENT_RELEASE_TAG_NAME}"
version="${GITHUB_EVENT_RELEASE_TAG_NAME}"
else
echo "Using tag provided: $input"
version="$input"
@@ -44,11 +40,45 @@ jobs:
echo "Invalid version number: $version"
exit 1
fi
echo "kimai_version=$version" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ env.kimai_version }}
persist-credentials: false
- name: Install buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to DockerHub
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_PASSWORD}}
# TODO 3.0 remove kimai/kimai2:apache and kimai/kimai2:apache-<version>
- name: Apache image
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: Dockerfile
build-args: |
KIMAI=${{ env.kimai_version }}
BASE=apache
target: prod
platforms: linux/amd64,linux/arm64
tags: |
kimai/kimai2:stable
kimai/kimai2:apache
kimai/kimai2:2
kimai/kimai2:${{ env.kimai_version }}
push: true
# TODO 3.0 remove the deprecated FPM build
- name: FPM image
uses: docker/build-push-action@v6
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: Dockerfile
@@ -62,24 +92,8 @@ jobs:
kimai/kimai2:fpm
push: true
- name: Apache image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
build-args: |
KIMAI=${{ env.kimai_version }}
BASE=apache
target: prod
platforms: linux/amd64,linux/arm64
tags: |
kimai/kimai2:stable
kimai/kimai2:apache
kimai/kimai2:apache-${{ env.kimai_version }}
push: true
- name: Development image
uses: docker/build-push-action@v6
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
with:
context: .
file: Dockerfile

View File

@@ -4,32 +4,37 @@ on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
frontend:
runs-on: ubuntu-latest
name: Frontend verification
steps:
- name: Clone Kimai
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Clone Kimai
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup PNPM
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
run_install: false
- name: Setup PNPM
uses: pnpm/action-setup@v6
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
- name: Check for security issues in frontend dependencies
run: pnpm audit
- name: Check for security issues in frontend dependencies
run: pnpm audit

76
.github/workflows/linting.yaml vendored Normal file
View File

@@ -0,0 +1,76 @@
name: Lint PHP
on:
pull_request: null
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
integration:
name: Linting (${{ matrix.php }})
runs-on: ubuntu-latest
strategy:
matrix:
php: ['8.2'] # use lowest supported PHP version to prevent introducing syntax from newer PHP versions
steps:
- name: Clone Kimai
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
with:
php-version: ${{ matrix.php }}
coverage: pcov
extensions: ctype, gd, iconv, intl, mbstring, xml, zip
tools: cs2pr, symfony-cli
env:
fail-fast: true
- name: Determine composer cache directory
id: composer-cache
run: echo "composer_cache_directory=$(composer config cache-dir)" >> $GITHUB_ENV
- name: Cache Composer dependencies
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: "${{ env.composer_cache_directory }}"
key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
- name: Install dependencies
run: composer install
- name: Validate Composer
run: composer validate --strict --no-check-all
- name: Lint YAML
run: APP_ENV=dev bin/console lint:yaml --parse-tags config
- name: Lint XLIFF
run: APP_ENV=dev bin/console lint:xliff translations
- name: Check codestyles
run: vendor/bin/php-cs-fixer fix --dry-run --verbose --config=.php-cs-fixer.dist.php --using-cache=no --show-progress=none --format=checkstyle | cs2pr
- name: Run PHPStan for application
run: vendor/bin/phpstan analyse -c phpstan.neon --no-progress --error-format=checkstyle | cs2pr
- name: Run PHPStan for tests
run: vendor/bin/phpstan analyse -c tests/phpstan.neon --no-progress --error-format=checkstyle | cs2pr
- name: Lint codebase
run: composer linting
- name: Check for security issues in packages
run: symfony security:check

View File

@@ -5,20 +5,22 @@ on:
- cron: '17 1 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
permissions: {}
concurrency:
group: lock-threads
cancel-in-progress: true
jobs:
action:
permissions:
issues: write # needed to comment and close the issues
runs-on: ubuntu-latest
name: Lock inactive issues
steps:
- uses: dessant/lock-threads@v6
- uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6.0.2
with:
process-only: 'issues, prs'
process-only: 'issues'
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: '90'
issue-comment: >

View File

@@ -1,21 +1,27 @@
name: Check .lock files
on:
on: # zizmor: ignore[dangerous-triggers] using the target branch workflow prevents adding new trustedAuthors
pull_request_target: null
push:
branches:
- main
permissions:
pull-requests: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
lockfiles:
permissions:
pull-requests: read # read the PR author
runs-on: ubuntu-latest
name: Verify lock file integrity
steps:
- name: Prevent file change
uses: xalvarez/prevent-file-change-action@v3
uses: xalvarez/prevent-file-change-action@dbc67c205c9ed02aa39c497b422c24f364c3e8dd # v3.0.1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
pattern: .*\.lock$|^\.github\/.*$
trustedAuthors: kevinpapst, dependabot
trustedAuthors: kevinpapst

View File

@@ -5,26 +5,29 @@ on:
branches:
- main
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
correct_repository:
permissions:
contents: none
runs-on: ubuntu-latest
name: Verify repository
steps:
- name: fail on fork
if: github.repository_owner != 'kimai'
run: exit 1
update_release_draft:
name: Draft next release
permissions:
contents: write # for release-drafter/release-drafter to create a github release
pull-requests: read
contents: write # to create a github release draft
pull-requests: read # to identify changes that occurred
needs: correct_repository
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v7
- uses: release-drafter/release-drafter@c2e2804cc59f45f57076a99af580d0fedb697927 # v7.3.0
env:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,15 +1,24 @@
name: Tests
on:
pull_request: null
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
integration:
name: Integration (${{ matrix.php }})
runs-on: ubuntu-latest
services:
mysql:
image: mysql:latest
image: mysql@sha256:c36050afdca850f23cef85703f84c7531a5ae155a11b5ee1c60acb09937c4084 # 8.4.9
env:
MYSQL_ALLOW_EMPTY_PASSWORD: false
MYSQL_ROOT_PASSWORD: kimai
@@ -17,20 +26,20 @@ jobs:
ports:
- 3306/tcp
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
matrix:
php: ['8.2', '8.3', '8.4', '8.5']
name: Integration (${{ matrix.php }})
steps:
- name: Clone Kimai
uses: actions/checkout@v6
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
with:
php-version: ${{ matrix.php }}
coverage: pcov
@@ -47,7 +56,7 @@ jobs:
run: echo "composer_cache_directory=$(composer config cache-dir)" >> $GITHUB_ENV
- name: Cache Composer dependencies
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: "${{ env.composer_cache_directory }}"
key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
@@ -55,28 +64,11 @@ jobs:
- name: Install dependencies
run: composer install
- name: Validate Composer
run: composer validate --strict --no-check-all
- name: Warmup cache
run: APP_ENV=dev bin/console kimai:reload -n
- name: Check codestyles
run: vendor/bin/php-cs-fixer fix --dry-run --verbose --config=.php-cs-fixer.dist.php --using-cache=no --show-progress=none --format=checkstyle | cs2pr
- name: Run PHPStan for application
run: vendor/bin/phpstan analyse -c phpstan.neon --no-progress --error-format=checkstyle | cs2pr
- name: Run PHPStan for tests
run: vendor/bin/phpstan analyse -c tests/phpstan.neon --no-progress --error-format=checkstyle | cs2pr
- name: Lint codebase
run: composer linting
- name: Install LDAP package (for tests)
run: composer require laminas/laminas-ldap
- name: Setup problem matchers (for PHPUnit)
# zizmor: ignore[template-injection] coming from the https://github.com/marketplace/actions/setup-php-action
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Run quick unit-tests
@@ -104,7 +96,7 @@ jobs:
- name: Upload code coverage
if: matrix.php == '8.5'
uses: codecov/codecov-action@v6
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
@@ -120,6 +112,3 @@ jobs:
DATABASE_URL: mysql://root:kimai@127.0.0.1:${{ job.services.mysql.ports['3306'] }}/kimai?charset=utf8mb4&serverVersion=8.0.35
APP_ENV: dev
MAILER_URL: null://localhost
- name: Check for security issues in packages
run: symfony security:check

View File

@@ -1,42 +1,52 @@
name: 'Website update'
on:
workflow_dispatch:
inputs:
kimai_version:
description: 'Kimai version for the website'
required: true
release:
types: [released]
workflow_dispatch:
inputs:
kimai_version:
description: 'Kimai version for the website'
required: true
release:
types: [released]
concurrency:
group: update-website
cancel-in-progress: true
permissions: {}
jobs:
build:
name: Trigger version update for website
runs-on: ubuntu-latest
steps:
- name: "Determine Version"
run: |
input="${{ github.event.inputs.kimai_version }}"
build:
name: Trigger version update for website
runs-on: ubuntu-latest
steps:
- name: "Determine Version"
env:
GITHUB_EVENT_INPUTS_KIMAI_VERSION: ${{ github.event.inputs.kimai_version }}
GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
input="${GITHUB_EVENT_INPUTS_KIMAI_VERSION}"
# Determine between manual trigger and release event
if [ -z "$input" ]; then
echo "No input provided, using release tag"
version="${GITHUB_EVENT_RELEASE_TAG_NAME}"
else
echo "Using input provided: $input"
version="$input"
fi
echo "kimai_version=$version" >> $GITHUB_ENV
if [[ ! $version =~ ^2\.(0|[1-9]*)(0?)\.(0|[0-9]*)(0?)$ ]]; then
echo "Invalid version number: $version"
exit 1
fi
# Determine between manual trigger and release event
if [ -z "$input" ]; then
echo "No input provided, using release tag"
version="${{ github.event.release.tag_name }}"
else
echo "Using input provided: $input"
version="$input"
fi
echo "kimai_version=$version" >> $GITHUB_ENV
if [[ ! $version =~ ^2\.(0|[1-9]*)(0?)\.(0|[0-9]*)(0?)$ ]]; then
echo "Invalid version number: $version"
exit 1
fi
- name: Emit repository_dispatch
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.WEBSITE_ACCESS_TOKEN }}
repository: kimai/www.kimai.org
event-type: kimai_release
client-payload: '{"kimai_version": "${{ env.kimai_version }}"}'
- name: Emit repository_dispatch
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
token: ${{ secrets.WEBSITE_ACCESS_TOKEN }}
repository: kimai/www.kimai.org
event-type: kimai_release
client-payload: '{"kimai_version": "${{ env.kimai_version }}"}'

28
.github/workflows/zizmor.yaml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Actions Security Analysis
on:
push:
branches: ["main"]
pull_request:
branches: ["**"]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
zizmor:
name: Scan workflows
runs-on: ubuntu-latest
permissions:
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Run zizmor 🌈
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6