pipecraft 0.0.0-releaseit
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +35 -0
- package/.github/actions/calculate-version/action.yml +106 -0
- package/.github/actions/create-pr/action.yml +122 -0
- package/.github/actions/create-release/action.yml +74 -0
- package/.github/actions/create-tag/action.yml +94 -0
- package/.github/actions/detect-changes/action.yml +62 -0
- package/.github/actions/manage-branch/action.yml +113 -0
- package/.github/actions/promote-branch/action.yml +352 -0
- package/.github/example/workflows/job.analyze.code.yml +26 -0
- package/.github/example/workflows/job.analyze.docker.yml +32 -0
- package/.github/example/workflows/job.app.api.deploy.yml +127 -0
- package/.github/example/workflows/job.app.api.test.yml +102 -0
- package/.github/example/workflows/job.app.docs.deploy.yml +40 -0
- package/.github/example/workflows/job.app.docs.test.yml +50 -0
- package/.github/example/workflows/job.app.web.deploy.yml +96 -0
- package/.github/example/workflows/job.app.web.test.yml +49 -0
- package/.github/example/workflows/job.changes.yml +82 -0
- package/.github/example/workflows/job.create-pr.yml +96 -0
- package/.github/example/workflows/job.env-check.yml +43 -0
- package/.github/example/workflows/job.fast-forward.yml +103 -0
- package/.github/example/workflows/job.lint.yml +64 -0
- package/.github/example/workflows/job.pr-name.yml +70 -0
- package/.github/example/workflows/job.pr-squash-name.yml +27 -0
- package/.github/example/workflows/job.tag.yml +38 -0
- package/.github/example/workflows/job.version.yml +99 -0
- package/.github/example/workflows/lib.plugin-base.publish.yml +59 -0
- package/.github/example/workflows/pipe.yml +178 -0
- package/.github/example/workflows/scripts/fastforward.sh +51 -0
- package/.github/example/workflows/scripts/pipe-cleaner.sh +70 -0
- package/.github/scripts/fastforward.sh +51 -0
- package/.github/scripts/pipe-cleaner.sh +70 -0
- package/.github/workflows/pipeline.yml +220 -0
- package/.github/workflows/pr-title-check.yml +70 -0
- package/.github/workflows/publish.yml +39 -0
- package/.pipecraftrc.json +78 -0
- package/.release-it.cjs +71 -0
- package/PIPELINE_TESTING_PLAN.md +499 -0
- package/README.md +1101 -0
- package/TRUNK_FLOW_PLAN.md +401 -0
- package/assets/logo_banner.png +0 -0
- package/assets/logo_banner.webp +0 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +364 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/generators/init.tpl.d.ts +3 -0
- package/dist/generators/init.tpl.d.ts.map +1 -0
- package/dist/generators/init.tpl.js +117 -0
- package/dist/generators/init.tpl.js.map +1 -0
- package/dist/generators/workflows.tpl.d.ts +7 -0
- package/dist/generators/workflows.tpl.d.ts.map +1 -0
- package/dist/generators/workflows.tpl.js +73 -0
- package/dist/generators/workflows.tpl.js.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js +122 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.js +145 -0
- package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.js +111 -0
- package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js +79 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js +130 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js +362 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +16 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +652 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/ast-path-operations.d.ts +287 -0
- package/dist/utils/ast-path-operations.d.ts.map +1 -0
- package/dist/utils/ast-path-operations.js +419 -0
- package/dist/utils/ast-path-operations.js.map +1 -0
- package/dist/utils/config.d.ts +3 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +49 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/github-setup.d.ts +74 -0
- package/dist/utils/github-setup.d.ts.map +1 -0
- package/dist/utils/github-setup.js +418 -0
- package/dist/utils/github-setup.js.map +1 -0
- package/dist/utils/idempotency.d.ts +47 -0
- package/dist/utils/idempotency.d.ts.map +1 -0
- package/dist/utils/idempotency.js +176 -0
- package/dist/utils/idempotency.js.map +1 -0
- package/dist/utils/preflight.d.ts +55 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +261 -0
- package/dist/utils/preflight.js.map +1 -0
- package/dist/utils/versioning.d.ts +41 -0
- package/dist/utils/versioning.d.ts.map +1 -0
- package/dist/utils/versioning.js +219 -0
- package/dist/utils/versioning.js.map +1 -0
- package/docs/USER_JOURNEY_ERRORS.md +352 -0
- package/eslint.config.js +77 -0
- package/examples/basic-config.json +41 -0
- package/examples/monorepo-config.json +49 -0
- package/examples/usage.md +289 -0
- package/package.json +58 -0
- package/scripts/debug-workflows.sh +339 -0
- package/scripts/parse-pipeline.js +29 -0
- package/scripts/test-job-order.cjs +140 -0
- package/scripts/validate-pipeline.cjs +379 -0
- package/scripts/verify-job-order.sh +30 -0
- package/src/cli/index.ts +414 -0
- package/src/generators/init.tpl.ts +126 -0
- package/src/generators/workflows.tpl.ts +80 -0
- package/src/templates/actions/calculate-version.yml.tpl.ts +124 -0
- package/src/templates/actions/create-pr.yml.tpl.ts +147 -0
- package/src/templates/actions/create-tag.yml.tpl.ts +112 -0
- package/src/templates/actions/detect-changes.yml.tpl.ts +87 -0
- package/src/templates/actions/manage-branch.yml.tpl.ts +132 -0
- package/src/templates/actions/promote-branch.yml.tpl.ts +364 -0
- package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +706 -0
- package/src/types/index.ts +64 -0
- package/src/utils/README-ast-path-operations.md +390 -0
- package/src/utils/ast-path-operations.ts +581 -0
- package/src/utils/config.ts +64 -0
- package/src/utils/github-setup.ts +558 -0
- package/src/utils/idempotency.ts +215 -0
- package/src/utils/preflight.ts +306 -0
- package/src/utils/versioning.ts +244 -0
- package/tests/README.md +229 -0
- package/tests/TEST_STRUCTURE.md +256 -0
- package/tests/act/run-act-tests.sh +345 -0
- package/tests/debugging/debug-utils.ts +538 -0
- package/tests/debugging/debug-workflow.test.ts +339 -0
- package/tests/debugging/debug-workflows.sh +339 -0
- package/tests/debugging/iterative-debug.ts +652 -0
- package/tests/debugging/run-debug-tests.sh +431 -0
- package/tests/fixtures/basic-config.json +51 -0
- package/tests/fixtures/invalid-config.json +9 -0
- package/tests/fixtures/pipeline-generated.yml +235 -0
- package/tests/fixtures/pipeline-preserve-comments.yml +245 -0
- package/tests/fixtures/pipeline-user-modified.yml +245 -0
- package/tests/fixtures/test-config.json +58 -0
- package/tests/github-live/README.md +250 -0
- package/tests/github-local/JOB_WORKFLOW_TESTS.md +296 -0
- package/tests/github-local/README.md +240 -0
- package/tests/github-local/run-all-tests.sh +422 -0
- package/tests/github-local/test-job-workflows.sh +631 -0
- package/tests/github-local/test-pipeline-workflow.sh +440 -0
- package/tests/integration/generators.test.ts +578 -0
- package/tests/integration/path-based-template.test.ts +510 -0
- package/tests/integration/simple-path-based.test.ts +415 -0
- package/tests/setup.ts +56 -0
- package/tests/unit/ast-path-operations-extended.test.ts +302 -0
- package/tests/unit/cli.test.ts +541 -0
- package/tests/unit/config-extended.test.ts +412 -0
- package/tests/unit/config.test.ts +152 -0
- package/tests/unit/github-setup.test.ts +189 -0
- package/tests/unit/idempotency-isolated.test.ts +297 -0
- package/tests/unit/job-order.test.ts +157 -0
- package/tests/unit/pipeline-path-based.test.ts +511 -0
- package/tests/unit/validate-pipeline.test.ts +384 -0
- package/tests/unit/versioning-extended.test.ts +279 -0
- package/tests/unit/versioning.test.ts +241 -0
- package/tsconfig.debug.json +17 -0
- package/tsconfig.json +28 -0
- package/vitest.config.ts +51 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
import { PinionContext, toFile, renderTemplate } from '@featherscloud/pinion'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import dedent from 'dedent'
|
|
4
|
+
|
|
5
|
+
// Template for the Promote Branch GitHub Action
|
|
6
|
+
// This action handles branch promotions via temporary branches + PRs
|
|
7
|
+
const promoteBranchActionTemplate = (ctx: any) => {
|
|
8
|
+
return dedent`name: 'Promote Branch'
|
|
9
|
+
description: 'Promote code from source to target branch via temporary branch + PR'
|
|
10
|
+
author: 'PipeCraft'
|
|
11
|
+
|
|
12
|
+
inputs:
|
|
13
|
+
sourceBranch:
|
|
14
|
+
description: 'Source branch to promote from (defaults to github.ref_name)'
|
|
15
|
+
required: false
|
|
16
|
+
default: \${{ github.ref_name }}
|
|
17
|
+
version:
|
|
18
|
+
description: 'Version being promoted (e.g., v1.2.3, auto-detected from git tags if not provided)'
|
|
19
|
+
required: false
|
|
20
|
+
default: ''
|
|
21
|
+
configPath:
|
|
22
|
+
description: 'Path to .pipecraftrc.json config file'
|
|
23
|
+
required: false
|
|
24
|
+
default: '.pipecraftrc.json'
|
|
25
|
+
tempBranchPattern:
|
|
26
|
+
description: 'Pattern for temp branch name'
|
|
27
|
+
required: false
|
|
28
|
+
default: 'release/{source}-to-{target}-{version}'
|
|
29
|
+
token:
|
|
30
|
+
description: 'GitHub token for authentication'
|
|
31
|
+
required: false
|
|
32
|
+
default: \${{ github.token }}
|
|
33
|
+
|
|
34
|
+
outputs:
|
|
35
|
+
prNumber:
|
|
36
|
+
description: 'The created PR number'
|
|
37
|
+
value: \${{ steps.create-pr.outputs.prNumber }}
|
|
38
|
+
prUrl:
|
|
39
|
+
description: 'The created PR URL'
|
|
40
|
+
value: \${{ steps.create-pr.outputs.prUrl }}
|
|
41
|
+
tempBranch:
|
|
42
|
+
description: 'The temporary branch name'
|
|
43
|
+
value: \${{ steps.create-temp.outputs.tempBranch }}
|
|
44
|
+
targetBranch:
|
|
45
|
+
description: 'The target branch determined from config'
|
|
46
|
+
value: \${{ steps.read-config.outputs.targetBranch }}
|
|
47
|
+
autoMerge:
|
|
48
|
+
description: 'The autoMerge setting for the target branch'
|
|
49
|
+
value: \${{ steps.read-config.outputs.autoMerge }}
|
|
50
|
+
|
|
51
|
+
runs:
|
|
52
|
+
using: 'composite'
|
|
53
|
+
steps:
|
|
54
|
+
- name: Checkout Code
|
|
55
|
+
uses: actions/checkout@v4
|
|
56
|
+
with:
|
|
57
|
+
fetch-depth: 0
|
|
58
|
+
token: \${{ inputs.token }}
|
|
59
|
+
|
|
60
|
+
- name: Read Config and Determine Target Branch
|
|
61
|
+
id: read-config
|
|
62
|
+
shell: bash
|
|
63
|
+
run: |
|
|
64
|
+
SOURCE="\${{ inputs.sourceBranch }}"
|
|
65
|
+
CONFIG_PATH="\${{ inputs.configPath }}"
|
|
66
|
+
|
|
67
|
+
echo "๐ Reading config from \$CONFIG_PATH"
|
|
68
|
+
|
|
69
|
+
# Check if config file exists
|
|
70
|
+
if [ ! -f "\$CONFIG_PATH" ]; then
|
|
71
|
+
echo "โ Config file not found: \$CONFIG_PATH"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Read branchFlow array from config
|
|
76
|
+
BRANCH_FLOW=\$(cat "\$CONFIG_PATH" | jq -r '.branchFlow | join(" ")')
|
|
77
|
+
echo "๐ Branch flow: \$BRANCH_FLOW"
|
|
78
|
+
|
|
79
|
+
# Convert to array
|
|
80
|
+
IFS=' ' read -ra BRANCHES <<< "\$BRANCH_FLOW"
|
|
81
|
+
|
|
82
|
+
# Find current branch index and determine target
|
|
83
|
+
TARGET=""
|
|
84
|
+
for i in "\${!BRANCHES[@]}"; do
|
|
85
|
+
if [ "\${BRANCHES[\$i]}" == "\$SOURCE" ]; then
|
|
86
|
+
# Get next branch in flow
|
|
87
|
+
NEXT_INDEX=\$((i + 1))
|
|
88
|
+
if [ \$NEXT_INDEX -lt \${#BRANCHES[@]} ]; then
|
|
89
|
+
TARGET="\${BRANCHES[\$NEXT_INDEX]}"
|
|
90
|
+
fi
|
|
91
|
+
break
|
|
92
|
+
fi
|
|
93
|
+
done
|
|
94
|
+
|
|
95
|
+
if [ -z "\$TARGET" ]; then
|
|
96
|
+
echo "โ Could not determine target branch for source: \$SOURCE"
|
|
97
|
+
echo " Branch flow: \$BRANCH_FLOW"
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo "โ
Target branch: \$TARGET"
|
|
102
|
+
echo "targetBranch=\$TARGET" >> \$GITHUB_OUTPUT
|
|
103
|
+
|
|
104
|
+
# Determine autoMerge setting for target branch
|
|
105
|
+
AUTO_MERGE=\$(cat "\$CONFIG_PATH" | jq -r ".autoMerge.\"\$TARGET\" // false")
|
|
106
|
+
echo "๐ Auto-merge for \$TARGET: \$AUTO_MERGE"
|
|
107
|
+
echo "autoMerge=\$AUTO_MERGE" >> \$GITHUB_OUTPUT
|
|
108
|
+
|
|
109
|
+
- name: Get Version
|
|
110
|
+
id: get-version
|
|
111
|
+
shell: bash
|
|
112
|
+
run: |
|
|
113
|
+
VERSION_INPUT="\${{ inputs.version }}"
|
|
114
|
+
|
|
115
|
+
if [ -n "\$VERSION_INPUT" ]; then
|
|
116
|
+
VERSION="\$VERSION_INPUT"
|
|
117
|
+
echo "๐ Using provided version: \$VERSION"
|
|
118
|
+
else
|
|
119
|
+
# Auto-detect from git tags
|
|
120
|
+
VERSION=\$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0")
|
|
121
|
+
echo "๐ท๏ธ Auto-detected version from tags: \$VERSION"
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
echo "version=\$VERSION" >> \$GITHUB_OUTPUT
|
|
125
|
+
|
|
126
|
+
- name: Create Temporary Branch
|
|
127
|
+
id: create-temp
|
|
128
|
+
shell: bash
|
|
129
|
+
run: |
|
|
130
|
+
SOURCE="\${{ inputs.sourceBranch }}"
|
|
131
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
132
|
+
VERSION="\${{ steps.get-version.outputs.version }}"
|
|
133
|
+
PATTERN="\${{ inputs.tempBranchPattern }}"
|
|
134
|
+
|
|
135
|
+
# Remove 'v' prefix from version for branch name
|
|
136
|
+
VERSION_CLEAN="\${VERSION#v}"
|
|
137
|
+
|
|
138
|
+
# Replace placeholders in pattern
|
|
139
|
+
TEMP_BRANCH="\$PATTERN"
|
|
140
|
+
TEMP_BRANCH="\${TEMP_BRANCH//\{source\}/\$SOURCE}"
|
|
141
|
+
TEMP_BRANCH="\${TEMP_BRANCH//\{target\}/\$TARGET}"
|
|
142
|
+
TEMP_BRANCH="\${TEMP_BRANCH//\{version\}/\$VERSION_CLEAN}"
|
|
143
|
+
|
|
144
|
+
echo "๐ฟ Preparing temporary branch: \$TEMP_BRANCH"
|
|
145
|
+
echo " From: \$SOURCE"
|
|
146
|
+
echo " To: \$TARGET"
|
|
147
|
+
echo " Version: \$VERSION"
|
|
148
|
+
|
|
149
|
+
# Ensure we're on the source branch
|
|
150
|
+
git checkout "\$SOURCE"
|
|
151
|
+
|
|
152
|
+
# Check if temp branch already exists locally or remotely
|
|
153
|
+
if git show-ref --verify --quiet refs/heads/"\$TEMP_BRANCH" || git ls-remote --heads origin "\$TEMP_BRANCH" | grep -q "\$TEMP_BRANCH"; then
|
|
154
|
+
echo "โ ๏ธ Temp branch \$TEMP_BRANCH already exists, using existing branch"
|
|
155
|
+
# Fetch and checkout existing branch
|
|
156
|
+
git fetch origin "\$TEMP_BRANCH" 2>/dev/null || true
|
|
157
|
+
git checkout "\$TEMP_BRANCH" 2>/dev/null || git checkout -b "\$TEMP_BRANCH" origin/"\$TEMP_BRANCH"
|
|
158
|
+
else
|
|
159
|
+
echo "๐ Creating new temp branch \$TEMP_BRANCH"
|
|
160
|
+
# Create temp branch from current commit
|
|
161
|
+
git checkout -b "\$TEMP_BRANCH"
|
|
162
|
+
# Push temp branch to remote
|
|
163
|
+
git push origin "\$TEMP_BRANCH"
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
echo "tempBranch=\$TEMP_BRANCH" >> \$GITHUB_OUTPUT
|
|
167
|
+
echo "โ
Temporary branch ready"
|
|
168
|
+
|
|
169
|
+
- name: Check for Existing PR
|
|
170
|
+
id: check-pr
|
|
171
|
+
shell: bash
|
|
172
|
+
env:
|
|
173
|
+
GH_TOKEN: \${{ inputs.token }}
|
|
174
|
+
run: |
|
|
175
|
+
TEMP_BRANCH="\${{ steps.create-temp.outputs.tempBranch }}"
|
|
176
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
177
|
+
|
|
178
|
+
# Check if PR already exists from temp branch to target
|
|
179
|
+
EXISTING_PR=\$(gh pr list --head "\$TEMP_BRANCH" --base "\$TARGET" --json number --jq '.[0].number' 2>/dev/null || echo "")
|
|
180
|
+
|
|
181
|
+
if [ -n "\$EXISTING_PR" ]; then
|
|
182
|
+
echo "exists=true" >> \$GITHUB_OUTPUT
|
|
183
|
+
echo "prNumber=\$EXISTING_PR" >> \$GITHUB_OUTPUT
|
|
184
|
+
echo "โ ๏ธ PR already exists: #\$EXISTING_PR"
|
|
185
|
+
|
|
186
|
+
# Get PR URL
|
|
187
|
+
PR_URL=\$(gh pr view "\$EXISTING_PR" --json url --jq '.url')
|
|
188
|
+
echo "prUrl=\$PR_URL" >> \$GITHUB_OUTPUT
|
|
189
|
+
else
|
|
190
|
+
echo "exists=false" >> \$GITHUB_OUTPUT
|
|
191
|
+
echo "โ
No existing PR found"
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
- name: Create Pull Request
|
|
195
|
+
id: create-pr
|
|
196
|
+
if: steps.check-pr.outputs.exists == 'false'
|
|
197
|
+
shell: bash
|
|
198
|
+
env:
|
|
199
|
+
GH_TOKEN: \${{ inputs.token }}
|
|
200
|
+
run: |
|
|
201
|
+
TEMP_BRANCH="\${{ steps.create-temp.outputs.tempBranch }}"
|
|
202
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
203
|
+
SOURCE="\${{ inputs.sourceBranch }}"
|
|
204
|
+
VERSION="\${{ steps.get-version.outputs.version }}"
|
|
205
|
+
AUTO_MERGE="\${{ steps.read-config.outputs.autoMerge }}"
|
|
206
|
+
|
|
207
|
+
TITLE="๐ Release \$VERSION to \$TARGET"
|
|
208
|
+
|
|
209
|
+
# Determine merge behavior text
|
|
210
|
+
if [ "\$AUTO_MERGE" == "true" ]; then
|
|
211
|
+
MERGE_TEXT="merge automatically"
|
|
212
|
+
else
|
|
213
|
+
MERGE_TEXT="require manual approval"
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
# Disable error exit to capture gh pr create output even on failure
|
|
217
|
+
set +e
|
|
218
|
+
|
|
219
|
+
# Create the PR - gh pr create returns the PR URL on success
|
|
220
|
+
PR_URL=\$(gh pr create \\
|
|
221
|
+
--title "\$TITLE" \\
|
|
222
|
+
--body "Release \$VERSION from \$SOURCE to \$TARGET" \\
|
|
223
|
+
--head "\$TEMP_BRANCH" \\
|
|
224
|
+
--base "\$TARGET" 2>&1)
|
|
225
|
+
PR_EXIT_CODE=\$?
|
|
226
|
+
|
|
227
|
+
# Re-enable error exit
|
|
228
|
+
set -e
|
|
229
|
+
|
|
230
|
+
if [ \$PR_EXIT_CODE -eq 0 ] && [[ "\$PR_URL" =~ ^https://github.com/.*/pull/[0-9]+$ ]]; then
|
|
231
|
+
# Extract PR number from URL (e.g., https://github.com/owner/repo/pull/123)
|
|
232
|
+
PR_NUMBER=\$(echo "\$PR_URL" | grep -oE '[0-9]+$')
|
|
233
|
+
echo "prNumber=\$PR_NUMBER" >> \$GITHUB_OUTPUT
|
|
234
|
+
echo "prUrl=\$PR_URL" >> \$GITHUB_OUTPUT
|
|
235
|
+
echo "โ
Created PR #\$PR_NUMBER"
|
|
236
|
+
echo "๐ URL: \$PR_URL"
|
|
237
|
+
else
|
|
238
|
+
echo "โ Failed to create PR"
|
|
239
|
+
echo "Error output:"
|
|
240
|
+
echo "\$PR_URL"
|
|
241
|
+
exit 1
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
- name: Enable PR Auto-Merge with Rebase (Manual Approval Required)
|
|
245
|
+
if: steps.read-config.outputs.autoMerge == 'false'
|
|
246
|
+
shell: bash
|
|
247
|
+
env:
|
|
248
|
+
GH_TOKEN: \${{ inputs.token }}
|
|
249
|
+
run: |
|
|
250
|
+
PR_NUMBER="\${{ steps.check-pr.outputs.prNumber || steps.create-pr.outputs.prNumber }}"
|
|
251
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
252
|
+
|
|
253
|
+
echo "๐ Enabling auto-merge with rebase for PR #\$PR_NUMBER (requires approval)"
|
|
254
|
+
echo " This will fast-forward \$TARGET when approved, maintaining linear history"
|
|
255
|
+
|
|
256
|
+
# Enable auto-merge with rebase method (fast-forward, no merge commit)
|
|
257
|
+
gh pr merge "\$PR_NUMBER" --auto --rebase
|
|
258
|
+
|
|
259
|
+
echo "โ
Auto-merge enabled - PR will fast-forward merge when approved"
|
|
260
|
+
echo "โ ๏ธ Manual approval required before merge completes"
|
|
261
|
+
|
|
262
|
+
- name: Fast-Forward Merge (Immediate Auto-Merge)
|
|
263
|
+
if: steps.read-config.outputs.autoMerge == 'true'
|
|
264
|
+
shell: bash
|
|
265
|
+
run: |
|
|
266
|
+
SOURCE="\${{ inputs.sourceBranch }}"
|
|
267
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
268
|
+
VERSION="\${{ steps.get-version.outputs.version }}"
|
|
269
|
+
|
|
270
|
+
echo "๐ Fast-forwarding \$TARGET to \$SOURCE (maintaining linear history)"
|
|
271
|
+
|
|
272
|
+
# Get the commit SHA from source branch
|
|
273
|
+
COMMIT_SHA=\$(git rev-parse \$SOURCE)
|
|
274
|
+
echo "Source commit: \$COMMIT_SHA"
|
|
275
|
+
|
|
276
|
+
# Fetch target branch
|
|
277
|
+
git fetch origin \$TARGET:\$TARGET 2>/dev/null || true
|
|
278
|
+
|
|
279
|
+
# Checkout target branch
|
|
280
|
+
git checkout \$TARGET
|
|
281
|
+
|
|
282
|
+
# Verify we can fast-forward (no divergent commits)
|
|
283
|
+
if git merge-base --is-ancestor \$TARGET \$SOURCE; then
|
|
284
|
+
echo "โ
Fast-forward is possible (linear history maintained)"
|
|
285
|
+
else
|
|
286
|
+
echo "โ Cannot fast-forward - branches have diverged"
|
|
287
|
+
echo "Target branch has commits not in source branch"
|
|
288
|
+
exit 1
|
|
289
|
+
fi
|
|
290
|
+
|
|
291
|
+
# Fast-forward merge (no merge commit)
|
|
292
|
+
git merge --ff-only \$SOURCE
|
|
293
|
+
|
|
294
|
+
# Push to remote
|
|
295
|
+
git push origin \$TARGET
|
|
296
|
+
|
|
297
|
+
echo "โ
Fast-forwarded \$TARGET to \$COMMIT_SHA"
|
|
298
|
+
echo "๐ PR will be closed automatically for audit trail"
|
|
299
|
+
|
|
300
|
+
- name: Trigger Pipeline Workflow on Target Branch
|
|
301
|
+
if: steps.read-config.outputs.autoMerge == 'true'
|
|
302
|
+
shell: bash
|
|
303
|
+
env:
|
|
304
|
+
GH_TOKEN: \${{ inputs.token }}
|
|
305
|
+
run: |
|
|
306
|
+
TARGET="\${{ steps.read-config.outputs.targetBranch }}"
|
|
307
|
+
VERSION="\${{ steps.get-version.outputs.version }}"
|
|
308
|
+
|
|
309
|
+
echo "๐ Triggering pipeline workflow on \$TARGET branch with version \$VERSION"
|
|
310
|
+
|
|
311
|
+
# Trigger the pipeline workflow on the target branch
|
|
312
|
+
# This is necessary because GITHUB_TOKEN pushes don't trigger workflows by default
|
|
313
|
+
# Pass the version so the run name is descriptive
|
|
314
|
+
gh workflow run pipeline.yml --ref "\$TARGET" --field version="\$VERSION"
|
|
315
|
+
|
|
316
|
+
echo "โ
Pipeline workflow triggered on \$TARGET with version \$VERSION"
|
|
317
|
+
|
|
318
|
+
- name: Close PR and Delete Branch
|
|
319
|
+
if: steps.read-config.outputs.autoMerge == 'true'
|
|
320
|
+
shell: bash
|
|
321
|
+
env:
|
|
322
|
+
GH_TOKEN: \${{ inputs.token }}
|
|
323
|
+
run: |
|
|
324
|
+
TEMP_BRANCH="\${{ steps.create-temp.outputs.tempBranch }}"
|
|
325
|
+
PR_NUMBER="\${{ steps.check-pr.outputs.prNumber || steps.create-pr.outputs.prNumber }}"
|
|
326
|
+
|
|
327
|
+
echo "๐งน Cleaning up temporary branch: \$TEMP_BRANCH"
|
|
328
|
+
|
|
329
|
+
# Close the PR (it's already been fast-forward merged)
|
|
330
|
+
if [ -n "\$PR_NUMBER" ]; then
|
|
331
|
+
gh pr close "\$PR_NUMBER" --comment "Automatically merged via fast-forward. Closing PR and cleaning up release branch." || true
|
|
332
|
+
echo "โ
Closed PR #\$PR_NUMBER"
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
# Delete the temporary branch from remote
|
|
336
|
+
git push origin --delete "\$TEMP_BRANCH" || echo "โ ๏ธ Branch may already be deleted"
|
|
337
|
+
|
|
338
|
+
echo "โ
Deleted temporary branch \$TEMP_BRANCH"
|
|
339
|
+
|
|
340
|
+
- name: Use Existing PR
|
|
341
|
+
if: steps.check-pr.outputs.exists == 'true'
|
|
342
|
+
shell: bash
|
|
343
|
+
run: |
|
|
344
|
+
PR_NUMBER="\${{ steps.check-pr.outputs.prNumber }}"
|
|
345
|
+
PR_URL="\${{ steps.check-pr.outputs.prUrl }}"
|
|
346
|
+
|
|
347
|
+
echo "โน๏ธ Using existing PR #\$PR_NUMBER"
|
|
348
|
+
echo "๐ URL: \$PR_URL"
|
|
349
|
+
|
|
350
|
+
# Note: Fast-forward merge happens in separate step if autoMerge is enabled
|
|
351
|
+
`
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export const generate = (ctx: PinionContext) =>
|
|
355
|
+
Promise.resolve(ctx)
|
|
356
|
+
.then((ctx) => {
|
|
357
|
+
// Check if file exists to determine merge status
|
|
358
|
+
const filePath = '.github/actions/promote-branch/action.yml'
|
|
359
|
+
const exists = fs.existsSync(filePath)
|
|
360
|
+
const status = exists ? '๐ Merged with existing' : '๐ Created new'
|
|
361
|
+
console.log(`${status} ${filePath}`)
|
|
362
|
+
return ctx
|
|
363
|
+
})
|
|
364
|
+
.then(renderTemplate(promoteBranchActionTemplate, toFile('.github/actions/promote-branch/action.yml')))
|