Repository navigation
216 lines (208 loc) · 9.41 KB
/
Copy pathdocs-snippets.yml
File metadata and controls
216 lines (208 loc) · 9.41 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
name: Docs snippets
# Live tests of the JavaScript docs code samples (docs-snippets/README.md). Separate from run-tests.yml on purpose: this
# suite calls the real PubNub service and is never part of npm test, ci:node or ci:web.
#
# No workflow-level paths filter: a required check behind a paths filter stays pending. The `changes` job decides instead,
# and the `gate` job is the one to require in branch protection.
on:
pull_request:
push:
branches: [master]
schedule:
- cron: '17 3 * * *'
workflow_dispatch:
defaults:
run:
shell: bash
permissions:
contents: read
jobs:
changes:
name: Relevant changes
runs-on:
group: organization/Default
outputs:
changed: ${{ steps.diff.outputs.changed }}
live: ${{ steps.diff.outputs.live }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Decide with git diff
id: diff
env:
EVENT: ${{ github.event_name }}
PR_BASE: ${{ github.event.pull_request.base.sha }}
PUSH_BEFORE: ${{ github.event.before }}
FORK: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
run: |
changed=false
if [ "$EVENT" = "schedule" ] || [ "$EVENT" = "workflow_dispatch" ]; then
changed=true
else
base="$PR_BASE"
[ "$EVENT" = "push" ] && base="$PUSH_BEFORE"
if [ -z "$base" ] || [ "$base" = "0000000000000000000000000000000000000000" ] || ! git cat-file -e "$base^{commit}" 2>/dev/null; then
changed=true
elif git diff --name-only "$base" HEAD | grep -qE '^(docs-snippets/|src/|lib/|package\.json$|package-lock\.json$|\.github/workflows/docs-snippets\.yml$)'; then
changed=true
fi
fi
live=$changed
if [ "$FORK" = "true" ]; then
live=false
[ "$changed" = "true" ] && echo "live shards skipped: fork PR without secrets" >> "$GITHUB_STEP_SUMMARY"
fi
echo "changed=$changed" >> "$GITHUB_OUTPUT"
echo "live=$live" >> "$GITHUB_OUTPUT"
echo "relevant changes: $changed, live shards: $live"
dry:
name: Dry run, types and manifest
needs: [changes]
if: needs.changes.outputs.changed == 'true'
runs-on:
group: organization/Default
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Setup NodeJS 22
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build the SDK for Node
run: npm run build:node
- name: Dry run (no network)
run: npm run test:docs-snippets:dry
- name: Type check the suite and the browser samples
run: npm run test:docs-snippets:types
- name: Check the coverage manifest
run: npm run docs-snippets:manifest -- --check
live:
name: Live shards (open, pam, datasync)
needs: [changes, dry]
if: needs.changes.outputs.live == 'true'
runs-on:
group: organization/Default
# The three shards run one after another in this one job, never in parallel. The pam and datasync roles may share one
# keyset, and the pam shard opens it with an application-level grant for a moment. Run in parallel, that grant and the
# janitor's revoke would break the other shard.
timeout-minutes: 35
# One live job at a time across the repository, so two workflow runs (a pull request and master, say) never share the
# keysets either. A newer waiting run replaces an older waiting one, a running one is never cancelled.
concurrency:
group: docs-snippets-live
cancel-in-progress: false
# Keys and secrets. The one place that maps CI secrets onto the env names the suite reads (docs-snippets/README.md, "Keys in
# CI"). They are set on the steps that run the suite only, never on the job, so `npm ci` (install scripts of
# dependencies) and the build never see them.
env:
DOCS_SNIPPETS_DS_KEYSET_ID: ${{ vars.SDK_DOCS_DS_KEYSET_ID }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Setup NodeJS 22
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build the SDK for Node
id: build
run: npm run build:node
# Each shard runs when the build succeeded, even when an earlier shard failed, but not after a cancel. Each gets the secret
# key of its own role only. The janitor step after them needs every role, so it keeps all of them.
- name: Shard open
id: open
if: '!cancelled() && steps.build.outcome == ''success'''
env:
SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_OPEN_SUBSCRIBE_KEY }}
PUBLISH_KEY: ${{ secrets.SDK_DOCS_OPEN_PUBLISH_KEY }}
run: npm run test:docs-snippets -- --shard open
- name: Keep the open report
if: always() && steps.open.outcome != 'skipped'
run: mkdir -p docs-snippets/report/open && mv docs-snippets/report/run.json docs-snippets/report/summary.md docs-snippets/report/open/ 2>/dev/null || true
- name: Shard pam
id: pam
if: '!cancelled() && steps.build.outcome == ''success'''
env:
SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_OPEN_SUBSCRIBE_KEY }}
PUBLISH_KEY: ${{ secrets.SDK_DOCS_OPEN_PUBLISH_KEY }}
PAM_SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_PAM_SUBSCRIBE_KEY }}
PAM_PUBLISH_KEY: ${{ secrets.SDK_DOCS_PAM_PUBLISH_KEY }}
PAM_SECRET_KEY: ${{ secrets.SDK_DOCS_PAM_SECRET_KEY }}
run: npm run test:docs-snippets -- --shard pam
- name: Keep the pam report
if: always() && steps.pam.outcome != 'skipped'
run: mkdir -p docs-snippets/report/pam && mv docs-snippets/report/run.json docs-snippets/report/summary.md docs-snippets/report/pam/ 2>/dev/null || true
- name: Shard datasync
id: datasync
if: '!cancelled() && steps.build.outcome == ''success'''
env:
SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_OPEN_SUBSCRIBE_KEY }}
PUBLISH_KEY: ${{ secrets.SDK_DOCS_OPEN_PUBLISH_KEY }}
DS_SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_DS_SUBSCRIBE_KEY }}
DS_PUBLISH_KEY: ${{ secrets.SDK_DOCS_DS_PUBLISH_KEY }}
DS_SECRET_KEY: ${{ secrets.SDK_DOCS_DS_SECRET_KEY }}
# Only this shard gets the Admin API key: it sets up the DataSync classes before the tests.
PUBNUB_ADMIN_API_KEY: ${{ secrets.SDK_DOCS_ADMIN_API_KEY }}
run: npm run test:docs-snippets -- --shard datasync
- name: Keep the datasync report
if: always() && steps.datasync.outcome != 'skipped'
run: mkdir -p docs-snippets/report/datasync && mv docs-snippets/report/run.json docs-snippets/report/summary.md docs-snippets/report/datasync/ 2>/dev/null || true
# One block on the run page with a row per snippet id (passed, FAILED, skipped, not run, type checked only). It reads the
# shard reports and coverage.json, needs no secrets, and runs after a failure or a cancel too.
- name: Result per snippet id
if: always()
run: node docs-snippets/harness/snippet-summary.cjs docs-snippets/report/open docs-snippets/report/pam docs-snippets/report/datasync
# After a failure or a cancel: revoke the application-level Access Manager grants and remove leftovers, so a run that
# died between a grant and its revoke never leaves a keyset open until the next run.
- name: Revoke grants and clean up
if: (cancelled() || failure()) && steps.build.outcome == 'success'
env:
SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_OPEN_SUBSCRIBE_KEY }}
PUBLISH_KEY: ${{ secrets.SDK_DOCS_OPEN_PUBLISH_KEY }}
PAM_SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_PAM_SUBSCRIBE_KEY }}
PAM_PUBLISH_KEY: ${{ secrets.SDK_DOCS_PAM_PUBLISH_KEY }}
PAM_SECRET_KEY: ${{ secrets.SDK_DOCS_PAM_SECRET_KEY }}
DS_SUBSCRIBE_KEY: ${{ secrets.SDK_DOCS_DS_SUBSCRIBE_KEY }}
DS_PUBLISH_KEY: ${{ secrets.SDK_DOCS_DS_PUBLISH_KEY }}
DS_SECRET_KEY: ${{ secrets.SDK_DOCS_DS_SECRET_KEY }}
run: npm run test:docs-snippets:janitor
- name: Upload the reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: docs-snippets-reports
path: docs-snippets/report/
if-no-files-found: warn
gate:
name: Docs snippets
if: always()
needs: [changes, dry, live]
runs-on:
group: organization/Default
steps:
- name: Decide
env:
RESULTS: ${{ needs.changes.result }} ${{ needs.dry.result }} ${{ needs.live.result }}
CHANGED: ${{ needs.changes.outputs.changed }}
run: |
echo "changes, dry, live: $RESULTS (relevant changes: $CHANGED)"
for result in $RESULTS; do
if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
echo "a needed job ended with $result"
exit 1
fi
done
echo "docs snippets gate passed"