@panoptic-it-solutions/coolify-setup 1.1.39 → 1.1.40
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/dist/generator.js +4 -4
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.js +1 -1
- package/dist/templates/production-workflow.d.ts +1 -0
- package/dist/templates/production-workflow.js +49 -0
- package/dist/templates/workflow.js +169 -21
- package/package.json +1 -1
- package/dist/templates/staging-workflow.d.ts +0 -1
- package/dist/templates/staging-workflow.js +0 -210
package/dist/generator.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, writeFileSync, readFileSync, unlinkSync, readdirSync, rmSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
|
-
import { generateDockerfile, generateDockerCompose, generateDockerComposeBuild, generateWorkflow,
|
|
4
|
+
import { generateDockerfile, generateDockerCompose, generateDockerComposeBuild, generateWorkflow, generateProductionWorkflow, generateEntrypoint, generateMigrateScript, generateClaudeRules, } from './templates/index.js';
|
|
5
5
|
function ensureDir(filePath) {
|
|
6
6
|
const dir = dirname(filePath);
|
|
7
7
|
if (!existsSync(dir)) {
|
|
@@ -219,9 +219,9 @@ export async function generateFiles(options) {
|
|
|
219
219
|
packageManager,
|
|
220
220
|
});
|
|
221
221
|
writeFile('.github/workflows/build-deploy.yml', workflow);
|
|
222
|
-
// Generate
|
|
223
|
-
const
|
|
224
|
-
writeFile('.github/workflows/
|
|
222
|
+
// Generate production deploy workflow
|
|
223
|
+
const productionWorkflow = generateProductionWorkflow();
|
|
224
|
+
writeFile('.github/workflows/production-deploy.yml', productionWorkflow);
|
|
225
225
|
// Generate entrypoint.sh
|
|
226
226
|
const entrypoint = generateEntrypoint({
|
|
227
227
|
projectType,
|
|
@@ -2,7 +2,7 @@ export { generateDockerfile, type DockerfileOptions } from './dockerfile.js';
|
|
|
2
2
|
export { generateDockerCompose, type DockerComposeOptions } from './docker-compose.js';
|
|
3
3
|
export { generateDockerComposeBuild, type DockerComposeBuildOptions } from './docker-compose-build.js';
|
|
4
4
|
export { generateWorkflow, type WorkflowOptions } from './workflow.js';
|
|
5
|
-
export {
|
|
5
|
+
export { generateProductionWorkflow } from './production-workflow.js';
|
|
6
6
|
export { generateEntrypoint, type EntrypointOptions } from './entrypoint.js';
|
|
7
7
|
export { generateMigrateScript, type MigrateScriptOptions } from './migrate.js';
|
|
8
8
|
export { generateClaudeRules } from './claude-rules.js';
|
package/dist/templates/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { generateDockerfile } from './dockerfile.js';
|
|
|
2
2
|
export { generateDockerCompose } from './docker-compose.js';
|
|
3
3
|
export { generateDockerComposeBuild } from './docker-compose-build.js';
|
|
4
4
|
export { generateWorkflow } from './workflow.js';
|
|
5
|
-
export {
|
|
5
|
+
export { generateProductionWorkflow } from './production-workflow.js';
|
|
6
6
|
export { generateEntrypoint } from './entrypoint.js';
|
|
7
7
|
export { generateMigrateScript } from './migrate.js';
|
|
8
8
|
export { generateClaudeRules } from './claude-rules.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateProductionWorkflow(): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function generateProductionWorkflow() {
|
|
2
|
+
return `name: Production Deploy
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
tag-production:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Get version from package.json
|
|
20
|
+
id: version
|
|
21
|
+
run: |
|
|
22
|
+
VERSION=\$(node -p "require('./package.json').version")
|
|
23
|
+
echo "version=\$VERSION" >> \$GITHUB_OUTPUT
|
|
24
|
+
|
|
25
|
+
- name: Create production tag
|
|
26
|
+
run: |
|
|
27
|
+
TAG_NAME="v\${{ steps.version.outputs.version }}"
|
|
28
|
+
|
|
29
|
+
# Check if tag already exists
|
|
30
|
+
if git rev-parse "\$TAG_NAME" >/dev/null 2>&1; then
|
|
31
|
+
echo "Tag \$TAG_NAME already exists, skipping"
|
|
32
|
+
else
|
|
33
|
+
git config user.name "github-actions[bot]"
|
|
34
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
35
|
+
git tag "\$TAG_NAME"
|
|
36
|
+
git push origin "\$TAG_NAME"
|
|
37
|
+
echo "Created production tag \$TAG_NAME"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
- name: Output deployment info
|
|
41
|
+
run: |
|
|
42
|
+
echo "## Production Deployment" >> \$GITHUB_STEP_SUMMARY
|
|
43
|
+
echo "" >> \$GITHUB_STEP_SUMMARY
|
|
44
|
+
echo "**Version:** v\${{ steps.version.outputs.version }}" >> \$GITHUB_STEP_SUMMARY
|
|
45
|
+
echo "**Tag:** v\${{ steps.version.outputs.version }}" >> \$GITHUB_STEP_SUMMARY
|
|
46
|
+
echo "" >> \$GITHUB_STEP_SUMMARY
|
|
47
|
+
echo "Coolify will auto-deploy when it detects this commit on main." >> \$GITHUB_STEP_SUMMARY
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
@@ -76,7 +76,7 @@ env:
|
|
|
76
76
|
PROJECT_NAME: ${projectName}
|
|
77
77
|
|
|
78
78
|
jobs:
|
|
79
|
-
build-and-
|
|
79
|
+
build-and-deploy:
|
|
80
80
|
runs-on: self-hosted
|
|
81
81
|
permissions:
|
|
82
82
|
contents: write
|
|
@@ -85,37 +85,162 @@ jobs:
|
|
|
85
85
|
steps:
|
|
86
86
|
- name: Checkout
|
|
87
87
|
uses: actions/checkout@v4
|
|
88
|
+
with:
|
|
89
|
+
fetch-depth: 0
|
|
88
90
|
${migrationCheck}
|
|
91
|
+
- name: Configure Git (staging only)
|
|
92
|
+
if: github.ref_name == 'staging'
|
|
93
|
+
run: |
|
|
94
|
+
git config user.name "github-actions[bot]"
|
|
95
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
96
|
+
|
|
97
|
+
- name: Get last staging tag
|
|
98
|
+
if: github.ref_name == 'staging'
|
|
99
|
+
id: last_tag
|
|
100
|
+
run: |
|
|
101
|
+
LAST_TAG=\$(git tag -l "staging-v*" --sort=-v:refname | head -n1)
|
|
102
|
+
if [ -z "\$LAST_TAG" ]; then
|
|
103
|
+
LAST_TAG=\$(git rev-list --max-parents=0 HEAD)
|
|
104
|
+
fi
|
|
105
|
+
echo "tag=\$LAST_TAG" >> \$GITHUB_OUTPUT
|
|
106
|
+
|
|
107
|
+
- name: Determine version bump from commits
|
|
108
|
+
if: github.ref_name == 'staging'
|
|
109
|
+
id: bump
|
|
110
|
+
run: |
|
|
111
|
+
COMMITS=\$(git log \${{ steps.last_tag.outputs.tag }}..HEAD --pretty=format:"%s" 2>/dev/null || git log --pretty=format:"%s")
|
|
112
|
+
|
|
113
|
+
BUMP="patch"
|
|
114
|
+
|
|
115
|
+
if echo "\$COMMITS" | grep -qiE "^feat(\\(.+\\))?!:|BREAKING CHANGE:"; then
|
|
116
|
+
BUMP="major"
|
|
117
|
+
elif echo "\$COMMITS" | grep -qiE "^feat(\\(.+\\))?:"; then
|
|
118
|
+
BUMP="minor"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
echo "type=\$BUMP" >> \$GITHUB_OUTPUT
|
|
122
|
+
|
|
123
|
+
- name: Bump version
|
|
124
|
+
if: github.ref_name == 'staging'
|
|
125
|
+
id: version
|
|
126
|
+
run: |
|
|
127
|
+
CURRENT=\$(node -p "require('./package.json').version")
|
|
128
|
+
LAST_TAG="\${{ steps.last_tag.outputs.tag }}"
|
|
129
|
+
|
|
130
|
+
# Check if HEAD is the same as the last tag (rerun scenario with no new commits)
|
|
131
|
+
LAST_TAG_SHA=\$(git rev-parse "\$LAST_TAG" 2>/dev/null || echo "")
|
|
132
|
+
HEAD_SHA=\$(git rev-parse HEAD)
|
|
133
|
+
|
|
134
|
+
if [ "\$LAST_TAG_SHA" = "\$HEAD_SHA" ]; then
|
|
135
|
+
echo "HEAD is at \$LAST_TAG, no new commits to version"
|
|
136
|
+
echo "version=\$CURRENT" >> \$GITHUB_OUTPUT
|
|
137
|
+
echo "skip_bump=true" >> \$GITHUB_OUTPUT
|
|
138
|
+
exit 0
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Check if there are any commits since last tag (excluding version bump commits)
|
|
142
|
+
NEW_COMMITS=\$(git log "\$LAST_TAG"..HEAD --pretty=format:"%s" --invert-grep --grep="^chore(release):" 2>/dev/null | head -1)
|
|
143
|
+
if [ -z "\$NEW_COMMITS" ]; then
|
|
144
|
+
echo "No new commits since \$LAST_TAG (only release commits)"
|
|
145
|
+
echo "version=\$CURRENT" >> \$GITHUB_OUTPUT
|
|
146
|
+
echo "skip_bump=true" >> \$GITHUB_OUTPUT
|
|
147
|
+
exit 0
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
IFS='.' read -r MAJOR MINOR PATCH <<< "\$CURRENT"
|
|
151
|
+
|
|
152
|
+
case "\${{ steps.bump.outputs.type }}" in
|
|
153
|
+
major)
|
|
154
|
+
MAJOR=\$((MAJOR + 1))
|
|
155
|
+
MINOR=0
|
|
156
|
+
PATCH=0
|
|
157
|
+
;;
|
|
158
|
+
minor)
|
|
159
|
+
MINOR=\$((MINOR + 1))
|
|
160
|
+
PATCH=0
|
|
161
|
+
;;
|
|
162
|
+
patch)
|
|
163
|
+
PATCH=\$((PATCH + 1))
|
|
164
|
+
;;
|
|
165
|
+
esac
|
|
166
|
+
|
|
167
|
+
NEW_VERSION="\${MAJOR}.\${MINOR}.\${PATCH}"
|
|
168
|
+
npm version \$NEW_VERSION --no-git-tag-version
|
|
169
|
+
|
|
170
|
+
echo "version=\$NEW_VERSION" >> \$GITHUB_OUTPUT
|
|
171
|
+
echo "skip_bump=false" >> \$GITHUB_OUTPUT
|
|
172
|
+
|
|
173
|
+
- name: Commit version bump
|
|
174
|
+
if: github.ref_name == 'staging' && steps.version.outputs.skip_bump != 'true'
|
|
175
|
+
run: |
|
|
176
|
+
git add package.json
|
|
177
|
+
git commit -m "chore(release): v\${{ steps.version.outputs.version }}"
|
|
178
|
+
|
|
179
|
+
- name: Create and push staging tag
|
|
180
|
+
if: github.ref_name == 'staging' && steps.version.outputs.skip_bump != 'true'
|
|
181
|
+
run: |
|
|
182
|
+
TAG_NAME="staging-v\${{ steps.version.outputs.version }}"
|
|
183
|
+
# Check if tag already exists
|
|
184
|
+
if git rev-parse "\$TAG_NAME" >/dev/null 2>&1; then
|
|
185
|
+
EXISTING_SHA=\$(git rev-parse "\$TAG_NAME")
|
|
186
|
+
CURRENT_SHA=\$(git rev-parse HEAD)
|
|
187
|
+
if [ "\$EXISTING_SHA" = "\$CURRENT_SHA" ]; then
|
|
188
|
+
echo "Tag \$TAG_NAME already exists at current commit, skipping"
|
|
189
|
+
else
|
|
190
|
+
echo "Error: Tag \$TAG_NAME exists at different commit"
|
|
191
|
+
exit 1
|
|
192
|
+
fi
|
|
193
|
+
else
|
|
194
|
+
git tag "\$TAG_NAME"
|
|
195
|
+
fi
|
|
196
|
+
git push origin staging --tags
|
|
197
|
+
|
|
89
198
|
- name: Get commit SHA
|
|
90
199
|
id: sha
|
|
91
|
-
run: echo "sha=\$(git rev-parse --short HEAD)" >>
|
|
200
|
+
run: echo "sha=\$(git rev-parse --short HEAD)" >> \$GITHUB_OUTPUT
|
|
92
201
|
|
|
93
|
-
- name: Build
|
|
202
|
+
- name: Build Docker image
|
|
94
203
|
run: |
|
|
95
204
|
export COMMIT_SHA=\${{ steps.sha.outputs.sha }}
|
|
96
205
|
export COMPOSE_PROJECT_NAME=\${{ env.PROJECT_NAME }}
|
|
97
|
-
|
|
98
206
|
docker compose -f docker-compose.build.yml build --no-cache
|
|
207
|
+
|
|
208
|
+
- name: Push to registry (staging only)
|
|
209
|
+
if: github.ref_name == 'staging'
|
|
210
|
+
run: |
|
|
211
|
+
export COMMIT_SHA=\${{ steps.sha.outputs.sha }}
|
|
212
|
+
export COMPOSE_PROJECT_NAME=\${{ env.PROJECT_NAME }}
|
|
99
213
|
docker compose -f docker-compose.build.yml push
|
|
100
214
|
|
|
101
215
|
# Also tag and push as latest
|
|
102
216
|
docker tag \${{ env.REGISTRY }}/\${{ env.PROJECT_NAME }}-app:\${{ steps.sha.outputs.sha }} \${{ env.REGISTRY }}/\${{ env.PROJECT_NAME }}-app:latest
|
|
103
217
|
docker push \${{ env.REGISTRY }}/\${{ env.PROJECT_NAME }}-app:latest
|
|
104
218
|
|
|
219
|
+
- name: Output version info (staging only)
|
|
220
|
+
if: github.ref_name == 'staging'
|
|
221
|
+
run: |
|
|
222
|
+
echo "## Version Summary" >> \$GITHUB_STEP_SUMMARY
|
|
223
|
+
echo "" >> \$GITHUB_STEP_SUMMARY
|
|
224
|
+
echo "**Version:** v\${{ steps.version.outputs.version }}" >> \$GITHUB_STEP_SUMMARY
|
|
225
|
+
echo "**Bump Type:** \${{ steps.bump.outputs.type }}" >> \$GITHUB_STEP_SUMMARY
|
|
226
|
+
echo "**Skipped:** \${{ steps.version.outputs.skip_bump }}" >> \$GITHUB_STEP_SUMMARY
|
|
227
|
+
|
|
105
228
|
- name: Determine target branch
|
|
106
229
|
id: target
|
|
107
230
|
run: |
|
|
108
231
|
SOURCE_BRANCH="\${{ github.ref_name }}"
|
|
109
232
|
|
|
110
233
|
# Feature/fix/hotfix branches target develop
|
|
111
|
-
if [[ "
|
|
112
|
-
echo "branch=develop" >>
|
|
234
|
+
if [[ "\$SOURCE_BRANCH" == feature/* ]] || [[ "\$SOURCE_BRANCH" == fix/* ]] || [[ "\$SOURCE_BRANCH" == hotfix/* ]]; then
|
|
235
|
+
echo "branch=develop" >> \$GITHUB_OUTPUT
|
|
113
236
|
# Develop targets staging
|
|
114
|
-
elif [[ "
|
|
115
|
-
echo "branch=staging" >>
|
|
116
|
-
# Staging
|
|
237
|
+
elif [[ "\$SOURCE_BRANCH" == "develop" ]]; then
|
|
238
|
+
echo "branch=staging" >> \$GITHUB_OUTPUT
|
|
239
|
+
# Staging targets main
|
|
240
|
+
elif [[ "\$SOURCE_BRANCH" == "staging" ]]; then
|
|
241
|
+
echo "branch=main" >> \$GITHUB_OUTPUT
|
|
117
242
|
else
|
|
118
|
-
echo "branch=" >>
|
|
243
|
+
echo "branch=" >> \$GITHUB_OUTPUT
|
|
119
244
|
fi
|
|
120
245
|
|
|
121
246
|
- name: Create deploy PR
|
|
@@ -145,7 +270,7 @@ ${migrationCheck}
|
|
|
145
270
|
owner: context.repo.owner,
|
|
146
271
|
repo: context.repo.repo,
|
|
147
272
|
title: \`Deploy: \${sourceBranch} -> \${targetBranch}\`,
|
|
148
|
-
body: \`Automated deployment PR from \${sourceBranch} to \${targetBranch}.\\n\\n**Commit:** \${{ steps.sha.outputs.sha }}\\n**Image:** \${{ env.REGISTRY }}
|
|
273
|
+
body: \`Automated deployment PR from \${sourceBranch} to \${targetBranch}.\\n\\n**Commit:** \${{ steps.sha.outputs.sha }}\\n**Image:** \${{ env.REGISTRY }}/${projectName}-app:\${{ steps.sha.outputs.sha }}\\n\\nMerge this PR to trigger deployment.\`,
|
|
149
274
|
head: sourceBranch,
|
|
150
275
|
base: targetBranch
|
|
151
276
|
});
|
|
@@ -154,22 +279,22 @@ ${migrationCheck}
|
|
|
154
279
|
console.log(\`PR creation skipped: \${error.message}\`);
|
|
155
280
|
}
|
|
156
281
|
|
|
157
|
-
- name: Create
|
|
158
|
-
if: github.
|
|
282
|
+
- name: Create sync PR to develop (staging only)
|
|
283
|
+
if: github.ref_name == 'staging' && steps.version.outputs.skip_bump != 'true'
|
|
159
284
|
uses: actions/github-script@v7
|
|
160
285
|
with:
|
|
161
286
|
script: |
|
|
162
|
-
// Check if PR already exists
|
|
287
|
+
// Check if sync PR already exists
|
|
163
288
|
const { data: prs } = await github.rest.pulls.list({
|
|
164
289
|
owner: context.repo.owner,
|
|
165
290
|
repo: context.repo.repo,
|
|
166
291
|
head: \`\${context.repo.owner}:staging\`,
|
|
167
|
-
base: '
|
|
292
|
+
base: 'develop',
|
|
168
293
|
state: 'open'
|
|
169
294
|
});
|
|
170
295
|
|
|
171
296
|
if (prs.length > 0) {
|
|
172
|
-
console.log(\`PR #\${prs[0].number} already exists for staging ->
|
|
297
|
+
console.log(\`Sync PR #\${prs[0].number} already exists for staging -> develop\`);
|
|
173
298
|
return;
|
|
174
299
|
}
|
|
175
300
|
|
|
@@ -177,14 +302,37 @@ ${migrationCheck}
|
|
|
177
302
|
const { data: pr } = await github.rest.pulls.create({
|
|
178
303
|
owner: context.repo.owner,
|
|
179
304
|
repo: context.repo.repo,
|
|
180
|
-
title:
|
|
181
|
-
body: \`
|
|
305
|
+
title: \`Sync: version bump v\${{ steps.version.outputs.version }} → develop\`,
|
|
306
|
+
body: \`Syncs the version bump commit back to develop to prevent package.json conflicts in future merges.\\n\\n**Version:** v\${{ steps.version.outputs.version }}\\n\\nMerge this PR to keep branches in sync.\`,
|
|
182
307
|
head: 'staging',
|
|
183
|
-
base: '
|
|
308
|
+
base: 'develop'
|
|
184
309
|
});
|
|
185
|
-
console.log(\`Created PR #\${pr.number}\`);
|
|
310
|
+
console.log(\`Created sync PR #\${pr.number}\`);
|
|
311
|
+
|
|
312
|
+
// Enable auto-merge for sync PR (just version bump)
|
|
313
|
+
try {
|
|
314
|
+
await github.graphql(\`
|
|
315
|
+
mutation(\$pullRequestId: ID!) {
|
|
316
|
+
enablePullRequestAutoMerge(input: {
|
|
317
|
+
pullRequestId: \$pullRequestId,
|
|
318
|
+
mergeMethod: MERGE
|
|
319
|
+
}) {
|
|
320
|
+
pullRequest {
|
|
321
|
+
autoMergeRequest {
|
|
322
|
+
enabledAt
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
\`, {
|
|
328
|
+
pullRequestId: pr.node_id
|
|
329
|
+
});
|
|
330
|
+
console.log(\`Enabled auto-merge for sync PR #\${pr.number}\`);
|
|
331
|
+
} catch (autoMergeError) {
|
|
332
|
+
console.log(\`Auto-merge not available: \${autoMergeError.message}\`);
|
|
333
|
+
}
|
|
186
334
|
} catch (error) {
|
|
187
|
-
console.log(\`PR creation skipped: \${error.message}\`);
|
|
335
|
+
console.log(\`Sync PR creation skipped: \${error.message}\`);
|
|
188
336
|
}
|
|
189
337
|
`;
|
|
190
338
|
}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function generateStagingWorkflow(): string;
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
export function generateStagingWorkflow() {
|
|
2
|
-
return `name: Staging Version
|
|
3
|
-
|
|
4
|
-
on:
|
|
5
|
-
push:
|
|
6
|
-
branches:
|
|
7
|
-
- staging
|
|
8
|
-
|
|
9
|
-
permissions:
|
|
10
|
-
contents: write
|
|
11
|
-
pull-requests: write
|
|
12
|
-
|
|
13
|
-
jobs:
|
|
14
|
-
version:
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
steps:
|
|
17
|
-
- name: Checkout
|
|
18
|
-
uses: actions/checkout@v4
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 0
|
|
21
|
-
token: \${{ secrets.GITHUB_TOKEN }}
|
|
22
|
-
|
|
23
|
-
- name: Setup Node.js
|
|
24
|
-
uses: actions/setup-node@v4
|
|
25
|
-
with:
|
|
26
|
-
node-version: '22'
|
|
27
|
-
|
|
28
|
-
- name: Configure Git
|
|
29
|
-
run: |
|
|
30
|
-
git config user.name "github-actions[bot]"
|
|
31
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
32
|
-
|
|
33
|
-
- name: Get last staging tag
|
|
34
|
-
id: last_tag
|
|
35
|
-
run: |
|
|
36
|
-
LAST_TAG=\$(git tag -l "staging-v*" --sort=-v:refname | head -n1)
|
|
37
|
-
if [ -z "\$LAST_TAG" ]; then
|
|
38
|
-
LAST_TAG=\$(git rev-list --max-parents=0 HEAD)
|
|
39
|
-
fi
|
|
40
|
-
echo "tag=\$LAST_TAG" >> \$GITHUB_OUTPUT
|
|
41
|
-
|
|
42
|
-
- name: Determine version bump from commits
|
|
43
|
-
id: bump
|
|
44
|
-
run: |
|
|
45
|
-
COMMITS=\$(git log \${{ steps.last_tag.outputs.tag }}..HEAD --pretty=format:"%s" 2>/dev/null || git log --pretty=format:"%s")
|
|
46
|
-
|
|
47
|
-
BUMP="patch"
|
|
48
|
-
|
|
49
|
-
if echo "\$COMMITS" | grep -qiE "^feat(\\(.+\\))?!:|BREAKING CHANGE:"; then
|
|
50
|
-
BUMP="major"
|
|
51
|
-
elif echo "\$COMMITS" | grep -qiE "^feat(\\(.+\\))?:"; then
|
|
52
|
-
BUMP="minor"
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
echo "type=\$BUMP" >> \$GITHUB_OUTPUT
|
|
56
|
-
|
|
57
|
-
- name: Bump version
|
|
58
|
-
id: version
|
|
59
|
-
run: |
|
|
60
|
-
CURRENT=\$(node -p "require('./package.json').version")
|
|
61
|
-
LAST_TAG="\${{ steps.last_tag.outputs.tag }}"
|
|
62
|
-
|
|
63
|
-
# Check if HEAD is the same as the last tag (rerun scenario with no new commits)
|
|
64
|
-
LAST_TAG_SHA=\$(git rev-parse "\$LAST_TAG" 2>/dev/null || echo "")
|
|
65
|
-
HEAD_SHA=\$(git rev-parse HEAD)
|
|
66
|
-
|
|
67
|
-
if [ "\$LAST_TAG_SHA" = "\$HEAD_SHA" ]; then
|
|
68
|
-
echo "HEAD is at \$LAST_TAG, no new commits to version"
|
|
69
|
-
echo "version=\$CURRENT" >> \$GITHUB_OUTPUT
|
|
70
|
-
echo "skip_commit=true" >> \$GITHUB_OUTPUT
|
|
71
|
-
exit 0
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
# Check if there are any commits since last tag (excluding version bump commits)
|
|
75
|
-
NEW_COMMITS=\$(git log "\$LAST_TAG"..HEAD --pretty=format:"%s" --invert-grep --grep="^chore(release):" 2>/dev/null | head -1)
|
|
76
|
-
if [ -z "\$NEW_COMMITS" ]; then
|
|
77
|
-
echo "No new commits since \$LAST_TAG (only release commits)"
|
|
78
|
-
echo "version=\$CURRENT" >> \$GITHUB_OUTPUT
|
|
79
|
-
echo "skip_commit=true" >> \$GITHUB_OUTPUT
|
|
80
|
-
exit 0
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
IFS='.' read -r MAJOR MINOR PATCH <<< "\$CURRENT"
|
|
84
|
-
|
|
85
|
-
case "\${{ steps.bump.outputs.type }}" in
|
|
86
|
-
major)
|
|
87
|
-
MAJOR=\$((MAJOR + 1))
|
|
88
|
-
MINOR=0
|
|
89
|
-
PATCH=0
|
|
90
|
-
;;
|
|
91
|
-
minor)
|
|
92
|
-
MINOR=\$((MINOR + 1))
|
|
93
|
-
PATCH=0
|
|
94
|
-
;;
|
|
95
|
-
patch)
|
|
96
|
-
PATCH=\$((PATCH + 1))
|
|
97
|
-
;;
|
|
98
|
-
esac
|
|
99
|
-
|
|
100
|
-
NEW_VERSION="\${MAJOR}.\${MINOR}.\${PATCH}"
|
|
101
|
-
npm version \$NEW_VERSION --no-git-tag-version
|
|
102
|
-
|
|
103
|
-
echo "version=\$NEW_VERSION" >> \$GITHUB_OUTPUT
|
|
104
|
-
echo "skip_commit=false" >> \$GITHUB_OUTPUT
|
|
105
|
-
|
|
106
|
-
- name: Generate changelog
|
|
107
|
-
id: changelog
|
|
108
|
-
if: steps.version.outputs.skip_commit != 'true'
|
|
109
|
-
run: |
|
|
110
|
-
LAST_TAG="\${{ steps.last_tag.outputs.tag }}"
|
|
111
|
-
|
|
112
|
-
{
|
|
113
|
-
echo "changelog<<EOF"
|
|
114
|
-
echo "## Changes in v\${{ steps.version.outputs.version }}"
|
|
115
|
-
echo ""
|
|
116
|
-
|
|
117
|
-
# Features
|
|
118
|
-
FEATURES=\$(git log \$LAST_TAG..HEAD --pretty=format:"- %s" --grep="^feat" 2>/dev/null || true)
|
|
119
|
-
if [ -n "\$FEATURES" ]; then
|
|
120
|
-
echo "### Features"
|
|
121
|
-
echo "\$FEATURES"
|
|
122
|
-
echo ""
|
|
123
|
-
fi
|
|
124
|
-
|
|
125
|
-
# Fixes
|
|
126
|
-
FIXES=\$(git log \$LAST_TAG..HEAD --pretty=format:"- %s" --grep="^fix" 2>/dev/null || true)
|
|
127
|
-
if [ -n "\$FIXES" ]; then
|
|
128
|
-
echo "### Bug Fixes"
|
|
129
|
-
echo "\$FIXES"
|
|
130
|
-
echo ""
|
|
131
|
-
fi
|
|
132
|
-
|
|
133
|
-
# Other changes
|
|
134
|
-
OTHERS=\$(git log \$LAST_TAG..HEAD --pretty=format:"- %s" --invert-grep --grep="^feat" --grep="^fix" 2>/dev/null | head -20 || true)
|
|
135
|
-
if [ -n "\$OTHERS" ]; then
|
|
136
|
-
echo "### Other Changes"
|
|
137
|
-
echo "\$OTHERS"
|
|
138
|
-
echo ""
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
echo "EOF"
|
|
142
|
-
} >> \$GITHUB_OUTPUT
|
|
143
|
-
|
|
144
|
-
- name: Commit version bump
|
|
145
|
-
if: steps.version.outputs.skip_commit != 'true'
|
|
146
|
-
run: |
|
|
147
|
-
git add package.json
|
|
148
|
-
git commit -m "chore(release): v\${{ steps.version.outputs.version }}"
|
|
149
|
-
|
|
150
|
-
- name: Create and push tag
|
|
151
|
-
if: steps.version.outputs.skip_commit != 'true'
|
|
152
|
-
run: |
|
|
153
|
-
TAG_NAME="staging-v\${{ steps.version.outputs.version }}"
|
|
154
|
-
# Check if tag already exists
|
|
155
|
-
if git rev-parse "\$TAG_NAME" >/dev/null 2>&1; then
|
|
156
|
-
EXISTING_SHA=\$(git rev-parse "\$TAG_NAME")
|
|
157
|
-
CURRENT_SHA=\$(git rev-parse HEAD)
|
|
158
|
-
if [ "\$EXISTING_SHA" = "\$CURRENT_SHA" ]; then
|
|
159
|
-
echo "Tag \$TAG_NAME already exists at current commit, skipping"
|
|
160
|
-
else
|
|
161
|
-
echo "Error: Tag \$TAG_NAME exists at different commit"
|
|
162
|
-
exit 1
|
|
163
|
-
fi
|
|
164
|
-
else
|
|
165
|
-
git tag "\$TAG_NAME"
|
|
166
|
-
fi
|
|
167
|
-
git push origin staging --tags
|
|
168
|
-
|
|
169
|
-
- name: Output version info
|
|
170
|
-
run: |
|
|
171
|
-
echo "## Version Summary" >> \$GITHUB_STEP_SUMMARY
|
|
172
|
-
echo "" >> \$GITHUB_STEP_SUMMARY
|
|
173
|
-
echo "**Version:** v\${{ steps.version.outputs.version }}" >> \$GITHUB_STEP_SUMMARY
|
|
174
|
-
echo "**Bump Type:** \${{ steps.bump.outputs.type }}" >> \$GITHUB_STEP_SUMMARY
|
|
175
|
-
echo "**Skipped:** \${{ steps.version.outputs.skip_commit }}" >> \$GITHUB_STEP_SUMMARY
|
|
176
|
-
|
|
177
|
-
- name: Create sync PR to develop
|
|
178
|
-
if: steps.version.outputs.skip_commit != 'true'
|
|
179
|
-
uses: actions/github-script@v7
|
|
180
|
-
with:
|
|
181
|
-
script: |
|
|
182
|
-
// Check if sync PR already exists
|
|
183
|
-
const { data: prs } = await github.rest.pulls.list({
|
|
184
|
-
owner: context.repo.owner,
|
|
185
|
-
repo: context.repo.repo,
|
|
186
|
-
head: \`\${context.repo.owner}:staging\`,
|
|
187
|
-
base: 'develop',
|
|
188
|
-
state: 'open'
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
if (prs.length > 0) {
|
|
192
|
-
console.log(\`Sync PR #\${prs[0].number} already exists for staging -> develop\`);
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
const { data: pr } = await github.rest.pulls.create({
|
|
198
|
-
owner: context.repo.owner,
|
|
199
|
-
repo: context.repo.repo,
|
|
200
|
-
title: \`Sync: version bump v\${{ steps.version.outputs.version }} → develop\`,
|
|
201
|
-
body: \`Syncs the version bump commit back to develop to prevent package.json conflicts in future merges.\\n\\n**Version:** v\${{ steps.version.outputs.version }}\\n\\nMerge this PR to keep branches in sync.\`,
|
|
202
|
-
head: 'staging',
|
|
203
|
-
base: 'develop'
|
|
204
|
-
});
|
|
205
|
-
console.log(\`Created sync PR #\${pr.number}\`);
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.log(\`Sync PR creation skipped: \${error.message}\`);
|
|
208
|
-
}
|
|
209
|
-
`;
|
|
210
|
-
}
|