-
Notifications
You must be signed in to change notification settings - Fork 1
673 lines (582 loc) · 29.8 KB
/
Copy pathcreate-release.yml
File metadata and controls
673 lines (582 loc) · 29.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
name: Create Release
on:
workflow_dispatch:
inputs:
bump:
type: choice
description: 'Semver bump type'
options: [patch, minor, major]
default: patch
custom_version:
description: 'Custom version (optional, overrides bump)'
required: false
type: string
release_type:
type: choice
description: 'Release type'
options: [latest, prerelease]
default: latest
permissions:
contents: write # commit version bump + tag
jobs:
build-package:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Install Salesforce CLI
run: |
npm install -g @salesforce/cli
echo "$(npm config get prefix)/bin" >> $GITHUB_PATH
sf --version
- name: Auth via JWT (packaging org)
env:
SFDX_CLIENT_ID: ${{ secrets.SF_CLIENT_ID }}
SFDX_JWT_KEY: ${{ secrets.SF_JWT_KEY }}
SF_USERNAME: ${{ secrets.SF_PACKAGING_USERNAME }}
run: |
echo "$SFDX_JWT_KEY" > server.key
sf org login jwt \
--client-id "$SFDX_CLIENT_ID" \
--jwt-key-file server.key \
--username "$SF_USERNAME" \
--alias pkgorg --set-default
rm -f server.key
- name: Read and calculate version
id: version
run: |
# Read current version from package.json
CUR=$(node -p "require('./package.json').version")
MAJOR=$(echo "$CUR" | cut -d. -f1)
MINOR=$(echo "$CUR" | cut -d. -f2)
PATCH=$(echo "$CUR" | cut -d. -f3)
if [ -n "${{ github.event.inputs.custom_version }}" ]; then
NEW="${{ github.event.inputs.custom_version }}"
echo "Using custom version: $NEW"
else
case "${{ github.event.inputs.bump }}" in
major) MAJOR=$((MAJOR+1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR+1)); PATCH=0 ;;
patch) PATCH=$((PATCH+1)) ;;
esac
NEW="$MAJOR.$MINOR.$PATCH"
fi
# Debug: Show all input values
echo "🔍 DEBUG: Input values:"
echo " bump: '${{ github.event.inputs.bump }}'"
echo " custom_version: '${{ github.event.inputs.custom_version }}'"
echo " release_type: '${{ github.event.inputs.release_type }}'"
echo " Calculated NEW before beta check: '$NEW'"
# Add prerelease suffix if release type is prerelease
if [ "${{ github.event.inputs.release_type }}" == "prerelease" ]; then
NEW="${NEW}-beta"
echo " Added prerelease suffix: '$NEW'"
else
echo " No prerelease suffix added (release_type is not 'prerelease')"
fi
echo "current=$CUR" >> $GITHUB_OUTPUT
echo "new=$NEW" >> $GITHUB_OUTPUT
echo "tag=v$NEW" >> $GITHUB_OUTPUT
echo "release_type=${{ github.event.inputs.release_type }}" >> $GITHUB_OUTPUT
echo "Current version: $CUR"
echo "New version: $NEW"
echo "Release type: ${{ github.event.inputs.release_type }}"
- name: Update package.json version
run: |
NEW_VERSION="${{ steps.version.outputs.new }}"
npm version $NEW_VERSION --no-git-tag-version
echo "Updated package.json to version $NEW_VERSION"
- name: Update package.xml version
run: |
NEW_VERSION="${{ steps.version.outputs.new }}"
API_VERSION=$(echo $NEW_VERSION | cut -d. -f1)
sed -i "s/<version>.*<\/version>/<version>$API_VERSION.0<\/version>/" manifest/package.xml
echo "Updated package.xml API version to $API_VERSION.0"
- name: Update sfdx-project.json version
run: |
NEW_VERSION="${{ steps.version.outputs.new }}"
# Extract numeric version (remove prerelease suffix if present) for versionNumber
NUMERIC_VERSION=$(echo "$NEW_VERSION" | sed 's/-.*$//')
# Update versionName in sfdx-project.json
sed -i "s/\"versionName\": \"ver [^\"]*\"/\"versionName\": \"ver $NEW_VERSION\"/" sfdx-project.json
# Update versionNumber in sfdx-project.json (format: MAJOR.MINOR.PATCH.NEXT)
sed -i "s/\"versionNumber\": \"[^\"]*\"/\"versionNumber\": \"$NUMERIC_VERSION.NEXT\"/" sfdx-project.json
echo "Updated sfdx-project.json version to $NEW_VERSION (numeric: $NUMERIC_VERSION)"
- name: Create package
run: |
# Create package directory
mkdir -p package
# Copy source files
cp -r force-app package/
cp manifest/package.xml package/
cp README.md package/
cp docs/PACKAGE-README.md package/ 2>/dev/null || true
# Create package zip
cd package
zip -r ../REST-API-Library-v${{ steps.version.outputs.new }}.zip .
cd ..
echo "Created REST-API-Library-v${{ steps.version.outputs.new }}.zip"
# Clean up package directory
rm -rf package
echo "Cleaned up temporary package directory"
- name: Convert to MDAPI
run: |
sf project convert source --root-dir force-app --output-dir mdapi_out
- name: Deploy to packaging org
run: |
echo "Deploying converted metadata to packaging org..."
echo "Source directory: mdapi_out"
echo "Target org: pkgorg"
set +e # Don't exit on error, we'll handle it manually
DEPLOY_OUTPUT=$(sf project deploy start --metadata-dir mdapi_out --target-org pkgorg --wait 60 --ignore-conflicts 2>&1)
DEPLOY_EXIT_CODE=$?
set -e # Re-enable exit on error
echo "Deploy exit code: $DEPLOY_EXIT_CODE"
echo "Deploy output:"
echo "$DEPLOY_OUTPUT"
if [ $DEPLOY_EXIT_CODE -eq 0 ]; then
echo "✅ Successfully deployed to packaging org"
else
echo "❌ ERROR: Deployment failed with exit code $DEPLOY_EXIT_CODE"
echo "💡 Check the output above for specific error details"
exit 1
fi
- name: Run tests and check code coverage
run: |
echo "Running tests for package-specific test classes: NebulaAdapter_Test, RestLibTests"
# Run only the test classes that are part of this package
set +e # Don't exit on error, we'll handle it manually
# Capture both stdout and stderr, but ignore warnings in stderr
sf apex test run --class-names NebulaAdapter_Test --class-names RestLibTests --target-org pkgorg --result-format json --code-coverage --wait 10 > test_result.json 2>test_errors.log
TEST_EXIT_CODE=$?
set -e # Re-enable exit on error
# Check if there were any real errors (not just warnings)
if [ -s test_errors.log ]; then
echo "🔍 Debug: Checking for errors vs warnings..."
cat test_errors.log
# If the only content is warnings about array format, we can ignore it
if grep -q "array arguments has changed" test_errors.log && ! grep -v "array arguments has changed\|Warning:" test_errors.log; then
echo "⚠️ WARNING: Only array format warnings detected, ignoring..."
TEST_EXIT_CODE=0 # Treat as success if only warnings
fi
fi
echo "Test execution exit code: $TEST_EXIT_CODE"
echo "Test execution output:"
# Read from file to avoid broken pipe issues
cat test_result.json
# Check if test execution was successful
# Note: sf apex test run may return non-zero exit code for warnings, but tests might still pass
# We'll check the actual test results in the JSON output instead of relying solely on exit code
if [ $TEST_EXIT_CODE -ne 0 ]; then
echo "⚠️ WARNING: Test execution returned exit code $TEST_EXIT_CODE"
echo "This might be due to CLI warnings. Checking actual test results..."
fi
# Check if we have valid JSON output
echo "🔍 Debug: Checking JSON validity..."
if ! jq -e '.result' test_result.json > /dev/null 2>&1; then
echo "❌ ERROR: Invalid test result format"
echo "Raw output:"
cat test_result.json
echo "🔍 Debug: jq command failed. Checking if jq is available..."
which jq || echo "jq not found in PATH"
jq --version || echo "jq version check failed"
exit 1
else
echo "✅ JSON format is valid"
fi
# Extract test summary
if jq -e '.result.summary' test_result.json > /dev/null 2>&1; then
SUMMARY=$(jq -r '.result.summary' test_result.json)
echo "Test Summary: $SUMMARY"
# Show detailed test counts
PASSING=$(jq -r '.result.summary.passing // 0' test_result.json)
FAILING=$(jq -r '.result.summary.failing // 0' test_result.json)
SKIPPED=$(jq -r '.result.summary.skipped // 0' test_result.json)
TESTS_RAN=$(jq -r '.result.summary.testsRan // 0' test_result.json)
echo "📈 Test Results: $PASSING passed, $FAILING failed, $SKIPPED skipped (Total: $TESTS_RAN)"
fi
# Extract coverage percentage - try multiple possible locations in the JSON
COVERAGE=""
if jq -e '.result.summary.testRunCoverage' test_result.json > /dev/null 2>&1; then
COVERAGE=$(jq -r '.result.summary.testRunCoverage' test_result.json | sed 's/%//')
echo "Code coverage (test run): $COVERAGE%"
elif jq -e '.result.coverage.coverage' test_result.json > /dev/null 2>&1; then
COVERAGE=$(jq -r '.result.coverage.coverage[].percent' test_result.json)
echo "Code coverage (per class): $COVERAGE%"
else
echo "⚠️ WARNING: Could not extract coverage information from test results"
fi
# Check if coverage meets minimum requirement (75%)
if [ -n "$COVERAGE" ]; then
MIN_COVERAGE=75
if (( $(echo "$COVERAGE < $MIN_COVERAGE" | bc -l) )); then
echo ""
echo "❌ COVERAGE FAILURE: Code coverage $COVERAGE% is below minimum requirement of $MIN_COVERAGE%"
echo ""
echo "📊 COVERAGE ANALYSIS:"
echo " Current Coverage: $COVERAGE%"
echo " Required Coverage: $MIN_COVERAGE%"
echo " Coverage Gap: $((MIN_COVERAGE - COVERAGE))%"
echo ""
echo "🔍 TEST CLASSES BEING VALIDATED:"
echo " - NebulaAdapter_Test"
echo " - RestLibTests"
echo ""
echo "💡 TO FIX THIS ISSUE:"
echo " 1. Add more test methods to cover uncovered code paths"
echo " 2. Improve existing test methods to cover more scenarios"
echo " 3. Review uncovered lines in the test results above"
echo " 4. Ensure all public methods and critical code paths are tested"
echo ""
echo "📋 NEXT STEPS:"
echo " - Check the detailed coverage information in the test output above"
echo " - Look for 'uncoveredLines' in the JSON output to see which lines need testing"
echo " - Add test methods for any missing scenarios"
echo " - Re-run the workflow after improving test coverage"
echo ""
exit 1
else
echo "✅ SUCCESS: Code coverage $COVERAGE% meets minimum requirement of $MIN_COVERAGE%"
fi
fi
# Check for test failures - this is the real test validation
if jq -e '.result.failures' test_result.json > /dev/null 2>&1; then
FAILURES=$(jq -r '.result.failures' test_result.json)
if [ "$FAILURES" != "0" ] && [ "$FAILURES" != "null" ]; then
echo "❌ ERROR: $FAILURES test(s) failed"
echo "Test failures details:"
jq -r '.result.tests[] | select(.Outcome == "Fail") | " - \(.MethodName): \(.Message)"' test_result.json 2>/dev/null || echo "Could not extract failure details"
exit 1
fi
fi
# Additional validation: Check if any tests actually ran and passed
if jq -e '.result.summary' test_result.json > /dev/null 2>&1; then
TESTS_RAN=$(jq -r '.result.summary.testsRan // 0' test_result.json)
PASSING=$(jq -r '.result.summary.passing // 0' test_result.json)
FAILING=$(jq -r '.result.summary.failing // 0' test_result.json)
if [ "$TESTS_RAN" = "0" ]; then
echo "❌ ERROR: No tests were executed"
exit 1
fi
if [ "$FAILING" != "0" ] && [ "$FAILING" != "null" ]; then
echo "❌ ERROR: $FAILING test(s) failed out of $TESTS_RAN total tests"
exit 1
fi
echo "✅ SUCCESS: All $PASSING tests passed (0 failures)"
else
echo "❌ ERROR: Could not extract test summary from results"
exit 1
fi
# Clean up temporary files
rm -f test_result.json test_errors.log
- name: Create package and version
id: package_version
env:
SF_PACKAGE1_ID: ${{ vars.SF_PACKAGE1_ID }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Check if package ID exists, if not create a new package
if [ -z "$SF_PACKAGE1_ID" ] || [ "$SF_PACKAGE1_ID" = "NULL" ] || [ "$SF_PACKAGE1_ID" = "null" ] || [ "$SF_PACKAGE1_ID" = "" ]; then
echo "No package ID found, creating new package..."
# Debug: Check authentication and org status
echo "Checking authentication..."
sf org list || echo "No orgs found"
# Debug: Check if we're in the right org
echo "Current org info:"
sf org display || echo "No org display available"
# Debug: Try a simple command first
echo "Testing basic sf command..."
sf --version || echo "SF CLI not working"
# Create a new package with more debugging
echo "Creating package with command:"
echo "sf package create --name 'REST API Library' --description 'A comprehensive Salesforce Apex library for making REST API callouts' --package-type Unlocked --path force-app --target-dev-hub pkgorg --json"
PACKAGE_OUTPUT=$(sf package create \
--name "REST API Library" \
--description "A comprehensive Salesforce Apex library for making REST API callouts" \
--package-type Unlocked \
--path force-app \
--target-dev-hub pkgorg \
--json 2>&1)
echo "Package create exit code: $?"
echo "Package create output:"
echo "$PACKAGE_OUTPUT"
# Extract package ID
PACKAGE_ID=$(echo "$PACKAGE_OUTPUT" | jq -r '.result.Id')
if [ "$PACKAGE_ID" != "null" ] && [ -n "$PACKAGE_ID" ]; then
echo "✅ Created new package with ID: $PACKAGE_ID"
# Update GitHub repository variable automatically
echo "Updating GitHub repository variable..."
curl -X PATCH \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${{ github.repository }}/actions/variables/SF_PACKAGE1_ID" \
-d "{\"name\":\"SF_PACKAGE1_ID\",\"value\":\"$PACKAGE_ID\"}" && echo "✅ GitHub variable updated successfully" || echo "⚠️ Failed to update GitHub variable (you can update manually)"
# Set the package ID for this run
SF_PACKAGE1_ID="$PACKAGE_ID"
else
echo "ERROR: Failed to create package"
echo "Full output: $PACKAGE_OUTPUT"
exit 1
fi
else
echo "Using existing package ID: $SF_PACKAGE1_ID"
fi
# Create a new package version
echo "Creating package version for package: $SF_PACKAGE1_ID"
echo "Command: sf package version create --package '$SF_PACKAGE1_ID' --installation-key-bypass --code-coverage --wait 10 --target-dev-hub pkgorg --json"
# Run the command and capture both output and exit code
set +e # Don't exit on error, we'll handle it manually
PACKAGE_VERSION_OUTPUT=$(sf package version create \
--package "$SF_PACKAGE1_ID" \
--installation-key-bypass \
--code-coverage \
--wait 10 \
--target-dev-hub pkgorg \
--json 2>&1)
PACKAGE_VERSION_EXIT_CODE=$?
set -e # Re-enable exit on error
echo "Package version create exit code: $PACKAGE_VERSION_EXIT_CODE"
echo "Package version create output:"
echo "$PACKAGE_VERSION_OUTPUT"
# Check if the command was successful
if [ $PACKAGE_VERSION_EXIT_CODE -eq 0 ] && echo "$PACKAGE_VERSION_OUTPUT" | jq -e '.result.SubscriberPackageVersionId' > /dev/null 2>&1; then
# Extract the package version ID and create installation URLs
PACKAGE_VERSION_ID=$(echo "$PACKAGE_VERSION_OUTPUT" | jq -r '.result.SubscriberPackageVersionId')
PRODUCTION_URL="https://login.salesforce.com/packaging/installPackage.apexp?p0=$PACKAGE_VERSION_ID"
SANDBOX_URL="https://test.salesforce.com/packaging/installPackage.apexp?p0=$PACKAGE_VERSION_ID"
echo "package_version_id=$PACKAGE_VERSION_ID" >> $GITHUB_OUTPUT
echo "production_url=$PRODUCTION_URL" >> $GITHUB_OUTPUT
echo "sandbox_url=$SANDBOX_URL" >> $GITHUB_OUTPUT
echo "package_id=$SF_PACKAGE1_ID" >> $GITHUB_OUTPUT
echo "✅ Created package version: $PACKAGE_VERSION_ID"
echo "Production URL: $PRODUCTION_URL"
echo "Sandbox URL: $SANDBOX_URL"
# Promote package version to released status if it's a latest release
if [ "${{ steps.version.outputs.release_type }}" == "latest" ]; then
echo "🚀 Promoting package version to released status..."
echo "🔍 Debug: Package version ID: $PACKAGE_VERSION_ID"
echo "🔍 Debug: Target dev hub: pkgorg"
# Check if package version is ready for promotion
echo "🔍 Checking package version status..."
VERSION_STATUS=$(echo "$PACKAGE_VERSION_OUTPUT" | jq -r '.result.Status // "Unknown"')
CODE_COVERAGE_PASSED=$(echo "$PACKAGE_VERSION_OUTPUT" | jq -r '.result.HasPassedCodeCoverageCheck // false')
echo "Package version status: $VERSION_STATUS"
echo "Code coverage passed: $CODE_COVERAGE_PASSED"
if [ "$CODE_COVERAGE_PASSED" = "false" ]; then
echo "⚠️ WARNING: Code coverage check has not passed yet"
echo "Package version may not be ready for promotion"
echo "Waiting 30 seconds for code coverage to complete..."
sleep 30
fi
# Run promotion with better error handling
set +e # Don't exit on error, we'll handle it manually
PROMOTE_OUTPUT=$(sf package version promote \
--package "$PACKAGE_VERSION_ID" \
--target-dev-hub pkgorg \
--json 2>&1)
PROMOTE_EXIT_CODE=$?
set -e # Re-enable exit on error
echo "Package version promote exit code: $PROMOTE_EXIT_CODE"
echo "Package version promote output:"
echo "$PROMOTE_OUTPUT"
if [ $PROMOTE_EXIT_CODE -eq 0 ]; then
echo "✅ Successfully promoted package version to released status"
else
echo "⚠️ WARNING: Failed to promote package version to released status"
echo "Exit code: $PROMOTE_EXIT_CODE"
echo "Error details:"
echo "$PROMOTE_OUTPUT"
# Try to extract specific error information
if echo "$PROMOTE_OUTPUT" | jq -e '.message' > /dev/null 2>&1; then
ERROR_MSG=$(echo "$PROMOTE_OUTPUT" | jq -r '.message')
echo "Error message: $ERROR_MSG"
fi
if echo "$PROMOTE_OUTPUT" | jq -e '.result[0].error' > /dev/null 2>&1; then
ERROR_DETAILS=$(echo "$PROMOTE_OUTPUT" | jq -r '.result[0].error')
echo "Error details: $ERROR_DETAILS"
fi
echo "Package will remain as prerelease version"
echo "You can manually promote it later using:"
echo "sf package version promote --package $PACKAGE_VERSION_ID --target-dev-hub pkgorg"
fi
else
echo "ℹ️ Package version remains as prerelease (release_type is prerelease)"
fi
else
echo "❌ ERROR: Failed to create package version"
echo "Exit code: $PACKAGE_VERSION_EXIT_CODE"
echo "Full output: $PACKAGE_VERSION_OUTPUT"
# Try to extract error details from JSON output
if echo "$PACKAGE_VERSION_OUTPUT" | jq -e '.message' > /dev/null 2>&1; then
ERROR_MESSAGE=$(echo "$PACKAGE_VERSION_OUTPUT" | jq -r '.message')
echo "Error message: $ERROR_MESSAGE"
fi
if echo "$PACKAGE_VERSION_OUTPUT" | jq -e '.result[0].error' > /dev/null 2>&1; then
ERROR_DETAILS=$(echo "$PACKAGE_VERSION_OUTPUT" | jq -r '.result[0].error')
echo "Error details: $ERROR_DETAILS"
fi
# Check for common issues
if echo "$PACKAGE_VERSION_OUTPUT" | grep -i "permission" > /dev/null; then
echo "💡 Possible permission issue - check if the user has Package Creation permissions"
fi
if echo "$PACKAGE_VERSION_OUTPUT" | grep -i "validation" > /dev/null; then
echo "💡 Possible validation error - check if all metadata is valid"
fi
if echo "$PACKAGE_VERSION_OUTPUT" | grep -i "coverage" > /dev/null; then
echo "💡 Possible code coverage issue - ensure all code has adequate test coverage"
fi
exit 1
fi
- name: Build changelog
run: |
# Get previous tag
git fetch --tags --quiet || true
PREV=$(git tag --sort=-creatordate | head -1)
if [ -n "$PREV" ]; then
RANGE="$PREV..HEAD"
COMPARE_LINK="https://github.com/${{ github.repository }}/compare/$PREV...${{ steps.version.outputs.tag }}"
else
FIRST=$(git rev-list --max-parents=0 HEAD)
RANGE="$FIRST..HEAD"
COMPARE_LINK="https://github.com/${{ github.repository }}/compare/$FIRST...${{ steps.version.outputs.tag }}"
fi
{
echo "## Release ${{ steps.version.outputs.tag }}"
echo
echo "**Package:** REST-API-Library-v${{ steps.version.outputs.new }}.zip"
echo "**Previous Version:** ${{ steps.version.outputs.current }}"
echo "**Release Type:** ${{ steps.version.outputs.release_type }}"
echo "**Package Version ID:** ${{ steps.package_version.outputs.package_version_id }}"
echo
echo "### Installation"
echo "- **Production:** [${{ steps.package_version.outputs.production_url }}](${{ steps.package_version.outputs.production_url }})"
echo "- **Sandbox:** [${{ steps.package_version.outputs.sandbox_url }}](${{ steps.package_version.outputs.sandbox_url }})"
echo "- **CLI:** \`sf package install --package ${{ steps.package_version.outputs.package_version_id }} --wait 10 --installation-key-bypass\`"
echo
echo "### Changes"
if [ -n "$PREV" ]; then
git log --pretty=format:'- %s (%h) — %an' $RANGE
else
echo "- Initial release"
fi
echo
echo "[Compare changes](${COMPARE_LINK})"
} > release_notes.md
echo "Generated changelog from $RANGE"
- name: Commit version changes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_AUTHOR_NAME: github-actions
GIT_AUTHOR_EMAIL: github-actions@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions
GIT_COMMITTER_EMAIL: github-actions@users.noreply.github.com
run: |
set -e
git add package.json manifest/package.xml sfdx-project.json
if ! git diff --quiet --staged; then
git commit -m "chore(release): bump version to ${{ steps.version.outputs.new }}"
fi
git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.new }}"
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }} HEAD:${{ github.ref_name }}
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }} "${{ steps.version.outputs.tag }}"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: release-${{ steps.version.outputs.tag }}
path: |
REST-API-Library-v${{ steps.version.outputs.new }}.zip
release_notes.md
retention-days: 30
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: REST API Library ${{ steps.version.outputs.tag }}
body_path: release_notes.md
files: |
REST-API-Library-v${{ steps.version.outputs.new }}.zip
prerelease: ${{ steps.version.outputs.release_type == 'prerelease' }}
latest: ${{ steps.version.outputs.release_type == 'latest' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update README with release info
run: |
PACKAGE_FILE="REST-API-Library-v${{ steps.version.outputs.new }}.zip"
{
echo "<!--LATEST-RELEASE-START-->"
echo "**Version:** ${{ steps.version.outputs.new }} "
echo "**Tag:** ${{ steps.version.outputs.tag }} "
echo "**Release Type:** ${{ steps.version.outputs.release_type }} "
echo "**Package Version ID:** ${{ steps.package_version.outputs.package_version_id }} "
echo "**Package:** [$PACKAGE_FILE](https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.tag }}/$PACKAGE_FILE) "
echo "**Release Date:** $(date -u +"%Y-%m-%d") "
echo ""
echo "### Quick Install"
echo "- **Production:** [${{ steps.package_version.outputs.production_url }}](${{ steps.package_version.outputs.production_url }})"
echo "- **Sandbox:** [${{ steps.package_version.outputs.sandbox_url }}](${{ steps.package_version.outputs.sandbox_url }})"
echo "- **CLI:** \`sf package install --package ${{ steps.package_version.outputs.package_version_id }} --wait 10 --installation-key-bypass\`"
echo ""
echo "<details><summary>Change summary</summary>"
echo ""
# Skip first 5 lines (header) from notes if desired:
awk 'NR>5 {print}' release_notes.md
echo "</details>"
echo "<!--LATEST-RELEASE-END-->"
} > latest_block.md
# Update README with the new block (replace entire section)
awk '
BEGIN{printing=1; in_section=0}
/<!--LATEST-RELEASE-START-->/ {print; system("cat latest_block.md"); printing=0; in_section=1; next}
/<!--LATEST-RELEASE-END-->/ {print; printing=1; in_section=0; next}
in_section==0 && printing==1 {print}
' README.md > README.md.new
mv README.md.new README.md
rm latest_block.md
echo "Updated README.md with latest release information"
- name: Commit README update
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_AUTHOR_NAME: github-actions
GIT_AUTHOR_EMAIL: github-actions@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions
GIT_COMMITTER_EMAIL: github-actions@users.noreply.github.com
run: |
set -e
if ! git diff --quiet; then
git add README.md
git commit -m "docs: update README for ${{ steps.version.outputs.tag }}"
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${{ github.repository }} HEAD:${{ github.ref_name }}
echo "Committed README update"
else
echo "No README changes to commit"
fi
- name: Summary
run: |
echo "## Release Created Successfully!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Version:** ${{ steps.version.outputs.new }}" >> $GITHUB_STEP_SUMMARY
echo "**Previous Version:** ${{ steps.version.outputs.current }}" >> $GITHUB_STEP_SUMMARY
echo "**Release Type:** ${{ steps.version.outputs.release_type }}" >> $GITHUB_STEP_SUMMARY
echo "**Bump Type:** ${{ github.event.inputs.bump }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Artifacts Created" >> $GITHUB_STEP_SUMMARY
echo "- Package zip file" >> $GITHUB_STEP_SUMMARY
echo "- Salesforce package version: ${{ steps.package_version.outputs.package_version_id }}" >> $GITHUB_STEP_SUMMARY
echo "- Production URL: ${{ steps.package_version.outputs.production_url }}" >> $GITHUB_STEP_SUMMARY
echo "- Sandbox URL: ${{ steps.package_version.outputs.sandbox_url }}" >> $GITHUB_STEP_SUMMARY
echo "- Release notes" >> $GITHUB_STEP_SUMMARY
echo "- Version file" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Next Steps" >> $GITHUB_STEP_SUMMARY
echo "- GitHub release created and README updated automatically!" >> $GITHUB_STEP_SUMMARY
echo "- Package version created and ready for installation!" >> $GITHUB_STEP_SUMMARY