pulumi preview --diff outputs a custom format that's not compatible with standard diff/patch tools or GitHub's diff syntax highlighting:
~ aws:cloudwatch/logGroup:LogGroup: (update)
~ retentionInDays: 0 => 90
+ tags : {
+ ManagedBy: "Pulumi"
}
+ aws:iam/role:Role: (create)
name: "github-actions-role-2"
This makes it difficult to:
- Get proper syntax highlighting in GitHub PR comments/issues
- Use standard diff tools (
patch,delta,diff-so-fancy) - Integrate with CI systems that expect unified diff format
Critical issue: GitHub's diff syntax highlighting requires +/- markers at column 0 (line start). Pulumi's current output has markers after indentation, so no highlighting occurs.
Add a --patch flag to pulumi preview that outputs GitHub-compatible diff format:
pulumi preview --patchCRITICAL: Markers MUST be at column 0 (start of line), not after indentation.
+at column 0 for additions (resources being created, properties being added)-at column 0 for deletions (resources being deleted, properties being removed)(space) at column 0 for context lines- Value changes (
old => new) expanded to-/+line pairs - Original indentation preserved AFTER the marker
Example - WRONG (current behavior, markers after indent):
~ aws:cloudwatch/logGroup:LogGroup: (update)
- retentionInDays: 0
+ retentionInDays: 90
Example - CORRECT (markers at column 0):
~ aws:cloudwatch/logGroup:LogGroup: (update)
- retentionInDays: 0
+ retentionInDays: 90- Markers at column 0: All
+/-/~/markers must be the first character of the line - Value changes: Lines with
=>should be expanded to two lines:retentionInDays: 0 => 90becomes:- retentionInDays: 0 + retentionInDays: 90
- Provider version changes:
[provider: old => new]lines should also be expanded:[provider=pulumi:providers:aws 6.65.0 => 6.66.0]becomes:- [provider=pulumi:providers:aws 6.65.0] + [provider=pulumi:providers:aws 6.66.0]
- Block propagation: When a resource is created (
+) or deleted (-), all nested properties inherit that marker - Updates (
~): Resource-level updates use~marker; property-level changes within use+/- - Context lines: Unchanged content uses
(space) at column 0 - ANSI colors: When combined with
--color always, output ANSI-colored diff (green/red/yellow)
Input (current --diff output):
Previewing update (dev)
View in Browser (Conditions API): https://app.pulumi.com/...
Type Name Plan Info
pulumi:pulumi:Stack oa-ci-dev
~ └─ aws:cloudwatch:LogGroup github-runners update [diff: ~retentionInDays]
Resources:
~ 1 to update
9 unchanged
---outputs:---
...
Resources:
~ 1 to update
9 unchanged
Do you want to perform this update?
yes
> no
details
Expected output (--patch):
Previewing update (dev)
View in Browser (Conditions API): https://app.pulumi.com/...
Type Name Plan Info
pulumi:pulumi:Stack oa-ci-dev
~ └─ aws:cloudwatch:LogGroup github-runners update [diff: ~retentionInDays]
Resources:
~ 1 to update
9 unchangedInput (from detailed diff view):
~ aws:cloudwatch/logGroup:LogGroup: (update)
[id=/aws/ec2/github-runners]
[urn=urn:pulumi:dev::oa-ci::aws:cloudwatch/logGroup:LogGroup::github-runners]
[provider=pulumi:providers:aws::default_6_66_0::a1b2c3d4]
~ retentionInDays: 0 => 90
Expected output (--patch):
~ aws:cloudwatch/logGroup:LogGroup: (update)
[id=/aws/ec2/github-runners]
[urn=urn:pulumi:dev::oa-ci::aws:cloudwatch/logGroup:LogGroup::github-runners]
[provider=pulumi:providers:aws::default_6_66_0::a1b2c3d4]
- retentionInDays: 0
+ retentionInDays: 90Input:
~ aws:iam/role:Role: (update)
[id=github-actions-role-0]
[urn=urn:pulumi:dev::oa-ci::aws:iam/role:Role::github-actions-role-0]
[provider: pulumi:providers:aws 6.65.0 => 6.66.0]
Expected output (--patch):
~ aws:iam/role:Role: (update)
[id=github-actions-role-0]
[urn=urn:pulumi:dev::oa-ci::aws:iam/role:Role::github-actions-role-0]
- [provider: pulumi:providers:aws 6.65.0]
+ [provider: pulumi:providers:aws 6.66.0]Input:
+ aws:iam/role:Role: (create)
name: "github-actions-role-2"
assumeRolePolicy: "{...}"
Expected output (--patch):
+ aws:iam/role:Role: (create)
+ name: "github-actions-role-2"
+ assumeRolePolicy: "{...}"Input:
- aws:iam/role:OldRole: (delete)
[id=old-role-id]
name: "old-role"
Expected output (--patch):
- aws:iam/role:OldRole: (delete)
- [id=old-role-id]
- name: "old-role"Input:
Previewing update (dev)
Type Name Plan Info
pulumi:pulumi:Stack oa-ci-dev
+ ├─ aws:iam:Role new-role create
~ ├─ aws:cloudwatch:LogGroup github-runners update [diff: ~retentionInDays]
- └─ aws:iam:Role old-role delete
---outputs:---
...
Expected output (--patch):
Previewing update (dev)
Type Name Plan Info
pulumi:pulumi:Stack oa-ci-dev
+ ├─ aws:iam:Role new-role create
~ ├─ aws:cloudwatch:LogGroup github-runners update [diff: ~retentionInDays]
- └─ aws:iam:Role old-role delete
---outputs:---
...With native --patch support:
- name: Run Pulumi preview
run: |
pulumi preview --patch --non-interactive 2>&1 | tee pulumi-output.txt
- name: Comment on PR
run: |
gh pr comment --body "$(cat <<'EOF'
## Pulumi Preview
\`\`\`diff
$(cat pulumi-output.txt)
\`\`\`
EOF
)"The diff output is generated in:
pkg/backend/display/- display/rendering logicpkg/backend/display/object_diff.go- object/property diff formatting
Key areas to modify:
- Add
--patchflag to preview command (pkg/cmd/pulumi/operations/preview.go) - Modify diff rendering to output markers at column 0 (
pkg/backend/display/object_diff.go) - Expand
=>patterns to-/+line pairs
The core transformation is:
BEFORE: " + property: value" (marker after indent)
AFTER: "+ property: value" (marker at column 0, indent preserved after)
This can be done by:
- Detecting lines with leading whitespace followed by
+/-/~ - Extracting: (indent, marker, rest)
- Outputting: marker + indent + rest
- Post-processing scripts - fragile, doesn't handle all edge cases, requires maintenance
- JSON output + external tool -
--jsonexists but requires separate formatting tool - ANSI-to-HTML conversion - preserves colors but not widely supported in markdown