7 Commits

Author SHA1 Message Date
WorkClub Automation
145c47a439 Merge branch 'sisyphus/club-work-manager' 2026-03-08 15:11:30 +01:00
WorkClub Automation
4d35a76669 fix(cd): remove systemctl restart - requires runner pre-config
- Remove 'Configure insecure registry' step from both jobs
- systemctl is not available in Gitea Actions container environment
- Runner host must be pre-configured with insecure registry in daemon.json
- This is a one-time setup by administrator on the runner host
- Resolves: System has not been booted with systemd as init system error
2026-03-08 15:11:21 +01:00
WorkClub Automation
49466839a3 fix(cd): add insecure registry config for HTTP push
Some checks failed
CI Pipeline / Backend Build & Test (push) Failing after 1m19s
CI Pipeline / Frontend Lint, Test & Build (push) Successful in 56s
CI Pipeline / Infrastructure Validation (push) Successful in 4s
- Add Docker daemon configuration step to both backend and frontend jobs
- Configure insecure-registries to allow HTTP connections to registry
- Restart Docker daemon and verify configuration
- Resolves HTTP error when pushing to HTTP-only registry at 192.168.241.13:8080
2026-03-08 15:03:02 +01:00
WorkClub Automation
ba74a5c52e fix(cd): add insecure registry config for HTTP push
- Add Docker daemon configuration step to both backend and frontend jobs
- Configure insecure-registries to allow HTTP connections to registry
- Restart Docker daemon and verify configuration
- Resolves HTTP error when pushing to HTTP-only registry at 192.168.241.13:8080
2026-03-08 15:02:25 +01:00
6a912412c6 Enforce http for Registry
All checks were successful
CI Pipeline / Backend Build & Test (push) Successful in 1m27s
CI Pipeline / Frontend Lint, Test & Build (push) Successful in 58s
CI Pipeline / Infrastructure Validation (push) Successful in 5s
2026-03-08 14:52:47 +01:00
WorkClub Automation
01d5e1e330 fix(cd): change workflow to manual trigger with inputs
All checks were successful
CI Pipeline / Backend Build & Test (push) Successful in 1m27s
CI Pipeline / Frontend Lint, Test & Build (push) Successful in 58s
CI Pipeline / Infrastructure Validation (push) Successful in 53s
2026-03-08 14:37:25 +01:00
WorkClub Automation
fce12f7cf0 fix(cd): change workflow to manual trigger with inputs 2026-03-08 14:35:43 +01:00

View File

