Repository navigation
Docs snippets tests #538
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
techwritermat
wants to merge
8
commits into
master
Choose a base branch
from
docs-snippets-live-tests
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Docs snippets tests #538
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3d87be5
Docs snippets tests
techwritermat bc7ad42
Enhance presence tests and improve event loop idle handling
techwritermat 81736e6
Improve event loop handling and enhance timer management in wait func…
techwritermat 951db79
Wait for channel group presence before the hereNow samples
techwritermat 66fe002
Poll App Context read-backs after writes
techwritermat 406a1dc
Add summary script for snippet results in CI
techwritermat 7c9a1cd
Update documentation snippets to clarify execution limitations
techwritermat 0a7cb2b
Merge branch 'master' into docs-snippets-live-tests
techwritermat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| 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@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| 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@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| 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 }} | ||
| # Nightly: the CI keysets must have these features, so their skips fail the run. | ||
| DOCS_SNIPPETS_REQUIRE_FEATURES: ${{ github.event_name == 'schedule' && 'datasync-events,push-notifications' || '' }} | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| 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 | ||
| # Each shard runs even when an earlier one failed (success() || failure()), 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: success() || failure() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so, we will still run this step event previous setup steps failed? Does it really make sense? |
||
| 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: (success() || failure()) && 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: success() || failure() | ||
| 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: (success() || failure()) && 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: success() || failure() | ||
| 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: (success() || failure()) && 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() | ||
| 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" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Keys for the live docs snippet tests (docs-snippets/README.md, "Use your own keys"). | ||
| # Copy this file to docs-snippets/.env.local and fill in the values. Git ignores .env.local. | ||
| # Real environment variables win over this file. Leave a role empty to skip its steps (missing-env:<role>). | ||
|
|
||
| # open: a keyset without Access Manager | ||
| SUBSCRIBE_KEY= | ||
| PUBLISH_KEY= | ||
|
|
||
| # pam: a keyset with Access Manager and token revocation | ||
| PAM_SUBSCRIBE_KEY= | ||
| PAM_PUBLISH_KEY= | ||
| PAM_SECRET_KEY= | ||
|
|
||
| # datasync: a keyset with Access Manager and DataSync. It may be the same keyset as pam. | ||
| DS_SUBSCRIBE_KEY= | ||
| DS_PUBLISH_KEY= | ||
| DS_SECRET_KEY= | ||
|
|
||
| # Optional. A Service Integration key with DataSync read and write on the datasync keyset. It creates the DataSync classes. | ||
| PUBNUB_ADMIN_API_KEY= | ||
|
|
||
| # Optional, not secret. Admin Portal keyset ids, so the preflight can read each keyset's features through the Admin API. | ||
| DOCS_SNIPPETS_OPEN_KEYSET_ID= | ||
| DOCS_SNIPPETS_PAM_KEYSET_ID= | ||
| DOCS_SNIPPETS_DS_KEYSET_ID= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| 'use strict'; | ||
| /** | ||
| * Mocha options of the live docs snippet suite. harness/cli.ts reads them and adds the staged spec file, which only exists | ||
| * after staging (docs-snippets/.run/<runId>/harness/mocha-entry.ts). This file is separate from the SDK's root .mocharc.json | ||
| * on purpose: the suite never loads test/setup-why.ts (it restores nock) and the root spec never picks up the suite. | ||
| * | ||
| * retries 0: a retry would hide a flaky docs sample, waits are explicit (harness/wait.ts). bail false: one failing step must | ||
| * not hide the others. | ||
| */ | ||
| module.exports = { | ||
| reporter: require('node:path').join(__dirname, 'harness', 'reporter.cjs'), | ||
| retries: 0, | ||
| timeout: 30000, | ||
| bail: false, | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is brutal. We actually can at least trust official GitHub account to deliver stable products.
Current checkout is
v7