-
Notifications
You must be signed in to change notification settings - Fork 0
169 lines (149 loc) · 5.43 KB
/
ci.yml
File metadata and controls
169 lines (149 loc) · 5.43 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
name: CI
on:
pull_request:
branches:
- main
paths:
- "force-app/**"
types: [opened, reopened, synchronize]
concurrency:
# Cancel old runs when a new commit is pushed to the same branch
group: ci-${{ github.event.pull_request.number }}
cancel-in-progress: true
env:
CHANGES_DIR: changes
permissions:
actions: read
contents: read
issues: write
pull-requests: write
jobs:
scan:
name: Run Static Analysis
if: ${{ '! github.event.pull_request.draft' }}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Setup SF CLI
uses: ./.github/actions/setup-sf-cli
with:
install-plugins: "true"
- name: Get Changed Files
run: |
# Ensure this check only runs against changed files in the current PR; not the entire codebase
set -euo pipefail
mkdir "$CHANGES_DIR"
sf sgd source delta --generate-delta --from "HEAD^" --to "HEAD" --output-dir "$CHANGES_DIR"/ --source-dir "force-app/"
echo "Changed files:"
ls "$CHANGES_DIR"
- name: Run Salesforce Code Analyzer
id: scan
uses: forcedotcom/run-code-analyzer@v2
with:
github-token: ${{ github.token }}
results-artifact-name: salesforce-code-analyzer-results
run-arguments: "--target ${{ env.CHANGES_DIR }} --view detail --output-file sfca_results.json"
- name: Handle Errors
if: ${{ failure() && !cancelled() }}
uses: ./.github/actions/report-error
with:
actor: ${{ github.actor }}
job: ${{ github.job }}
run-id: ${{ github.run_id }}
token: ${{ github.token }}
- name: Evaluate
if: |
steps.scan.outputs.exit-code > 0 ||
steps.scan.outputs.num-sev1-violations > 0 ||
steps.scan.outputs.num-sev2-violations > 0
run: |
echo "🚨 sf code-analyzer detected violations that exceed the acceptable threshold."
exit 1
run-unit-tests:
name: Run Unit Tests
if: ${{ '! github.event.pull_request.draft' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup SF CLI
uses: ./.github/actions/setup-sf-cli
- name: Authenticate Devhub
env:
CLIENT_ID: ${{ secrets.SALESFORCE_CONSUMER_KEY }}
JWT_KEY: ${{ secrets.SALESFORCE_JWT_KEY }}
USERNAME: ${{ secrets.SALESFORCE_DEVHUB_USERNAME }}
run: |
set -euo pipefail
echo "${JWT_KEY}" > server.key
sf org login jwt \
--client-id "$CLIENT_ID" \
--jwt-key-file server.key \
--set-default-dev-hub \
--username "$USERNAME"
# TODO: Consider making a dedicated get/create scratch org helper action.yml
- name: Generate Username
id: generate-username
run: |
# Dynamically generate a scratch org username, based on the repository
USERNAME="${GITHUB_REPOSITORY##*/}-ci@${GITHUB_REPOSITORY%%/*}.com"
echo "username=$USERNAME" >> "$GITHUB_OUTPUT"
echo "Scratch Org Username: $USERNAME"
- name: Get Existing Scratch Org
id: get-existing
continue-on-error: true
env:
CLIENT_ID: ${{ secrets.SALESFORCE_CONSUMER_KEY }}
DEV_HUB: ${{ secrets.SALESFORCE_DEVHUB_USERNAME }}
JWT_KEY: ${{ secrets.SALESFORCE_JWT_KEY }}
USERNAME: ${{ steps.generate-username.outputs.username }}
run: |
# Re-use scratch orgs to prevent exceeding new scratch orgs/day limits:
set -euo pipefail
QUERY="SELECT LoginUrl FROM ScratchOrgInfo WHERE SignupUsername = '$USERNAME'"
RESPONSE=$(sf data query --target-org "$DEV_HUB" -q "$QUERY" --json 2>/dev/null || true)
LOGIN_URL=$(echo "$RESPONSE" | jq -r '.result.records[0]?.LoginUrl // empty')
echo "Existing Scratch Org: $LOGIN_URL"
if [[ -n "$LOGIN_URL" && "$LOGIN_URL" != "null" ]]; then
sf org login jwt \
--client-id "$CLIENT_ID" \
--instance-url "$LOGIN_URL" \
--jwt-key-file server.key \
--set-default \
--username "$USERNAME"
echo "success=true" >> "$GITHUB_OUTPUT"
fi
- name: Create Scratch Org
if: ${{ steps.get-existing.outputs.success != 'true' }}
env:
USERNAME: ${{ steps.generate-username.outputs.username }}
run: |
set -euo pipefail
sf org create scratch \
--definition-file config/project-scratch-def.json \
--duration-days 1 \
--set-default \
--username "$USERNAME" \
--wait 10
- name: Deploy
env:
SCRATCH_ORG: ${{ steps.generate-username.outputs.username }}
run: sf project deploy start --target-org "$SCRATCH_ORG"
- name: Run Tests
run: sf apex run test --code-coverage --result-format human --synchronous
- name: Cleanup
if: ${{ always() }}
run: rm -f server.key
- name: Handle Errors
if: ${{ failure() && !cancelled() }}
uses: ./.github/actions/report-error
with:
actor: ${{ github.actor }}
job: ${{ github.job }}
run-id: ${{ github.run_id }}
token: ${{ github.token }}