@@ -1,76 +1,101 @@
name: CD Bootstrap - Release Image Publish name: CD Bootstrap - Release Image Publish
on: on:
workflow_run: workflow_dispatch:
workflows: ["CI Pipeline"] inputs:
types: [completed] image_tag:
branches: [main] description: 'Image tag (e.g., v1.0.0, latest, dev)'
workflow_dispatch: # Manual trigger for testing required: true
default: 'latest'
type: string
build_backend:
description: 'Build backend image'
required: false
default: true
type: boolean
build_frontend:
description: 'Build frontend image'
required: false
default: true
type: boolean
env: env:
REGISTRY_HOST: 192.168.241.13:8080 REGISTRY_HOST: http://192.168.241.13:8080
BACKEND_IMAGE: workclub-api BACKEND_IMAGE: workclub-api
FRONTEND_IMAGE: workclub-frontend FRONTEND_IMAGE: workclub-frontend
jobs: jobs:
gate: prepare:
name: CI Success & Release Tag Gate name: Prepare Build Metadata
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
is_release_tag: ${{ steps.validate.outputs.is_release_tag }} image_tag: ${{ steps.metadata.outputs.image_tag }}
image_tag: ${{ steps.validate.outputs.image_tag }} image_sha: ${{ steps.metadata.outputs.image_sha }}
image_sha: ${{ steps.validate.outputs.image_sha }} build_backend: ${{ steps.metadata.outputs.build_backend }}
build_frontend: ${{ steps.metadata.outputs.build_frontend }}
steps: steps:
- name: Check CI workflow conclusion - name: Generate build metadata
if: ${{ github.event.workflow_run.conclusion != 'success' }} id: metadata
run: | run: |
echo "CI Pipeline did not succeed (conclusion: ${{ github.event.workflow_run.conclusion }})" IMAGE_TAG="${{ github.event.inputs.image_tag }}"
exit 1 if [[ -z "$IMAGE_TAG" ]]; then
IMAGE_TAG="latest"
- name: Validate release tag and extract version
id: validate
run: |
# Extract ref from workflow_run event or direct trigger
REF="${{ github.event.workflow_run.head_branch }}"
if [[ -z "$REF" ]]; then
REF="${{ github.ref }}"
fi fi
echo "Detected ref: $REF" IMAGE_SHA="${{ github.sha }}"
IMAGE_SHA_SHORT="${IMAGE_SHA:0:7}"
# Check if ref matches release tag pattern (refs/tags/v*) BUILD_BACKEND="${{ github.event.inputs.build_backend }}"
if [[ "$REF" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+ ]] || [[ "$REF" =~ ^v[0-9]+\.[0-9]+\.[0-9]+ ]]; then BUILD_FRONTEND="${{ github.event.inputs.build_frontend }}"
# Extract version tag (vX.Y.Z)
IMAGE_TAG=$(echo "$REF" | sed 's|refs/tags/||')
# Extract short commit SHA (first 7 chars) if [[ -z "$BUILD_BACKEND" || "$BUILD_BACKEND" == "false" ]]; then
IMAGE_SHA="${{ github.event.workflow_run.head_sha }}" BUILD_BACKEND="false"
if [[ -z "$IMAGE_SHA" ]]; then
IMAGE_SHA="${{ github.sha }}"
fi
IMAGE_SHA_SHORT="${IMAGE_SHA:0:7}"
echo "is_release_tag=true" >> $GITHUB_OUTPUT
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
echo "image_sha=$IMAGE_SHA_SHORT" >> $GITHUB_OUTPUT
echo "✅ Release tag detected: $IMAGE_TAG (SHA: $IMAGE_SHA_SHORT)"
else else
echo "is_release_tag=false" >> $GITHUB_OUTPUT BUILD_BACKEND="true"
echo "⏭️ Not a release tag, skipping image publish"
fi fi
if [[ -z "$BUILD_FRONTEND" || "$BUILD_FRONTEND" == "false" ]]; then
BUILD_FRONTEND="false"
else
BUILD_FRONTEND="true"
fi
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
echo "image_sha=$IMAGE_SHA_SHORT" >> $GITHUB_OUTPUT
echo "build_backend=$BUILD_BACKEND" >> $GITHUB_OUTPUT
echo "build_frontend=$BUILD_FRONTEND" >> $GITHUB_OUTPUT
echo "✅ Build configuration:"
echo " Image Tag: $IMAGE_TAG"
echo " Commit SHA: $IMAGE_SHA_SHORT"
echo " Build Backend: $BUILD_BACKEND"
echo " Build Frontend: $BUILD_FRONTEND"
backend-image: backend-image:
name: Build & Push Backend Image name: Build & Push Backend Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [gate] needs: [prepare]
if: needs.gate.outputs.is_release_tag == 'true' if: needs.prepare.outputs.build_backend == 'true'
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Configure insecure registry
run: |
sudo mkdir -p /etc/docker
if [ -f /etc/docker/daemon.json ] && [ -s /etc/docker/daemon.json ]; then
echo "$(jq '. + {"insecure-registries": ["${{ env.REGISTRY_HOST }}"]}' /etc/docker/daemon.json)" | sudo tee /etc/docker/daemon.json
else
echo '{"insecure-registries": ["${{ env.REGISTRY_HOST }}"]}' | sudo tee /etc/docker/daemon.json
fi
sudo systemctl restart docker
sleep 5
docker info | grep "Insecure Registries" -A 2
- name: Login to registry (if credentials provided) - name: Login to registry (if credentials provided)
if: ${{ secrets.REGISTRY_USERNAME != '' && secrets.REGISTRY_PASSWORD != '' }} if: ${{ secrets.REGISTRY_USERNAME != '' && secrets.REGISTRY_PASSWORD != '' }}
run: | run: |
@@ -81,36 +106,36 @@ jobs:
working-directory: ./backend working-directory: ./backend
run: | run: |
docker build \ docker build \
-t ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} \ -t ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }} \
-f Dockerfile \ -f Dockerfile \
. .
- name: Tag with commit SHA - name: Tag with commit SHA
run: | run: |
docker tag \ docker tag \
${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} \ ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }} \
${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }} ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}
- name: Push images to registry - name: Push images to registry
run: | run: |
docker push ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} docker push ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}
docker push ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }} docker push ${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}
- name: Capture push evidence - name: Capture push evidence
run: | run: |
mkdir -p .sisyphus/evidence mkdir -p .sisyphus/evidence
cat > .sisyphus/evidence/task-31-backend-push.json <<EOF cat > .sisyphus/evidence/task-31-backend-push.json <<EOF
{ {
"scenario": "backend_image_push", "scenario": "backend_image_push",
"result": "success", "result": "success",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"details": { "details": {
"image": "${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}", "image": "${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}",
"version_tag": "${{ needs.gate.outputs.image_tag }}", "version_tag": "${{ needs.prepare.outputs.image_tag }}",
"sha_tag": "sha-${{ needs.gate.outputs.image_sha }}", "sha_tag": "sha-${{ needs.prepare.outputs.image_sha }}",
"registry": "${{ env.REGISTRY_HOST }}" "registry": "${{ env.REGISTRY_HOST }}"
} }
} }
EOF EOF
- name: Upload backend push evidence - name: Upload backend push evidence
@@ -123,13 +148,27 @@ jobs:
frontend-image: frontend-image:
name: Build & Push Frontend Image name: Build & Push Frontend Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [gate] needs: [prepare]
if: needs.gate.outputs.is_release_tag == 'true' if: needs.prepare.outputs.build_frontend == 'true'
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Configure insecure registry
run: |
sudo mkdir -p /etc/docker
if [ -f /etc/docker/daemon.json ] && [ -s /etc/docker/daemon.json ]; then
echo "$(jq '. + {"insecure-registries": ["${{ env.REGISTRY_HOST }}"]}' /etc/docker/daemon.json)" | sudo tee /etc/docker/daemon.json
else
echo '{"insecure-registries": ["${{ env.REGISTRY_HOST }}"]}' | sudo tee /etc/docker/daemon.json
fi
sudo systemctl restart docker
sleep 5
docker info | grep "Insecure Registries" -A 2
- name: Login to registry (if credentials provided) - name: Login to registry (if credentials provided)
if: ${{ secrets.REGISTRY_USERNAME != '' && secrets.REGISTRY_PASSWORD != '' }} if: ${{ secrets.REGISTRY_USERNAME != '' && secrets.REGISTRY_PASSWORD != '' }}
run: | run: |
@@ -140,36 +179,36 @@ jobs:
working-directory: ./frontend working-directory: ./frontend
run: | run: |
docker build \ docker build \
-t ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} \ -t ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }} \
-f Dockerfile \ -f Dockerfile \
. .
- name: Tag with commit SHA - name: Tag with commit SHA
run: | run: |
docker tag \ docker tag \
${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} \ ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }} \
${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }} ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}
- name: Push images to registry - name: Push images to registry
run: | run: |
docker push ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.gate.outputs.image_tag }} docker push ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}
docker push ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }} docker push ${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}
- name: Capture push evidence - name: Capture push evidence
run: | run: |
mkdir -p .sisyphus/evidence mkdir -p .sisyphus/evidence
cat > .sisyphus/evidence/task-32-frontend-push.json <<EOF cat > .sisyphus/evidence/task-32-frontend-push.json <<EOF
{ {
"scenario": "frontend_image_push", "scenario": "frontend_image_push",
"result": "success", "result": "success",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"details": { "details": {
"image": "${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}", "image": "${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}",
"version_tag": "${{ needs.gate.outputs.image_tag }}", "version_tag": "${{ needs.prepare.outputs.image_tag }}",
"sha_tag": "sha-${{ needs.gate.outputs.image_sha }}", "sha_tag": "sha-${{ needs.prepare.outputs.image_sha }}",
"registry": "${{ env.REGISTRY_HOST }}" "registry": "${{ env.REGISTRY_HOST }}"
} }
} }
EOF EOF
- name: Upload frontend push evidence - name: Upload frontend push evidence
@@ -182,50 +221,21 @@ jobs:
release-summary: release-summary:
name: Create Release Summary Evidence name: Create Release Summary Evidence
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [gate, backend-image, frontend-image] needs: [prepare, backend-image, frontend-image]
if: always() && needs.gate.outputs.is_release_tag == 'true' if: always()
steps: steps:
- name: Generate release summary - name: Generate release summary
run: | run: |
mkdir -p .sisyphus/evidence mkdir -p .sisyphus/evidence
# Task 30 evidence: CI gate validation
cat > .sisyphus/evidence/task-30-ci-gate.json <<EOF
{
"scenario": "ci_success_gate",
"result": "passed",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"details": {
"ci_workflow": "CI Pipeline",
"ci_conclusion": "${{ github.event.workflow_run.conclusion }}",
"source_ref": "${{ github.event.workflow_run.head_branch }}",
"validated": "true"
}
}
EOF
# Task 30 evidence: Non-tag skip proof (placeholder for documentation)
cat > .sisyphus/evidence/task-30-non-tag-skip.json <<EOF
{
"scenario": "non_release_tag_skip",
"result": "not_applicable",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"details": {
"note": "This workflow only runs on release tags (refs/tags/v*)",
"gate_condition": "is_release_tag == true",
"current_execution": "release_tag_detected"
}
}
EOF
# Task 33 evidence: CD bootstrap release summary # Task 33 evidence: CD bootstrap release summary
cat > .sisyphus/evidence/task-33-cd-bootstrap-release.json <<EOF cat > .sisyphus/evidence/task-33-cd-bootstrap-release.json <<EOF
{ {
"release_tag": "${{ needs.gate.outputs.image_tag }}", "release_tag": "${{ needs.prepare.outputs.image_tag }}",
"commit_sha": "${{ needs.gate.outputs.image_sha }}", "commit_sha": "${{ needs.prepare.outputs.image_sha }}",
"backend_image": "${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.gate.outputs.image_tag }}", "backend_image": "${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}",
"frontend_image": "${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.gate.outputs.image_tag }}", "frontend_image": "${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}",
"backend_job_conclusion": "${{ needs.backend-image.result }}", "backend_job_conclusion": "${{ needs.backend-image.result }}",
"frontend_job_conclusion": "${{ needs.frontend-image.result }}", "frontend_job_conclusion": "${{ needs.frontend-image.result }}",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
@@ -243,14 +253,14 @@ jobs:
run: | run: |
echo "## 🚀 CD Bootstrap Release Summary" >> $GITHUB_STEP_SUMMARY echo "## 🚀 CD Bootstrap Release Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "**Release Tag:** ${{ needs.gate.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY echo "**Release Tag:** ${{ needs.prepare.outputs.image_tag }}" >> $GITHUB_STEP_SUMMARY
echo "**Commit SHA:** ${{ needs.gate.outputs.image_sha }}" >> $GITHUB_STEP_SUMMARY echo "**Commit SHA:** ${{ needs.prepare.outputs.image_sha }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### Published Images" >> $GITHUB_STEP_SUMMARY echo "### Published Images" >> $GITHUB_STEP_SUMMARY
echo "- **Backend:** \`${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.gate.outputs.image_tag }}\`" >> $GITHUB_STEP_SUMMARY echo "- **Backend:** \`${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Backend SHA:** \`${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }}\`" >> $GITHUB_STEP_SUMMARY echo "- **Backend SHA:** \`${{ env.REGISTRY_HOST }}/${{ env.BACKEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Frontend:** \`${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.gate.outputs.image_tag }}\`" >> $GITHUB_STEP_SUMMARY echo "- **Frontend:** \`${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:${{ needs.prepare.outputs.image_tag }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Frontend SHA:** \`${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.gate.outputs.image_sha }}\`" >> $GITHUB_STEP_SUMMARY echo "- **Frontend SHA:** \`${{ env.REGISTRY_HOST }}/${{ env.FRONTEND_IMAGE }}:sha-${{ needs.prepare.outputs.image_sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### Job Results" >> $GITHUB_STEP_SUMMARY echo "### Job Results" >> $GITHUB_STEP_SUMMARY
echo "- Backend Image: ${{ needs.backend-image.result }}" >> $GITHUB_STEP_SUMMARY echo "- Backend Image: ${{ needs.backend-image.result }}" >> $GITHUB_STEP_SUMMARY