## Problem PR #906 changed healthcheck commands from `wget` to `curl`, but Alpine Linux (our base image) does not include `curl` by default, causing all containers to fail healthchecks with: ``` exec: "curl": executable file not found in $PATH ``` This creates a configuration mismatch: - docker/Dockerfile.backend uses `wget` (✅ works) - docker-compose.yml uses `curl` (❌ fails) ## Root Cause Analysis Alpine Linux philosophy is minimalism: - ✅ `wget` is pre-installed (part of busybox) - ❌ `curl` requires `apk add curl` (~3MB extra) The original PR #906 made two commits: 1. First commit (3af8760): `curl` → `wget` (✅ correct fix) 2. Second commit (333b2ef): `wget` → `curl` (❌ introduced bug) The second commit was based on incorrect assumption that "curl is more widely available than wget in Docker images". This is false for Alpine. ## Solution Revert healthcheck commands back to `wget` to match: 1. Alpine's pre-installed tools 2. Dockerfile.backend healthcheck (line 68) 3. Docker and Kubernetes best practices ## Testing ✅ Verified `wget` exists in Alpine containers: ```bash docker run --rm alpine:latest which wget # Output: /usr/bin/wget ``` ✅ Added new CI workflow to prevent regression: - `.github/workflows/pr-docker-compose-healthcheck.yml` - Validates healthcheck compatibility with Alpine - Ensures containers reach healthy status ## Impact - **Before**: Containers show (unhealthy), potential auto-restart loops - **After**: Containers show (healthy), monitoring systems happy - **Scope**: Only affects docker-compose deployments - **Breaking**: None - this is a bug fix ## References - PR #906: Original (incorrect) fix - Alpine Linux: https://alpinelinux.org/about/ - Dockerfile.backend L68: Existing `wget` healthcheck 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: the-dev-z <the-dev-z@users.noreply.github.com> Co-authored-by: tinkle-community <tinklefund@gmail.com> Co-authored-by: Shui <88711385+hzb1115@users.noreply.github.com>
GitHub Actions Workflows
This directory contains the GitHub Actions workflows for the NOFX project.
📚 Documentation Index
- README.md - This file, overview of all workflows
- PERMISSIONS.md - Detailed permission analysis and security model
- TRIGGERS.md - Comparison of event triggers (pull_request vs pull_request_target vs workflow_run)
- FORK_PR_FLOW.md - Complete analysis of what happens when a fork PR is submitted
- FLOW_DIAGRAM.md - Visual flow diagrams and quick reference
- SECRETS_SCANNING.md - Secrets scanning solutions and TruffleHog setup
🚀 Quick Start
Want to understand how fork PRs work? → Read FLOW_DIAGRAM.md
Need security details? → Read PERMISSIONS.md
Confused about triggers? → Read TRIGGERS.md
PR Check Workflows
We use a two-workflow pattern to safely handle PR checks from both internal and fork PRs:
1. pr-checks-run.yml - Execute Checks
Trigger: On pull request (opened, synchronize, reopened)
Permissions: Read-only
Purpose: Executes all PR checks with read-only permissions, making it safe for fork PRs.
What it does:
- ✅ Checks PR title format (Conventional Commits)
- ✅ Calculates PR size
- ✅ Runs backend checks (Go formatting, vet, tests)
- ✅ Runs frontend checks (linting, type checking, build)
- ✅ Saves all results as artifacts
Security: Safe for fork PRs because it only has read permissions and cannot access secrets or modify the repository.
2. pr-checks-comment.yml - Post Results
Trigger: When pr-checks-run.yml completes (workflow_run)
Permissions: Write (pull-requests, issues)
Purpose: Posts check results as PR comments, running in the main repository context.
What it does:
- ✅ Downloads artifacts from
pr-checks-run.yml - ✅ Reads check results
- ✅ Posts a comprehensive comment to the PR
Security: Safe because:
- Runs in the main repository context (not fork context)
- Has write permissions but doesn't execute untrusted code
- Only reads pre-generated results from artifacts
3. pr-checks.yml - Strict Checks
Trigger: On pull request
Permissions: Read + conditional write
Purpose: Runs mandatory checks that must pass before PR can be merged.
What it does:
- ✅ Validates PR title (blocks merge if invalid)
- ✅ Auto-labels PR based on size and files changed (non-fork only)
- ✅ Runs backend tests (Go)
- ✅ Runs frontend tests (React/TypeScript)
- ✅ Security scanning (Trivy, Gitleaks)
Security:
- Fork PRs: Only runs read-only operations (tests, security scans)
- Non-fork PRs: Can add labels and comments
- Uses
continue-on-errorfor operations that may fail on forks
Why Two Workflows for PR Checks?
The Problem
When a PR comes from a forked repository:
- GitHub restricts
GITHUB_TOKENpermissions for security - Fork PRs cannot write comments, add labels, or access secrets
- This prevents malicious contributors from:
- Stealing repository secrets
- Modifying workflow files to execute malicious code
- Spamming issues/PRs with automated comments
The Solution
Two-Workflow Pattern:
Fork PR Submitted
↓
[pr-checks-run.yml]
- Runs with read-only permissions
- Executes all checks safely
- Saves results to artifacts
↓
[pr-checks-comment.yml]
- Triggered by workflow_run
- Runs in main repo context (has write permissions)
- Downloads artifacts
- Posts comment with results
This approach:
- ✅ Allows fork PRs to run checks
- ✅ Safely posts results as comments
- ✅ Prevents security vulnerabilities
- ✅ Follows GitHub's best practices
Can workflow_run Comment on Fork PRs?
Yes! ✅ The permissions are sufficient.
Key Understanding:
workflow_runexecutes in the base repository context- Fork PRs exist in the base repository (not in the fork)
- The base repository's
GITHUB_TOKENhas write permissions - Therefore,
workflow_runcan comment on fork PRs
Security:
- Fork PR code runs in isolated environment (read-only)
- Comment workflow doesn't execute fork code
- Only reads pre-generated artifact data
For detailed permission analysis, see: PERMISSIONS.md
Workflow Comparison
| Workflow | Fork PRs | Write Access | Blocks Merge | Purpose |
|---|---|---|---|---|
pr-checks-run.yml |
✅ Yes | ❌ No | ❌ No | Advisory checks |
pr-checks-comment.yml |
✅ Yes | ✅ Yes* | ❌ No | Post results |
pr-checks.yml |
✅ Yes | ⚠️ Partial | ✅ Yes | Mandatory checks |
* Write access only in main repo context, not available to fork PR code
File History
pr-checks-advisory.yml.old- Old advisory workflow that failed on fork PRs (deprecated)- Now replaced by the two-workflow pattern (
pr-checks-run.yml+pr-checks-comment.yml)
Testing the Workflows
Test with a Fork PR
- Fork the repository
- Make changes in your fork
- Create a PR to the main repository
- Observe:
pr-checks-run.ymlruns successfully with read-only accesspr-checks-comment.ymlposts results as a commentpr-checks.ymlruns tests but skips labeling
Test with a Branch PR
- Create a branch in the main repository
- Make changes
- Create a PR
- Observe:
- All workflows run with full permissions
- Labels are added automatically
- Comments are posted