- Runtime-base job now uses repository artifact instead of cloning (saves 1 git clone per run)
- Health checks are now optional via workflow_dispatch input (default: true)
- Health checks still run automatically on push events
- Reduces additional load on Gitea by ~10-15%
- Use repository artifacts in test and build jobs (reduces 2-3 git clones per run)
- Add comprehensive workflow performance monitoring system
- Add monitoring playbook and Gitea workflow for automated metrics collection
- Add monitoring documentation and scripts
Optimizations:
- Repository artifact caching: changes job uploads repo, test/build jobs download it
- Reduces Gitea load by eliminating redundant git operations
- Faster job starts (artifact download is typically faster than git clone)
Monitoring:
- Script for local workflow metrics collection via Gitea API
- Ansible playbook for server-side system and Gitea metrics
- Automated Gitea workflow that runs every 6 hours
- Tracks workflow durations, system load, Gitea API response times, and more
- Add traefik_auto_restart check to fix-gitea-timeouts.yml
- Add traefik_auto_restart check to fix-gitea-ssl-routing.yml
- Add traefik_auto_restart check to fix-gitea-complete.yml
- Set traefik_auto_restart=false in all Gitea workflow Ansible calls
- Set gitea_auto_restart=false in all Gitea workflow Ansible calls
- Add redeploy-traefik-gitea.yml playbook for clean redeployment
This prevents CI/CD pipelines from causing Traefik restart loops by
ensuring all remediation playbooks respect the traefik_auto_restart
flag, which is set to false in group_vars/production/vars.yml.
- Move deploy-image.yml before install-composer-dependencies.yml
- Containers must be running before composer can install dependencies
- Fixes 'container not running' error in composer install step
- Applied to both staging and production workflows
- Change deploy-staging and deploy-production to use php-ci runner
- php-ci image has Ansible pre-installed, fixing 'ansible-playbook: command not found' error
The 'Deploy to Production Server' step is separate from the clone step and
doesn't inherit the working directory. The scp command was running from the
default directory where docker-compose files don't exist.
Adding 'cd /workspace/repo' before scp to access the cloned repository files.
This fixes the error:
docker-compose.base.yml: No such file or directory
docker-compose.production.yml: No such file or directory
The previous 'always sync' approach failed because it tried to copy files
from /workspace/repo/ which doesn't exist on the production server.
The SSH heredoc (<<EOF) executes commands ON the production server, not in
the Gitea Actions workspace. File paths inside heredoc are relative to the
production server's filesystem.
This commit adds an scp step BEFORE the SSH heredoc to transfer
docker-compose.base.yml and docker-compose.production.yml from the Actions
workspace to the production server.
This ensures the build: null overrides (commit 2e539ed) reach production
and services can restart without build context errors.
Changes:
- Added scp command to deploy docker-compose files before SSH deployment
- Changed file sync check from 'cp' to file existence validation
- Updated comments to clarify rsync-based deployment architecture
Related commits:
- 0b342c6: Sequential push strategy
- 08f6f64: Stable git-SHA IMAGE_TAG
- 2e539ed: build: null overrides
- 0db73df: Always-sync docker-compose (incorrect implementation)
- 3091205: Trigger pipeline with source file change
The deployment script was only copying docker-compose files when missing,
preventing configuration updates (like build: null overrides) from being deployed.
Changed from conditional copy to always sync latest files from repository,
ensuring all configuration changes are properly deployed to production.
Changed IMAGE_TAG output from timestamp-based format to stable git-SHA format to ensure
deployment can reliably pull the image that was actually pushed to the registry.
Before: IMAGE_TAG="6c7040e-1762265632" (changes with time)
After: IMAGE_TAG="git-6c7040e" (stable, matches pushed tag)
This fixes deployment manifest not found errors.
Docker registry was getting overwhelmed with concurrent pushes of
multiple tags and cache layers, resulting in 499 status code
(Client Closed Request).
Changes:
- Build with --load instead of --push to save image locally first
- Push each tag sequentially (latest, timestamp, git-sha) instead of all at once
- Reduce cache targets from 2 to 1 (keep only buildcache)
- Add progress logging for each push operation
This approach:
1. Reduces concurrent write pressure on registry
2. Allows better error handling per tag
3. Provides clearer progress feedback
4. Prevents registry timeouts from concurrent uploads
Related to: Status 499 error during docker push
- Refine branch and path filters for efficient CI triggers.
- Add concurrency control to avoid overlapping builds.
- Improve runtime base build logic with conditional evaluation and skipping.
- Enhance image info generation with fallback handling and deployment readiness checks.
- Fix user home directory detection for stack path expansion
- Handle tilde expansion and relative paths correctly
- Add fallback logic for path resolution
- Replace job-level if condition with env variable for better control
- Add conditional checks to all build steps
- Add skip step when build not required
- Simplify deploy-staging conditions
- Add fallback to 'latest' tag when build fails
- Add fallback mechanism when pulling specific image tag fails
- Fix code style: move opening brace in ObjectInfo
- Remove unused comment in ObjectStorage
- build job accesses needs.runtime-base.outputs.image_ref, so runtime-base must be in needs
- Added always() condition to ensure build runs even if runtime-base is skipped
- Outputs will be empty if runtime-base was skipped, which is handled gracefully
- Better handling of optional runtime-base outputs
- Added null check for runtime-base image_ref
- Improved logging when using freshly built runtime image
- Removed runtime-base from build job dependencies (build now only depends on changes)
- runtime-base now only runs when needed (if needs_runtime_build or needs_build is true)
- build job now handles missing runtime-base outputs gracefully
- deploy-staging and deploy-production now only depend on build (not runtime-base)
- Added always() conditions to ensure jobs run even if previous jobs are skipped
- Fixes issue where workflow stopped after runtime-base job when build was skipped
- Added RUNTIME_IMAGE_NAME to env section of Build and push runtime base image step
- Added RUNTIME_IMAGE_NAME to env section of Set runtime base outputs step
- Fixes 'bad substitution' error when variable is used in shell scripts
- Added explicit Git pull in staging deployment after container restart
- Added production auto-deploy job to build-image.yml (for main branch)
- Removed redundant workflows: deploy-staging.yml, deploy-production.yml, production-deploy.yml
- All deployments now handled by build-image.yml:
- staging branch → auto-deploy to staging
- main branch → auto-deploy to production
- Fixed build job dependency (removed test dependency)
- Git sync now explicitly pulls code after deployment to ensure containers are up-to-date
- Removed 'test' from build job needs array
- Build job now depends only on [changes, runtime-base]
- Fixes issue where build was waiting for skipped test job
- deploy-staging now correctly waits for build completion
- Aktualisiere docker-compose.yml immer aus Repository
- Starte staging-app Container neu für Git-Pull
- Unterstütze mehrere Image-URL-Formate in sed-Replacements
- Füge Wartezeiten für Git-Sync hinzu
- Behebt Problem, dass Code nicht synchronisiert wurde
- Fix upstream configuration in staging-nginx container
- Verbessere sed-Befehle zur automatischen Korrektur der PHP-FPM Upstream-Definition
- Behebt 502 Bad Gateway Fehler durch korrekte Verbindung zu staging-app:9000