GitHub Actions Heredoc Indentation Guide¶
When writing heredocs that generate YAML files in GitHub Actions workflows (like pr-preview.yml), you must understand how whitespace is processed.
How Whitespace Processing Works¶
-
YAML Block Scalar Processing: GitHub Actions parses the workflow YAML first. Content in a
run: |block has its base indentation stripped (~10 spaces for steps nested under jobs). -
sed Post-Processing: The workflow uses
sedto strip any remaining leading spaces.
Two Valid Patterns¶
Both patterns produce correct output - choose either and be consistent:
Pattern A: 10 spaces base (simpler)¶
cat > file.yaml <<EOF
apiVersion: v1 # 10 spaces → 0 after YAML
spec:
containers: # 12 spaces → 2 after YAML
EOF
sed -i 's/^ //' file.yaml # sed matches nothing (no-op), but output is already correct
- Used by:
pr.yaml,namespace.yaml,mongodb-user.yaml - The sed command is effectively a no-op (could be removed)
Pattern B: 20 spaces base¶
cat > file.yaml <<EOF
apiVersion: v1 # 20 spaces → 10 after YAML → 0 after sed
spec:
containers: # 22 spaces → 12 after YAML → 2 after sed
EOF
sed -i 's/^ //' file.yaml # sed strips 10 spaces
- Used by:
db-reset-job.yaml - The sed command actively strips remaining indentation
The Critical Rule¶
The sed command must match what remains AFTER YAML processing:
- If content has 10 spaces base → after YAML has 0 spaces → sed (10 spaces) = no-op
- If content has 20 spaces base → after YAML has 10 spaces → sed (10 spaces) = strips correctly
- If content has 20 spaces base → after YAML has 10 spaces → sed (20 spaces) = BUG!
The Bug That Breaks Things¶
# WRONG - sed doesn't match what YAML processing left behind
cat > file.yaml <<EOF
apiVersion: v1 # 20 spaces → 10 after YAML
spec:
containers: # 22 spaces → 12 after YAML
image: bar # 26 spaces → 16 after YAML
EOF
sed -i 's/^ //' file.yaml # Tries to strip 20 spaces!
Result: apiVersion (10 spaces) doesn't match sed → stays at column 10. image (16 spaces) doesn't match → stays at column 16. Only lines with exactly 20+ spaces get stripped to 0, producing broken YAML.
Files in pr-preview.yml¶
| File | Pattern | Base Spaces | sed Strips |
|---|---|---|---|
pr.yaml |
A | 10 | 10 (no-op) |
namespace.yaml |
A | 10 | 10 (no-op) |
mongodb-user.yaml |
A | 10 | 10 (no-op) |
db-reset-job.yaml |
B | 20 | 10 |