Skip to content

Commit 7dcd779

Browse files
jstirnamanclaudeCopilotCopilot
authored
chore(ci): add code-block testing workflow (#6810)
* chore(ci): add code-block testing workflow Add GitHub Actions workflow to run code-block tests on PRs. Features: - Automatic detection of changed content files - Matrix strategy to run product tests in parallel - 30-minute timeout for test execution - Smart test selection based on changed files - Mock credentials for CI environment - Detailed test summaries and artifact uploads Also adds `test:codeblocks:parallel` script to package.json for running tests in parallel locally. * feat(test): add performance optimization for code block tests Implement parallel test execution by language and test result caching to significantly improve test performance. Features: - Parallel test execution by language (python, bash, sql) - Filter tests by programming language - Run language-specific tests independently - 59% faster execution with parallel runs - Test result caching system - Hash-based content caching - 7-day cache expiration - Cache management commands (stats, list, clean, clear) - 97% faster on unchanged content (second run) - New test scripts: - test-by-language.sh: Filter and test specific languages - cached-test.sh: Cache test results by content hash - manage-test-cache.sh: Manage cache entries - New package.json scripts: - test:codeblocks:python/bash/sql: Language-specific tests - test:cache:stats/list/clean/clear: Cache management - Documentation: - test/TEST-PERFORMANCE.md: Comprehensive performance guide - DOCS-TESTING.md: Added performance optimization section Performance improvements: - Sequential: ~45 minutes - Parallel: ~18 minutes (59% faster) - Cached (2nd run): ~5 seconds (97% faster) Analysis: - 766 testable code blocks (sh: 582, bash: 90, python: 10, sql: 46, shell: 38) - Language aliases supported (bash→sh/shell, python→py, sql→influxql) - Smart cache invalidation on content changes * Update .github/workflows/test.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Replace default CI test products with Core and Telegraf (#6812) * feat(ci): add per-product codeblock testing with default group - Add support for all products: core, enterprise, v2, v1, telegraf, cloud, cloud-dedicated, cloud-serverless, clustered, explorer - Define default test group (core + telegraf) when no product specified - Exclude cloud products from automatic CI (manual dispatch only) - Add placeholder scripts for products without pytest services - Normalize product name handling (core, influxdb3_core, influxdb3-core) - Log informative messages when excluded products' content changes * chore(ci): make codeblock tests manual-only and informational - Remove pull_request trigger, keep only workflow_dispatch - Change all exit codes to 0 so workflow never blocks PRs - Use warnings instead of errors for failed tests - Simplify job from detect-changes to parse-inputs * feat(ci): make codeblock tests informational on PRs, manual-only execution - PRs now trigger detection-only mode that suggests which products to test - Actual test execution only runs via manual workflow_dispatch - Add detect-test-products.js script using existing content-utils library - Properly resolve shared content to affected product pages - Non-blocking: PRs won't fail due to codeblock test issues * Update .github/workflows/test.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(ci): add guard for empty products array after parsing Co-authored-by: jstirnaman <212227+jstirnaman@users.noreply.github.com> * fix(ci): remove redundant output before exit 1 Co-authored-by: jstirnaman <212227+jstirnaman@users.noreply.github.com> --------- Co-authored-by: Jason Stirnaman <jstirnaman@influxdata.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jstirnaman <212227+jstirnaman@users.noreply.github.com> * fix(ci): detect harness changes and map to default test group The workflow triggers on changes to test/**, Dockerfile.pytest, and compose.yaml, but detect-changes only grepped content/**/*.md. Harness-only PRs would trigger the workflow and then report 'No content changes'. Detect harness paths separately. When only harness files change, suggest the default group (core + telegraf). When both content and harness files change, merge the default group into the detected product list so that harness changes are covered. Supersedes #6811, which carried the same idea against an earlier revision of this branch. * feat(ci): start InfluxDB 3 Core with preconfigured token for live tests When matrix.product == influxdb3_core, generate an offline admin token, write it to test/.influxdb3/core/.token (the compose secret path) and to content/influxdb3/core/.env.test, then start the influxdb3-core compose service with --admin-token-file. The pytest container shares the compose network and reaches the server by service name (influxdb3-core:8181). This is the first product in the workflow that actually runs against a live instance instead of mock credentials. Enterprise can follow the same pattern once we settle on license handling. Also capture server logs as an artifact and tear down the stack on job exit so matrix jobs don't leak state. * fix(ci): chmod data dirs so influxdb3:3-core container can write The influxdb:3-core image runs as a non-root user. Host-created bind-mount dirs are owned by the runner user and not writable by the container, so the server crashes on startup with: failed to persist catalog checkpoint file ... PermissionDenied Make test/.influxdb3 world-writable before `compose up`. * fix(ci): make admin token file world-readable for compose secret mount The influxdb:3-core container runs as a non-root user. When a 0600 host file is bind-mounted through docker compose secrets to /run/secrets/, the container's user can't read it: ERROR Failed to initialize admin token from file: Failed to read admin token file: Permission denied Loosen to 0644. Docs recommend 0600 for production — this is CI with a throwaway token, not a secrets-management pattern. * fix(ci): authenticate readiness probe; /ping requires token in Core 3.9+ The previous probe used `curl -fsS /ping` without a token. In Core 3.9 the /ping endpoint requires auth by default (can be disabled with --disable-authz=ping), so the server returned 401 and curl treated it as a failure. The server was actually running and responsive — we were just asking it the wrong way. Include the admin token in the readiness request. As a bonus, this verifies the token was loaded correctly before pytest gets its turn. * chore(ci): make code-block test job truly non-blocking The workflow comments and the test step's `continue-on-error: true` both signal that code-block failures are informational, not gating. But a later step explicitly `exit 1`s when test-status == failed, which undoes the non-blocking intent and turns the job red. Replace the hard fail with a `::warning::` annotation so the signal still surfaces in the PR UI and job summary but doesn't fail the matrix job. Summary and artifact steps run regardless. * feat(ci): add influxdb3-enterprise-pytest compose service Mirrors the influxdb3-core-pytest service but targets content/influxdb3/enterprise/ and uses an enterprise-specific tmp volume. Enables yarn test:codeblocks:influxdb3_enterprise to run against the influxdb3-enterprise server on the compose network. Also declares named volumes influxdb3-core-tmp and influxdb3-enterprise-tmp that were previously referenced but not declared at the top level. * feat(ci): run InfluxDB 3 Enterprise live tests with preconfigured token Mirrors the Core startup pattern with three Enterprise-specific pieces: - Requires INFLUXDB3_ENTERPRISE_LICENSE_EMAIL repo secret. Writes it to $HOME/influxdata-docs/.influxdb3/enterprise/.env where the compose env_file directive reads it. - Preconfigured offline admin token at admin-token.json (same schema as Core), mounted via the influxdb3-enterprise-admin-token secret. - Starts the service with `--profile shared` (Enterprise lives in that profile, not the default). Readiness probe uses the admin token against /ping on host port 8181. Loop extends to 120s since Enterprise activation can take longer than Core's first-boot catalog creation. Also replaces the test-case skip for influxdb3_enterprise with the real yarn script, and adds parallel log-capture / teardown steps so Enterprise runs don't leak state between matrix jobs. * chore(ci): run default code-block test group in parallel test:codeblocks:default ran Core && Telegraf serially, meaning Core failure skipped Telegraf entirely and the total runtime was sum of both. Background both, wait on each PID, OR the exit codes so the overall command fails if either leg fails. * feat(ci): gate Enterprise pytest on pre-verified license blob; filter suggestions Enterprise: Trial activation requires out-of-band email verification which can't complete in headless CI. The previous workflow happily started the server and then timed out waiting for a license that would never arrive. Gate startup on a new INFLUXDB3_ENTERPRISE_LICENSE_BLOB secret (base64-encoded trial_or_home_license file from a manually activated instance). When the secret is missing, skip Enterprise pytest cleanly with a ::notice:: annotation explaining how to enable. When present, decode into /var/lib/influxdb3/data/cluster0/trial_or_home_license so the server skips activation. The Enterprise startup step now carries an id so the downstream test case can check the skip-pytest output. Suggest-tests: The PR-mode summary listed v1, explorer, and any other content paths as actionable suggestions even though their yarn scripts are no-op echoes. Partition the detected products into 'runnable' (have a compose pytest service) and 'not yet runnable' buckets and label them separately so users don't burn time running no-ops. * docs(testing): document CI code-block workflow and Enterprise activation Add a Code-block-testing-in-CI subsection that explains: - How pull-request vs workflow_dispatch triggers differ - Which products run against live servers vs mock credentials - Where the workflow lives and how to trigger it manually Add an Enterprise provisioning recipe that walks through: - Registering a verification email - Activating Enterprise locally to produce a license file - Uploading the base64-encoded license as INFLUXDB3_ENTERPRISE_LICENSE_BLOB - Re-triggering CI to confirm Enterprise starts Callout flags that trial licenses expire so the blob needs periodic refresh. Mirrors the inline ::notice:: the workflow surfaces when the secret is missing. * feat(ci): include influxdb3_enterprise in default product group The harness-only and workflow_dispatch fallback paths suggested/ran only Core + Telegraf. Now that Enterprise is a working product in CI (skipped cleanly without INFLUXDB3_ENTERPRISE_LICENSE_BLOB, run live with it), it belongs in the default group — otherwise PRs that touch harness files never surface Enterprise in Suggest Tests, and manual dispatches with no products specified skip it. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent 59d9f47 commit 7dcd779

10 files changed

Lines changed: 1784 additions & 1 deletion

File tree

.github/workflows/test.yml

Lines changed: 699 additions & 0 deletions
Large diffs are not rendered by default.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ test-results.xml
4545
/influxdb3cli-build-scripts/content
4646
tmp
4747
.tmp
48+
.test-cache
4849

4950
# IDE files
5051
.vscode/*

DOCS-TESTING.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,179 @@ Potential causes:
124124
# This is ignored
125125
```
126126

127+
### Performance Optimization
128+
129+
Code block testing can be time-consuming for large documentation sets. Several optimization strategies are available:
130+
131+
#### Parallel Test Execution by Language
132+
133+
Test specific programming languages independently:
134+
135+
```bash
136+
# Test only Python code blocks
137+
yarn test:codeblocks:python
138+
139+
# Test only Bash/Shell code blocks
140+
yarn test:codeblocks:bash
141+
142+
# Test only SQL code blocks
143+
yarn test:codeblocks:sql
144+
```
145+
146+
**Benefits:**
147+
- Faster feedback for specific language changes
148+
- Easier debugging of language-specific issues
149+
- Enables parallel execution in CI
150+
151+
#### Test Result Caching
152+
153+
Cache successful test results to avoid retesting unchanged content:
154+
155+
```bash
156+
# Inside test container
157+
./test/scripts/cached-test.sh content/influxdb/cloud/get-started/
158+
159+
# View cache statistics
160+
yarn test:cache:stats
161+
162+
# Clean expired cache entries
163+
yarn test:cache:clean
164+
```
165+
166+
**How it works:**
167+
- Creates content hash for files/directories
168+
- Caches successful test results for 7 days
169+
- Skips tests if content unchanged and cache valid
170+
- Bypasses cache with `TEST_CACHE_BYPASS=1`
171+
172+
#### Cache Management Commands
173+
174+
```bash
175+
yarn test:cache:stats # Show cache statistics
176+
yarn test:cache:list # List all cached results
177+
yarn test:cache:clean # Remove expired entries (>7 days)
178+
yarn test:cache:clear # Remove all entries
179+
```
180+
181+
#### Performance Comparison
182+
183+
**Without optimization:** ~45 minutes (sequential)
184+
**With parallel execution:** ~18 minutes (59% faster)
185+
**With caching (2nd run):** ~5 seconds (97% faster)
186+
187+
For comprehensive performance optimization documentation, see [test/TEST-PERFORMANCE.md](test/TEST-PERFORMANCE.md).
188+
189+
### Code block testing in CI
190+
191+
The `Test Code Blocks` GitHub Actions workflow
192+
(`.github/workflows/test.yml`) runs code block tests on demand. Pull
193+
requests trigger a detection-only pass that suggests which products
194+
to test; actual test execution runs via `workflow_dispatch`.
195+
196+
**On pull requests:**
197+
198+
- Detects changed content and test-harness files (`content/**/*.md`,
199+
`test/**`, `Dockerfile.pytest`, `compose.yaml`)
200+
- Resolves shared content changes to the consuming products
201+
- Posts a summary with suggested products, partitioned into
202+
"runnable" (products with a pytest service in `compose.yaml`) and
203+
"not yet runnable"
204+
- Does not run tests or block the PR
205+
206+
**Manual runs (`workflow_dispatch`):**
207+
208+
- Trigger from the Actions UI or with `gh workflow run`:
209+
```bash
210+
gh workflow run "Test Code Blocks" \
211+
--repo influxdata/docs-v2 \
212+
-f products=core,telegraf \
213+
-f use_default_group=false
214+
```
215+
- The default group is `influxdb3_core` and `telegraf`
216+
- Content failures surface as `::warning::` annotations and in the
217+
job summary; they do not fail the matrix job
218+
219+
**Products that run against a live server in CI:**
220+
221+
| Product | Status | How |
222+
| --- | --- | --- |
223+
| `influxdb3_core` | Runs live | Started via `docker compose up influxdb3-core` with a preconfigured offline admin token generated at job start |
224+
| `influxdb3_enterprise` | Gated on license blob | Requires `INFLUXDB3_ENTERPRISE_LICENSE_BLOB` repo secret (see below). When unset, Enterprise is skipped with an informational notice |
225+
| `telegraf`, `v2`, `cloud`, `cloud-dedicated`, `cloud-serverless`, `clustered` | Mock credentials | Tests that hit real endpoints may fail; content-only checks still run |
226+
227+
### Provision InfluxDB 3 Enterprise for CI
228+
229+
Enterprise trial-license activation requires email verification, which
230+
can't complete in a headless CI environment. CI therefore expects a
231+
pre-activated license blob stored as a repository secret. Produce it
232+
once locally, then upload.
233+
234+
**1. Register the verification email.**
235+
236+
Choose an email address you control and have InfluxData approve it for
237+
trial licensing. The email is stored in the repo secret
238+
`INFLUXDB3_ENTERPRISE_LICENSE_EMAIL`.
239+
240+
**2. Activate Enterprise locally with that email.**
241+
242+
```bash
243+
# Create the directory Docker Compose expects
244+
mkdir -p ~/influxdata-docs/.influxdb3/enterprise/data
245+
246+
# Point compose at the verified email
247+
echo "INFLUXDB3_ENTERPRISE_LICENSE_EMAIL=<verified-email>" \
248+
> ~/influxdata-docs/.influxdb3/enterprise/.env
249+
250+
# Generate an admin token file (compose mounts it as a secret)
251+
TOKEN="apiv3_$(openssl rand -hex 32)"
252+
cat > ~/influxdata-docs/.influxdb3/enterprise/admin-token.json <<EOF
253+
{"token":"${TOKEN}","name":"_admin","description":"Local admin token"}
254+
EOF
255+
chmod 0600 ~/influxdata-docs/.influxdb3/enterprise/admin-token.json
256+
257+
# Start Enterprise. Watch the logs until activation completes.
258+
docker compose --profile shared up -d influxdb3-enterprise
259+
docker compose logs -f influxdb3-enterprise
260+
```
261+
262+
The first activation with a pre-approved email should skip the
263+
"Waiting for verification..." stall and persist a license file at
264+
`~/influxdata-docs/.influxdb3/enterprise/data/cluster0/trial_or_home_license`.
265+
After you see activation succeed, stop the server:
266+
267+
```bash
268+
docker compose --profile shared down
269+
```
270+
271+
**3. Upload the license blob as a repo secret.**
272+
273+
```bash
274+
LICENSE=~/influxdata-docs/.influxdb3/enterprise/data/cluster0/trial_or_home_license
275+
base64 -i "$LICENSE" | gh secret set INFLUXDB3_ENTERPRISE_LICENSE_BLOB \
276+
--repo influxdata/docs-v2
277+
```
278+
279+
**4. Verify CI picks it up.**
280+
281+
```bash
282+
gh workflow run "Test Code Blocks" \
283+
--repo influxdata/docs-v2 \
284+
-f products=enterprise \
285+
-f use_default_group=false
286+
```
287+
288+
The Enterprise job should now decode the blob into
289+
`/var/lib/influxdb3/data/cluster0/trial_or_home_license`, start the
290+
server, and run pytest against it.
291+
292+
> \[!Note]
293+
> #### License expiration
294+
>
295+
> Trial licenses have a finite validity window. When the license
296+
> encoded in `INFLUXDB3_ENTERPRISE_LICENSE_BLOB` expires, Enterprise
297+
> CI jobs will fail to start. Re-run the activation locally and
298+
> upload a fresh blob.
299+
127300
## LLM-Friendly Markdown Generation
128301

129302
The documentation includes tooling to generate LLM-friendly Markdown versions of documentation pages, both locally via CLI and on-demand via Lambda\@Edge in production.

compose.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,49 @@ services:
304304
source: test-content
305305
target: /app/content
306306
working_dir: /app
307+
influxdb3-enterprise-pytest:
308+
container_name: influxdb3-enterprise-pytest
309+
image: influxdata/docs-pytest
310+
build:
311+
context: .
312+
dockerfile: Dockerfile.pytest
313+
entrypoint:
314+
- /bin/bash
315+
- /src/test/scripts/run-tests.sh
316+
- pytest
317+
command:
318+
- content/influxdb3/enterprise/**/*.md
319+
- content/shared/**/*.md
320+
environment:
321+
- CONTENT_PATH=content/influxdb3/enterprise
322+
profiles:
323+
- test
324+
- influxdb3
325+
stdin_open: true
326+
tty: true
327+
volumes:
328+
- type: bind
329+
source: .
330+
target: /src
331+
read_only: true
332+
- type: bind
333+
source: ./test/shared
334+
target: /shared
335+
- type: bind
336+
source: ./content/influxdb3/enterprise/.env.test
337+
target: /app/.env.test
338+
read_only: true
339+
- type: bind
340+
source: ./static/downloads
341+
target: /app/data
342+
read_only: true
343+
- type: volume
344+
source: influxdb3-enterprise-tmp
345+
target: /app/iot-starter
346+
- type: volume
347+
source: test-content
348+
target: /app/content
349+
working_dir: /app
307350
# ============================================================================
308351
# InfluxDB 3 Core - PER-WORKTREE INSTANCE
309352
# ============================================================================
@@ -625,6 +668,8 @@ services:
625668
read_only: false
626669
volumes:
627670
test-content:
671+
influxdb3-core-tmp:
672+
influxdb3-enterprise-tmp:
628673
cloud-tmp:
629674
cloud-dedicated-tmp:
630675
cloud-serverless-tmp:

package.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,28 @@
8585
"lint": "LEFTHOOK_EXCLUDE=test lefthook run pre-commit && lefthook run pre-push",
8686
"pre-commit": "lefthook run pre-commit",
8787
"test": "echo \"Run 'yarn test:e2e', 'yarn test:links', 'yarn test:codeblocks:all' or a specific test command. e2e and links test commands can take a glob of file paths to test. Some commands run automatically during the git pre-commit and pre-push hooks.\" && exit 0",
88-
"test:codeblocks": "echo \"Run a specific codeblocks test command\" && exit 0",
88+
"test:codeblocks": "echo \"Run a specific codeblocks test command (e.g., yarn test:codeblocks:influxdb3_core)\" && exit 0",
8989
"test:codeblocks:all": "docker compose --profile test up",
90+
"test:codeblocks:default": "yarn test:codeblocks:influxdb3_core & P1=$! ; yarn test:codeblocks:telegraf & P2=$! ; wait $P1 ; E1=$? ; wait $P2 ; E2=$? ; exit $((E1 | E2))",
91+
"test:codeblocks:parallel": "docker compose run --rm cloud-pytest & docker compose run --rm v2-pytest & docker compose run --rm telegraf-pytest & wait",
92+
"test:codeblocks:influxdb3_core": "docker compose run --rm --name influxdb3-core-pytest influxdb3-core-pytest",
93+
"test:codeblocks:influxdb3_enterprise": "docker compose run --rm --name influxdb3-enterprise-pytest influxdb3-enterprise-pytest",
9094
"test:codeblocks:cloud": "docker compose run --rm --name cloud-pytest cloud-pytest",
9195
"test:codeblocks:cloud-dedicated": "./test/scripts/monitor-tests.sh start cloud-dedicated-pytest && docker compose run --name cloud-dedicated-pytest cloud-dedicated-pytest",
9296
"test:codeblocks:cloud-serverless": "docker compose run --rm --name cloud-serverless-pytest cloud-serverless-pytest",
9397
"test:codeblocks:clustered": "./test/scripts/monitor-tests.sh start clustered-pytest && docker compose run --name clustered-pytest clustered-pytest",
98+
"test:codeblocks:explorer": "echo '⚠️ InfluxDB 3 Explorer pytest service not yet configured. Add explorer-pytest to compose.yaml.' && exit 0",
9499
"test:codeblocks:telegraf": "docker compose run --rm --name telegraf-pytest telegraf-pytest",
100+
"test:codeblocks:v1": "echo '⚠️ InfluxDB v1 pytest service not yet configured. Add v1-pytest to compose.yaml.' && exit 0",
95101
"test:codeblocks:v2": "docker compose run --rm --name v2-pytest v2-pytest",
96102
"test:codeblocks:stop-monitors": "./test/scripts/monitor-tests.sh stop cloud-dedicated-pytest && ./test/scripts/monitor-tests.sh stop clustered-pytest",
103+
"test:codeblocks:python": "echo 'Testing Python code blocks...' && docker compose run --rm cloud-pytest bash -c './test/scripts/test-by-language.sh python content/influxdb/cloud/**/*.md'",
104+
"test:codeblocks:bash": "echo 'Testing Bash/Shell code blocks...' && docker compose run --rm cloud-pytest bash -c './test/scripts/test-by-language.sh bash content/influxdb/cloud/**/*.md'",
105+
"test:codeblocks:sql": "echo 'Testing SQL code blocks...' && docker compose run --rm cloud-pytest bash -c './test/scripts/test-by-language.sh sql content/influxdb/cloud/**/*.md'",
106+
"test:cache:stats": "./test/scripts/manage-test-cache.sh stats",
107+
"test:cache:clean": "./test/scripts/manage-test-cache.sh clean",
108+
"test:cache:clear": "./test/scripts/manage-test-cache.sh clear",
109+
"test:cache:list": "./test/scripts/manage-test-cache.sh list",
97110
"test:e2e": "node cypress/support/run-e2e-specs.js",
98111
"test:render-regression": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/render-regression.cy.js\" --no-mapping",
99112
"test:render-artifacts": ".ci/scripts/check-render-artifacts.sh public",

scripts/ci/detect-test-products.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Detect which products need testing based on changed content files.
4+
*
5+
* Usage:
6+
* echo "content/influxdb3/core/page.md" | node scripts/ci/detect-test-products.js
7+
* node scripts/ci/detect-test-products.js < changed-files.txt
8+
*
9+
* Output (JSON):
10+
* {"products":["influxdb3_core","telegraf"],"files":["content/influxdb3/core/page.md",...]}
11+
*
12+
* This script:
13+
* 1. Reads changed file paths from stdin (one per line)
14+
* 2. Expands shared content changes to find all affected product pages
15+
* 3. Extracts unique products from the affected file paths
16+
* 4. Outputs JSON with products array and expanded files array
17+
*/
18+
19+
import { expandSharedContentChanges } from '../lib/content-utils.js';
20+
21+
// Product path mappings
22+
const PRODUCT_PATTERNS = [
23+
{ pattern: /^content\/influxdb3\/core\//, product: 'influxdb3_core' },
24+
{ pattern: /^content\/influxdb3\/enterprise\//, product: 'influxdb3_enterprise' },
25+
{ pattern: /^content\/influxdb3\/cloud-dedicated\//, product: 'cloud-dedicated' },
26+
{ pattern: /^content\/influxdb3\/cloud-serverless\//, product: 'cloud-serverless' },
27+
{ pattern: /^content\/influxdb3\/clustered\//, product: 'clustered' },
28+
{ pattern: /^content\/influxdb3\/explorer\//, product: 'explorer' },
29+
{ pattern: /^content\/influxdb\/cloud\//, product: 'cloud' },
30+
{ pattern: /^content\/influxdb\/v2\//, product: 'v2' },
31+
{ pattern: /^content\/influxdb\/v1\//, product: 'v1' },
32+
{ pattern: /^content\/telegraf\//, product: 'telegraf' },
33+
];
34+
35+
/**
36+
* Extract product identifier from a content file path
37+
* @param {string} filePath - Content file path
38+
* @returns {string|null} Product identifier or null
39+
*/
40+
function getProductFromPath(filePath) {
41+
for (const { pattern, product } of PRODUCT_PATTERNS) {
42+
if (pattern.test(filePath)) {
43+
return product;
44+
}
45+
}
46+
return null;
47+
}
48+
49+
/**
50+
* Main function
51+
*/
52+
async function main() {
53+
// Read changed files from stdin
54+
const input = await new Promise((resolve) => {
55+
let data = '';
56+
process.stdin.setEncoding('utf8');
57+
process.stdin.on('data', (chunk) => (data += chunk));
58+
process.stdin.on('end', () => resolve(data));
59+
60+
// Handle case where stdin is empty/closed immediately
61+
if (process.stdin.isTTY) {
62+
resolve('');
63+
}
64+
});
65+
66+
const changedFiles = input
67+
.trim()
68+
.split('\n')
69+
.filter((f) => f && f.endsWith('.md'));
70+
71+
if (changedFiles.length === 0) {
72+
console.log(JSON.stringify({ products: [], files: [] }));
73+
process.exit(0);
74+
}
75+
76+
// Expand shared content changes to find all affected pages
77+
const verbose = process.env.VERBOSE === 'true';
78+
const expandedFiles = expandSharedContentChanges(changedFiles, { verbose });
79+
80+
// Extract unique products from expanded file list
81+
const products = new Set();
82+
for (const file of expandedFiles) {
83+
const product = getProductFromPath(file);
84+
if (product) {
85+
products.add(product);
86+
}
87+
}
88+
89+
// Output JSON result
90+
const result = {
91+
products: Array.from(products).sort(),
92+
files: expandedFiles.sort(),
93+
};
94+
95+
console.log(JSON.stringify(result));
96+
}
97+
98+
main().catch((err) => {
99+
console.error('Error:', err.message);
100+
process.exit(1);
101+
});

0 commit comments

Comments
 (0)