refactor(ci): use shared resolve-shared-content.sh script

- Replace Node.js detect-test-products.js with shell-based approach
- Add .github/scripts/resolve-shared-content.sh (from docs-v2-jts-vale-ci)
- Remove Node.js setup step from detect-changes job
- No external dependencies required for shared content resolution
copilot/sub-pr-6810-again
Jason Stirnaman 2026-02-11 18:22:27 -06:00
parent b5497b43e0
commit b4e4e37099
3 changed files with 93 additions and 117 deletions

45
.github/scripts/resolve-shared-content.sh vendored Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# Resolve shared content files to their consuming product pages.
#
# Usage:
# echo "content/shared/foo.md" | ./resolve-shared-content.sh
# ./resolve-shared-content.sh < changed_files.txt
# ./resolve-shared-content.sh changed_files.txt
#
# For shared files (content/shared/*), finds all pages with matching
# `source:` frontmatter and outputs those instead. Non-shared files
# pass through unchanged.
set -euo pipefail
# Read input from file argument or stdin
if [[ $# -gt 0 && -f "$1" ]]; then
INPUT=$(cat "$1")
else
INPUT=$(cat)
fi
# Process each file
while IFS= read -r file; do
[[ -z "$file" ]] && continue
if [[ "$file" == content/shared/* ]]; then
# Extract the shared path portion (e.g., /shared/influxdb3-cli/foo.md)
SHARED_PATH="${file#content}"
# Find all files that source this shared content
# The source frontmatter looks like: source: /shared/path/to/file.md
CONSUMERS=$(grep -rl "^source: ${SHARED_PATH}$" content/ 2>/dev/null | grep -v '^content/shared/' || true)
if [[ -n "$CONSUMERS" ]]; then
echo "$CONSUMERS"
else
# No consumers found - output the shared file itself
# (Vale can still lint it with default config)
echo "$file"
fi
else
# Non-shared file - pass through
echo "$file"
fi
done <<< "$INPUT" | sort -u

View File

@ -52,12 +52,6 @@ jobs:
with:
fetch-depth: 0
- name: Setup Node.js
if: github.event_name == 'pull_request'
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Analyze changes and determine products
id: check
run: |
@ -144,25 +138,63 @@ jobs:
echo "📝 Changed content files:"
echo "$CHANGED_FILES"
# Use Node.js script to detect products (handles shared content resolution)
# The script expands shared content changes to find all affected product pages
RESULT=$(echo "$CHANGED_FILES" | node scripts/ci/detect-test-products.js)
# Resolve shared content to consuming product pages
RESOLVED_FILES=$(echo "$CHANGED_FILES" | ./.github/scripts/resolve-shared-content.sh)
echo "📂 Resolved files (after shared content expansion):"
echo "$RESOLVED_FILES"
PRODUCTS_JSON=$(echo "$RESULT" | jq -c '.products')
FILES_JSON=$(echo "$RESULT" | jq -c '.files')
# Extract products from resolved file paths
PRODUCTS=()
while IFS= read -r file; do
case "$file" in
content/influxdb3/core/*)
[[ ! " ${PRODUCTS[*]} " =~ " influxdb3_core " ]] && PRODUCTS+=("influxdb3_core")
;;
content/influxdb3/enterprise/*)
[[ ! " ${PRODUCTS[*]} " =~ " influxdb3_enterprise " ]] && PRODUCTS+=("influxdb3_enterprise")
;;
content/influxdb3/cloud-dedicated/*)
[[ ! " ${PRODUCTS[*]} " =~ " cloud-dedicated " ]] && PRODUCTS+=("cloud-dedicated")
;;
content/influxdb3/cloud-serverless/*)
[[ ! " ${PRODUCTS[*]} " =~ " cloud-serverless " ]] && PRODUCTS+=("cloud-serverless")
;;
content/influxdb3/clustered/*)
[[ ! " ${PRODUCTS[*]} " =~ " clustered " ]] && PRODUCTS+=("clustered")
;;
content/influxdb3/explorer/*)
[[ ! " ${PRODUCTS[*]} " =~ " explorer " ]] && PRODUCTS+=("explorer")
;;
content/influxdb/cloud/*)
[[ ! " ${PRODUCTS[*]} " =~ " cloud " ]] && PRODUCTS+=("cloud")
;;
content/influxdb/v2/*)
[[ ! " ${PRODUCTS[*]} " =~ " v2 " ]] && PRODUCTS+=("v2")
;;
content/influxdb/v1/*)
[[ ! " ${PRODUCTS[*]} " =~ " v1 " ]] && PRODUCTS+=("v1")
;;
content/telegraf/*)
[[ ! " ${PRODUCTS[*]} " =~ " telegraf " ]] && PRODUCTS+=("telegraf")
;;
esac
done <<< "$RESOLVED_FILES"
# Check if we got any products
PRODUCT_COUNT=$(echo "$PRODUCTS_JSON" | jq 'length')
if [[ "$PRODUCT_COUNT" -eq 0 ]]; then
# If no products detected, use default group
if [[ ${#PRODUCTS[@]} -eq 0 ]]; then
echo "📦 No specific products detected - using default group"
PRODUCTS_JSON=$(printf '%s\n' "${DEFAULT_PRODUCTS[@]}" | jq -R . | jq -s -c .)
PRODUCTS=("${DEFAULT_PRODUCTS[@]}")
fi
# Convert to JSON array
PRODUCTS_JSON=$(printf '%s\n' "${PRODUCTS[@]}" | jq -R . | jq -s -c .)
FILES_JSON=$(echo "$RESOLVED_FILES" | jq -R . | jq -s -c .)
echo "test-products=$PRODUCTS_JSON" >> $GITHUB_OUTPUT
echo "suggested-products=$PRODUCTS_JSON" >> $GITHUB_OUTPUT
echo "affected-files=$FILES_JSON" >> $GITHUB_OUTPUT
echo "📋 Suggested products for testing: $(echo "$PRODUCTS_JSON" | jq -r 'join(", ")')"
echo "📋 Suggested products for testing: ${PRODUCTS[*]}"
# Informational job for PRs - suggests tests but doesn't run them
suggest-tests:

View File

@ -1,101 +0,0 @@
#!/usr/bin/env node
/**
* Detect which products need testing based on changed content files.
*
* Usage:
* echo "content/influxdb3/core/page.md" | node scripts/ci/detect-test-products.js
* node scripts/ci/detect-test-products.js < changed-files.txt
*
* Output (JSON):
* {"products":["influxdb3_core","telegraf"],"files":["content/influxdb3/core/page.md",...]}
*
* This script:
* 1. Reads changed file paths from stdin (one per line)
* 2. Expands shared content changes to find all affected product pages
* 3. Extracts unique products from the affected file paths
* 4. Outputs JSON with products array and expanded files array
*/
import { expandSharedContentChanges } from '../lib/content-utils.js';
// Product path mappings
const PRODUCT_PATTERNS = [
{ pattern: /^content\/influxdb3\/core\//, product: 'influxdb3_core' },
{ pattern: /^content\/influxdb3\/enterprise\//, product: 'influxdb3_enterprise' },
{ pattern: /^content\/influxdb3\/cloud-dedicated\//, product: 'cloud-dedicated' },
{ pattern: /^content\/influxdb3\/cloud-serverless\//, product: 'cloud-serverless' },
{ pattern: /^content\/influxdb3\/clustered\//, product: 'clustered' },
{ pattern: /^content\/influxdb3\/explorer\//, product: 'explorer' },
{ pattern: /^content\/influxdb\/cloud\//, product: 'cloud' },
{ pattern: /^content\/influxdb\/v2\//, product: 'v2' },
{ pattern: /^content\/influxdb\/v1\//, product: 'v1' },
{ pattern: /^content\/telegraf\//, product: 'telegraf' },
];
/**
* Extract product identifier from a content file path
* @param {string} filePath - Content file path
* @returns {string|null} Product identifier or null
*/
function getProductFromPath(filePath) {
for (const { pattern, product } of PRODUCT_PATTERNS) {
if (pattern.test(filePath)) {
return product;
}
}
return null;
}
/**
* Main function
*/
async function main() {
// Read changed files from stdin
const input = await new Promise((resolve) => {
let data = '';
process.stdin.setEncoding('utf8');
process.stdin.on('data', (chunk) => (data += chunk));
process.stdin.on('end', () => resolve(data));
// Handle case where stdin is empty/closed immediately
if (process.stdin.isTTY) {
resolve('');
}
});
const changedFiles = input
.trim()
.split('\n')
.filter((f) => f && f.endsWith('.md'));
if (changedFiles.length === 0) {
console.log(JSON.stringify({ products: [], files: [] }));
process.exit(0);
}
// Expand shared content changes to find all affected pages
const verbose = process.env.VERBOSE === 'true';
const expandedFiles = expandSharedContentChanges(changedFiles, { verbose });
// Extract unique products from expanded file list
const products = new Set();
for (const file of expandedFiles) {
const product = getProductFromPath(file);
if (product) {
products.add(product);
}
}
// Output JSON result
const result = {
products: Array.from(products).sort(),
files: expandedFiles.sort(),
};
console.log(JSON.stringify(result));
}
main().catch((err) => {
console.error('Error:', err.message);
process.exit(1);
});