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
- Create staging stack with separate containers and volumes
- Configure staging.michaelschiemer.de subdomain routing
- Add deploy-staging.yml workflow for auto-deployment
- Extend build-image.yml to support staging branch
- Separate Redis instance and network for staging
- Staging uses staging branch by default
Features:
- Auto-deploy: Push to staging branch → build → deploy to staging
- Separate from production: Different containers, volumes, networks
- Shared Traefik: Uses same SSL certificates (*.michaelschiemer.de)
- Testing environment before production deployment
- Add validation and fallback logic for IMAGE_TAG
- If build job output is empty, generate tag from commit SHA
- Use 'latest' tag as last resort fallback
- Add debug output to show what tag is being used
- Fixes 'invalid reference format' error when IMAGE_TAG is empty
- Remove Ansible dependency from deployment workflow
- Use direct SSH commands for Docker operations
- Simplify deployment process:
* SSH to production server
* Docker registry login
* Pull new image
* Update docker-compose.yml with sed
* Restart services with docker compose
- Remove Ansible verification step
- Simplify rollback step (only shows manual instructions)
- Works with ubuntu-latest runner (no special image needed)
- Fixes 'ansible: command not found' errors
- Works with act for local testing
- Changed deploy job to use php-ci runner which has Ansible pre-installed
- Removed redundant Ansible installation step
- Fixes 'ansible: command not found' error in Gitea Actions workflow
- Add check step to verify if image for commit SHA already exists
- Skip build step if image exists (saves 5+ minutes per deployment)
- Use git-{SHORT_SHA} tag to identify images by commit
- Only rebuild when code actually changed
- Improve build cache utilization
- Prioritize registry.michaelschiemer.de (HTTPS) over HTTP endpoints
- Configure Buildx to use docker-dind with insecure-registry support
- Ensure Buildx respects insecure-registry settings from docker-dind
- Fix 'http: server gave HTTP response to HTTPS client' error