diff --git a/.ci/vale/vale.sh b/.ci/vale/vale.sh index e0f385f58..47ac7c48b 100755 --- a/.ci/vale/vale.sh +++ b/.ci/vale/vale.sh @@ -13,7 +13,7 @@ set -euo pipefail # --minAlertLevel=suggestion \ # --config=content/influxdb/cloud-dedicated/.vale.ini -VALE_VERSION="3.13.1" +VALE_VERSION="3.14.1" VALE_MAJOR_MIN=3 if command -v vale &>/dev/null; then diff --git a/.claude/agents/influxdb1-tech-writer.md b/.claude/agents/influxdb1-tech-writer.md index 2ec900b83..a65681fed 100644 --- a/.claude/agents/influxdb1-tech-writer.md +++ b/.claude/agents/influxdb1-tech-writer.md @@ -61,6 +61,15 @@ You are an expert InfluxDB v1 technical writer with deep knowledge of InfluxData 5. **Apply Standards:** Ensure compliance with style guidelines and documentation conventions 6. **Cross-Reference:** Verify consistency with related documentation and product variants +## Release Documentation Workflow + +**Always create separate PRs for OSS v1 and Enterprise v1 releases.** + +- **OSS v1:** Publish immediately when the release tag is available on GitHub (`https://github.com/influxdata/influxdb/releases/tag/v1.x.x`). +- **Enterprise v1:** Publish only after the release artifact is generally available (GA) in the InfluxData portal. Create the PR as a **draft** until the v1 codeowner signals readiness (e.g., applies a release label). +- **`data/products.yml`:** Split version bumps per product. The OSS PR bumps `influxdb.latest_patches.v1`; the Enterprise PR bumps `enterprise_influxdb.latest_patches.v1`. +- **PR template:** Use `.github/pull_request_template/influxdb_v1_release.md` and select the appropriate release type (OSS or Enterprise). + ## Quality Assurance - All code examples must be testable and include proper pytest-codeblocks annotations diff --git a/.claude/commands/prepare-release-notes.md b/.claude/commands/prepare-release-notes.md index e3e241fd2..c51350493 100644 --- a/.claude/commands/prepare-release-notes.md +++ b/.claude/commands/prepare-release-notes.md @@ -222,6 +222,29 @@ influxdb3_core, influxdb3_enterprise, telegraf /influxdb3/core, /influxdb3/enterprise, /telegraf ``` +## v1 Release Workflow + +**InfluxDB v1 releases require separate PRs for OSS and Enterprise.** + +1. **OSS PR** — publish immediately when the GitHub release tag is available. +2. **Enterprise PR** — create as a draft; merge only after the v1 codeowner signals readiness (e.g., applies a release label) and the release artifact is GA in the InfluxData portal. + +Each PR should bump only its own product version in `data/products.yml`: +- OSS: `influxdb > latest_patches > v1` +- Enterprise: `enterprise_influxdb > latest_patches > v1` + +Use the PR template `.github/pull_request_template/influxdb_v1_release.md` and select the appropriate release type. + +### Examples for v1 + +```bash +# Generate OSS v1 release notes +docs release-notes v1.12.2 v1.12.3 --repos ~/github/influxdata/influxdb + +# Generate Enterprise v1 release notes (separate PR) +# Use the Enterprise changelog at https://dl.influxdata.com/enterprise/nightlies/master/CHANGELOG.md +``` + ## Related - **docs-cli-workflow** skill - When to use CLI tools diff --git a/.claude/skills/content-editing/SKILL.md b/.claude/skills/content-editing/SKILL.md index 863b5c101..d34b1bd6b 100644 --- a/.claude/skills/content-editing/SKILL.md +++ b/.claude/skills/content-editing/SKILL.md @@ -364,7 +364,7 @@ The documentation MCP server is hosted at `https://influxdb-docs.mcp.kapa.ai`— Already configured in [`.mcp.json`](/.mcp.json). Two server entries are available: - **`influxdb-docs`** (API key) — Set `INFLUXDATA_DOCS_KAPA_API_KEY` env var. 60 req/min. -- **`influxdb-docs-oauth`** (OAuth) — No setup. Authenticates via Google on first use. 40 req/hr, 200 req/day. +- **`influxdb-docs-oauth`** (OAuth) — No setup. Authenticates via Google or GitHub on first use. 40 req/hr, 200 req/day. ### Available Tool @@ -534,7 +534,7 @@ touch content/influxdb3/enterprise/path/to/file.md **Troubleshooting steps:** - **API key auth** (`influxdb-docs`): Verify `INFLUXDATA_DOCS_KAPA_API_KEY` is set. Rate limit: 60 req/min. -- **OAuth auth** (`influxdb-docs-oauth`): Sign in with Google on first use. Rate limits: 40 req/hr, 200 req/day. +- **OAuth auth** (`influxdb-docs-oauth`): Sign in with Google or GitHub on first use. Rate limits: 40 req/hr, 200 req/day. - Verify your network allows connections to `*.kapa.ai` - Check if you've exceeded rate limits (wait and retry) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..c1965c216 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.github/workflows/*.lock.yml linguist-generated=true merge=ours \ No newline at end of file diff --git a/.github/pull_request_template/influxdb_v1_release.md b/.github/pull_request_template/influxdb_v1_release.md index cc341db77..cbfe0e6c4 100644 --- a/.github/pull_request_template/influxdb_v1_release.md +++ b/.github/pull_request_template/influxdb_v1_release.md @@ -1,27 +1,37 @@ ## InfluxDB v1 Release Documentation -**Release Version:** v1.x.x -**Release Type:** [ ] OSS [ ] Enterprise [ ] Both +**Release Version:** v1.x.x +**Release Type:** [ ] OSS [ ] Enterprise + +> [!Important] +> **Always create separate PRs for OSS and Enterprise releases.** +> OSS can publish immediately when the GitHub release tag is available. +> Enterprise must wait until the release artifact is GA in the InfluxData portal. +> Never combine both products in a single release PR. ### Description Brief description of the release and documentation changes. +### Pre-merge Gate (Enterprise only) +- [ ] **Confirm release artifact is GA in the InfluxData portal** +- [ ] **v1 codeowner has signaled readiness** (e.g., applied a release label) + ### Release Documentation Checklist #### Release Notes - [ ] Generate release notes from changelog - - [ ] OSS: Use commit messages from GitHub release tag `https://github.com/influxdata/influxdb/releases/tag/v1.x.x` - - [ ] Enterprise: Use `https://dl.influxdata.com/enterprise/nightlies/master/CHANGELOG.md` - - [ ] **Note**: For Enterprise releases, include important updates, features, and fixes from the corresponding OSS tag + - OSS: Use commit messages from GitHub release tag `https://github.com/influxdata/influxdb/releases/tag/v1.x.x` + - Enterprise: Use `https://dl.influxdata.com/enterprise/nightlies/master/CHANGELOG.md` + - **Note**: For Enterprise releases, include important updates, features, and fixes from the corresponding OSS tag - [ ] Update release notes in appropriate location - - [ ] OSS: `/content/influxdb/v1/about_the_project/releasenotes-changelog.md` - - [ ] Enterprise: `/content/enterprise_influxdb/v1/about-the-project/release-notes.md` + - OSS: `content/influxdb/v1/about_the_project/release-notes.md` + - Enterprise: `content/enterprise_influxdb/v1/about-the-project/release-notes.md` - [ ] Ensure release notes follow documentation formatting standards #### Version Updates -- [ ] Update patch version in `/data/products.yml` - - [ ] OSS: `influxdb > v1 > latest` - - [ ] Enterprise: `enterprise_influxdb > v1 > latest` +- [ ] Update patch version in `data/products.yml` (**only for this product**) + - OSS: `influxdb > latest_patches > v1` + - Enterprise: `enterprise_influxdb > latest_patches > v1` - [ ] Update version references in documentation - [ ] Installation guides - [ ] Docker documentation @@ -37,8 +47,9 @@ Brief description of the release and documentation changes. #### Testing - [ ] Build documentation locally and verify changes render correctly - [ ] Test all updated links -- [ ] Run link validation: `yarn test:links content/influxdb/v1/**/*.md` -- [ ] Run link validation: `yarn test:links content/enterprise_influxdb/v1/**/*.md` +- [ ] Run link validation for the product being released: + - OSS: `yarn test:links content/influxdb/v1/**/*.md` + - Enterprise: `yarn test:links content/enterprise_influxdb/v1/**/*.md` ### Related Resources - DAR Issue: # @@ -50,6 +61,3 @@ Brief description of the release and documentation changes. - [ ] Verify documentation is deployed to production - [ ] Announce in #docs channel - [ ] Close related DAR issue(s) - ---- -**Note:** For Enterprise releases, ensure you have access to the Enterprise changelog and coordinate with the release team for timing. \ No newline at end of file diff --git a/.github/scripts/detect-preview-pages.js b/.github/scripts/detect-preview-pages.js index 12e255ac4..76ab1eac9 100644 --- a/.github/scripts/detect-preview-pages.js +++ b/.github/scripts/detect-preview-pages.js @@ -35,10 +35,10 @@ if (!/^origin\/[a-zA-Z0-9._\/-]+$/.test(BASE_REF)) { */ function getAllChangedFiles() { try { - const output = execSync( - `git diff --name-only ${BASE_REF}...HEAD`, - { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] } - ); + const output = execSync(`git diff --name-only ${BASE_REF}...HEAD`, { + encoding: 'utf-8', + stdio: ['pipe', 'pipe', 'pipe'], + }); return output.trim().split('\n').filter(Boolean); } catch (err) { console.error(`Error detecting changes: ${err.message}`); @@ -53,11 +53,13 @@ function getAllChangedFiles() { */ function categorizeChanges(files) { return { - content: files.filter(f => f.startsWith('content/') && f.endsWith('.md')), - layouts: files.filter(f => f.startsWith('layouts/')), - assets: files.filter(f => f.startsWith('assets/')), - data: files.filter(f => f.startsWith('data/')), - apiDocs: files.filter(f => f.startsWith('api-docs/') || f.startsWith('openapi/')), + content: files.filter((f) => f.startsWith('content/') && f.endsWith('.md')), + layouts: files.filter((f) => f.startsWith('layouts/')), + assets: files.filter((f) => f.startsWith('assets/')), + data: files.filter((f) => f.startsWith('data/')), + apiDocs: files.filter( + (f) => f.startsWith('api-docs/') || f.startsWith('openapi/') + ), }; } @@ -127,7 +129,7 @@ function main() { const htmlPaths = mapContentToPublic(expandedContent, 'public'); // Convert HTML paths to URL paths - pagesToDeploy = Array.from(htmlPaths).map(htmlPath => { + pagesToDeploy = Array.from(htmlPaths).map((htmlPath) => { return '/' + htmlPath.replace('public/', '').replace('/index.html', '/'); }); console.log(` Found ${pagesToDeploy.length} affected pages\n`); @@ -135,34 +137,53 @@ function main() { // Strategy 2: Layout/asset changes - parse URLs from PR body if (hasLayoutChanges) { - console.log('🎨 Layout/asset changes detected, checking PR description for URLs...'); + console.log( + '🎨 Layout/asset changes detected, checking PR description for URLs...' + ); + + // Auto-detect home page when the root template changes + if (changes.layouts.includes('layouts/index.html')) { + pagesToDeploy = [...new Set([...pagesToDeploy, '/'])]; + console.log( + ' 🏠 Home page template (layouts/index.html) changed - auto-adding / to preview pages' + ); + } + const prUrls = extractDocsUrls(PR_BODY); if (prUrls.length > 0) { console.log(` Found ${prUrls.length} URLs in PR description`); // Merge with content pages (deduplicate) pagesToDeploy = [...new Set([...pagesToDeploy, ...prUrls])]; - } else if (changes.content.length === 0) { - // No content changes AND no URLs specified - need author input - console.log(' ⚠️ No URLs found in PR description - author input needed'); + } else if (pagesToDeploy.length === 0) { + // No content changes, no auto-detected pages, and no URLs specified - need author input + console.log( + ' ⚠️ No URLs found in PR description - author input needed' + ); setOutput('pages-to-deploy', '[]'); setOutput('has-layout-changes', 'true'); setOutput('needs-author-input', 'true'); - setOutput('change-summary', 'Layout/asset changes detected - please specify pages to preview'); + setOutput( + 'change-summary', + 'Layout/asset changes detected - please specify pages to preview' + ); return; } } // Apply page limit if (pagesToDeploy.length > MAX_PAGES) { - console.log(`⚠️ Limiting preview to ${MAX_PAGES} pages (found ${pagesToDeploy.length})`); + console.log( + `⚠️ Limiting preview to ${MAX_PAGES} pages (found ${pagesToDeploy.length})` + ); pagesToDeploy = pagesToDeploy.slice(0, MAX_PAGES); } // Generate summary - const summary = pagesToDeploy.length > 0 - ? `${pagesToDeploy.length} page(s) will be previewed` - : 'No pages to preview'; + const summary = + pagesToDeploy.length > 0 + ? `${pagesToDeploy.length} page(s) will be previewed` + : 'No pages to preview'; console.log(`\n✅ ${summary}`); diff --git a/.github/scripts/parse-pr-urls.js b/.github/scripts/parse-pr-urls.js index 7e844fe14..58205b3b1 100644 --- a/.github/scripts/parse-pr-urls.js +++ b/.github/scripts/parse-pr-urls.js @@ -63,6 +63,9 @@ function isValidUrlPath(path) { // Must start with / if (!path.startsWith('/')) return false; + // Allow root path (docs home page at /) + if (path === '/') return true; + // Must start with known product prefix (loaded from products.yml) const validPrefixes = PRODUCT_NAMESPACES.map((ns) => `/${ns}/`); @@ -101,7 +104,8 @@ export function extractDocsUrls(text) { // Pattern 1: Full production URLs // https://docs.influxdata.com/influxdb3/core/get-started/ - const prodUrlPattern = /https?:\/\/docs\.influxdata\.com(\/[^\s)\]>"']+)/g; + // https://docs.influxdata.com/ (home page) + const prodUrlPattern = /https?:\/\/docs\.influxdata\.com(\/[^\s)\]>"']*)/g; let match; while ((match = prodUrlPattern.exec(text)) !== null) { const path = normalizeUrlPath(match[1]); @@ -112,7 +116,8 @@ export function extractDocsUrls(text) { // Pattern 2: Localhost dev URLs // http://localhost:1313/influxdb3/core/ - const localUrlPattern = /https?:\/\/localhost:\d+(\/[^\s)\]>"']+)/g; + // http://localhost:1313/ (home page) + const localUrlPattern = /https?:\/\/localhost:\d+(\/[^\s)\]>"']*)/g; while ((match = localUrlPattern.exec(text)) !== null) { const path = normalizeUrlPath(match[1]); if (isValidUrlPath(path)) { diff --git a/.github/scripts/resolve-review-urls.js b/.github/scripts/resolve-review-urls.js index 8869555d7..886679d35 100644 --- a/.github/scripts/resolve-review-urls.js +++ b/.github/scripts/resolve-review-urls.js @@ -10,6 +10,7 @@ */ import { appendFileSync } from 'fs'; +import { execSync } from 'child_process'; import { getChangedContentFiles, mapContentToPublic, @@ -27,11 +28,33 @@ if (!/^origin\/[a-zA-Z0-9._/-]+$/.test(BASE_REF)) { const changed = getChangedContentFiles(BASE_REF); const htmlPaths = mapContentToPublic(changed, 'public'); -const urls = Array.from(htmlPaths) +const contentUrls = Array.from(htmlPaths) .sort() .map((p) => '/' + p.replace(/^public\//, '').replace(/\/index\.html$/, '/')) .slice(0, MAX_PAGES); +// Check if the home page template changed (layouts/index.html → /) +let homePageUrls = []; +try { + const homePageChanged = execSync( + `git diff --name-only ${BASE_REF}...HEAD -- layouts/index.html`, + { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] } + ).trim(); + if (homePageChanged) { + homePageUrls = ['/']; + console.log( + 'Home page template (layouts/index.html) changed - adding / to review URLs' + ); + } +} catch { + // Ignore errors - fall back to content-only URLs +} + +const urls = [...new Set([...homePageUrls, ...contentUrls])].slice( + 0, + MAX_PAGES +); + appendFileSync(GITHUB_OUTPUT, `urls=${JSON.stringify(urls)}\n`); appendFileSync(GITHUB_OUTPUT, `url-count=${urls.length}\n`); diff --git a/.github/scripts/test-parse-pr-urls.js b/.github/scripts/test-parse-pr-urls.js index 6470122ec..36fd98d7c 100644 --- a/.github/scripts/test-parse-pr-urls.js +++ b/.github/scripts/test-parse-pr-urls.js @@ -145,7 +145,11 @@ test('Special characters: backticks are delimiters', () => { // This prevents command substitution injection const text = '/influxdb3/`whoami`/'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/'], 'Should truncate at backtick delimiter'); + assertEquals( + result, + ['/influxdb3/'], + 'Should truncate at backtick delimiter' + ); }); test('Special characters: single quotes truncate at extraction', () => { @@ -257,31 +261,51 @@ test('Normalization: removes query string', () => { test('Normalization: strips wildcard from path', () => { const text = '/influxdb3/enterprise/*'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/enterprise/'], 'Should strip wildcard character'); + assertEquals( + result, + ['/influxdb3/enterprise/'], + 'Should strip wildcard character' + ); }); test('Normalization: strips wildcard in middle of path', () => { const text = '/influxdb3/*/admin/'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/admin/'], 'Should strip wildcard from middle of path'); + assertEquals( + result, + ['/influxdb3/admin/'], + 'Should strip wildcard from middle of path' + ); }); test('Normalization: strips multiple wildcards', () => { const text = '/influxdb3/*/admin/*'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/admin/'], 'Should strip all wildcard characters'); + assertEquals( + result, + ['/influxdb3/admin/'], + 'Should strip all wildcard characters' + ); }); test('Wildcard in markdown-style notation', () => { const text = '**InfluxDB 3 Enterprise pages** (`/influxdb3/enterprise/*`)'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/enterprise/'], 'Should extract and normalize path with wildcard in backticks'); + assertEquals( + result, + ['/influxdb3/enterprise/'], + 'Should extract and normalize path with wildcard in backticks' + ); }); test('Wildcard in parentheses', () => { const text = 'Affects pages under (/influxdb3/enterprise/*)'; const result = extractDocsUrls(text); - assertEquals(result, ['/influxdb3/enterprise/'], 'Should extract and normalize path with wildcard in parentheses'); + assertEquals( + result, + ['/influxdb3/enterprise/'], + 'Should extract and normalize path with wildcard in parentheses' + ); }); // Test deduplication @@ -360,6 +384,31 @@ test('BASE_REF: rejects without origin/ prefix', () => { assertEquals(isValid, false, 'Should require origin/ prefix'); }); +// Home page URL support +test('Home page: production URL https://docs.influxdata.com/', () => { + const text = 'Preview: https://docs.influxdata.com/'; + const result = extractDocsUrls(text); + assertEquals(result, ['/'], 'Should extract root path for docs home page'); +}); + +test('Home page: localhost URL http://localhost:1313/', () => { + const text = 'Testing at http://localhost:1313/'; + const result = extractDocsUrls(text); + assertEquals(result, ['/'], 'Should extract root path from localhost URL'); +}); + +test('Home page: relative root path / in text', () => { + // Relative '/' alone is not extractable by the relative pattern (requires product prefix), + // but full URLs with / path are supported + const text = 'https://docs.influxdata.com/ and /influxdb3/core/'; + const result = extractDocsUrls(text); + assertEquals( + result.sort(), + ['/', '/influxdb3/core/'].sort(), + 'Should extract both root path and product path' + ); +}); + // Print summary console.log('\n=== Test Summary ==='); console.log(`Total: ${totalTests}`); diff --git a/.github/workflows/daily-repo-status.lock.yml b/.github/workflows/daily-repo-status.lock.yml new file mode 100644 index 000000000..edc867af7 --- /dev/null +++ b/.github/workflows/daily-repo-status.lock.yml @@ -0,0 +1,1031 @@ +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.61.1). DO NOT EDIT. +# +# To update this file, edit githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11 and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# This workflow creates daily repo status reports. It gathers recent repository +# activity (issues, PRs, discussions, releases, code changes) and generates +# engaging GitHub issues with productivity insights, community highlights, +# and project recommendations. +# +# Source: githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11 +# +# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"82c0ab85cfbd9b16bfb39799060eb64e360b5ea0fe071ce52866b333afe5e4e5","compiler_version":"v0.61.1","strict":true} + +name: "Daily Repo Status" +"on": + schedule: + - cron: "52 7 * * *" + # Friendly format: daily (scattered) + workflow_dispatch: + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}" + +run-name: "Daily Repo Status" + +jobs: + activation: + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }} + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@be0029bbbaeef8c6bea6825f31d9593219b2dc28 # v0.61.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + GH_AW_INFO_VERSION: "" + GH_AW_INFO_AGENT_VERSION: "latest" + GH_AW_INFO_CLI_VERSION: "v0.61.1" + GH_AW_INFO_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]' + GH_AW_INFO_FIREWALL_ENABLED: "true" + GH_AW_INFO_AWF_VERSION: "v0.24.2" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "squid" + GH_AW_COMPILED_STRICT: "true" + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Validate COPILOT_GITHUB_TOKEN secret + id: validate-secret + run: ${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Checkout .github and .agents folders + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_WORKFLOW_FILE: "daily-repo-status.lock.yml" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + bash ${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh + { + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_EOF' + + Tools: create_issue, missing_tool, missing_data, noop + + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_EOF' + + GH_AW_PROMPT_EOF + cat << 'GH_AW_PROMPT_EOF' + {{#runtime-import .github/workflows/daily-repo-status.md}} + GH_AW_PROMPT_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash ${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash ${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: activation + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/aw-prompts/prompt.txt + retention-days: 1 + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + issues: read + pull-requests: read + concurrency: + group: "gh-aw-copilot-${{ github.workflow }}" + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: dailyrepostatus + outputs: + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }} + detection_success: ${{ steps.detection_conclusion.outputs.success }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-inference-error.outputs.inference_access_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@be0029bbbaeef8c6bea6825f31d9593219b2dc28 # v0.61.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + - name: Set runtime paths + run: | + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" >> "$GITHUB_ENV" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" >> "$GITHUB_ENV" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" >> "$GITHUB_ENV" + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash ${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh + - name: Configure gh CLI for GitHub Enterprise + run: bash ${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + (github.event.pull_request) || (github.event.issue.pull_request) + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: ${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh latest + env: + GH_HOST: github.com + - name: Install AWF binary + run: bash ${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh v0.24.2 + - name: Determine automatic lockdown mode for GitHub MCP Server + id: determine-automatic-lockdown + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + with: + script: | + const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash ${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.24.2 ghcr.io/github/gh-aw-firewall/api-proxy:0.24.2 ghcr.io/github/gh-aw-firewall/squid:0.24.2 ghcr.io/github/gh-aw-mcpg:v0.1.17 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine + - name: Write Safe Outputs Config + run: | + mkdir -p ${RUNNER_TEMP}/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF' + {"create_issue":{"max":1},"mentions":{"enabled":false},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + GH_AW_SAFE_OUTPUTS_CONFIG_EOF + - name: Write Safe Outputs Tools + run: | + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF' + { + "description_suffixes": { + "create_issue": " CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"[repo-status] \". Labels [\"report\" \"daily-status\"] will be automatically added." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF + cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF' + { + "create_issue": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "parent": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "temporary_id": { + "type": "string" + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + } + } + GH_AW_SAFE_OUTPUTS_VALIDATION_EOF + node ${RUNNER_TEMP}/gh-aw/actions/generate_safe_outputs_tools.cjs + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash ${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} + GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.17' + + mkdir -p /home/runner/.copilot + cat << GH_AW_MCP_CONFIG_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.32.0", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY", + "repos": "$GITHUB_MCP_GUARD_REPOS" + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_EOF + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Clean git credentials + continue-on-error: true + run: bash ${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.2 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --allow-all-paths --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_VERSION: v0.61.1 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Detect inference access error + id: detect-inference-error + if: always() + continue-on-error: true + run: bash ${RUNNER_TEMP}/gh-aw/actions/detect_inference_access_error.sh + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Append agent step summary + if: always() + run: bash ${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh + - name: Copy Safe Outputs + if: always() + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" + GH_AW_ALLOWED_GITHUB_REFS: "" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: | + # Fix permissions on firewall logs so they can be uploaded as artifacts + # AWF runs with sudo, creating files owned by root + sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true + # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step) + if command -v awf &> /dev/null; then + awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + else + echo 'AWF binary not installed, skipping firewall log summary' + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/agent/ + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + if-no-files-found: ignore + # --- Threat Detection (inline) --- + - name: Check if detection needed + id: detection_guard + if: always() + env: + OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }} + HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }} + run: | + if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then + echo "run_detection=true" >> "$GITHUB_OUTPUT" + echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH" + else + echo "run_detection=false" >> "$GITHUB_OUTPUT" + echo "Detection skipped: no agent outputs or patches to analyze" + fi + - name: Clear MCP configuration for detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + rm -f /tmp/gh-aw/mcp-config/mcp-servers.json + rm -f /home/runner/.copilot/mcp-config.json + rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" + - name: Prepare threat detection files + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection/aw-prompts + cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true + cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true + for f in /tmp/gh-aw/aw-*.patch; do + [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true + done + echo "Prepared threat detection files:" + ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true + - name: Setup threat detection + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + WORKFLOW_NAME: "Daily Repo Status" + WORKFLOW_DESCRIPTION: "This workflow creates daily repo status reports. It gathers recent repository\nactivity (issues, PRs, discussions, releases, code changes) and generates\nengaging GitHub issues with productivity insights, community highlights,\nand project recommendations." + HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs'); + await main(); + - name: Ensure threat-detection directory and log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + run: | + mkdir -p /tmp/gh-aw/threat-detection + touch /tmp/gh-aw/threat-detection/detection.log + - name: Execute GitHub Copilot CLI + if: always() && steps.detection_guard.outputs.run_detection == 'true' + id: detection_agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool shell(cat) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(jq) + # --allow-tool shell(ls) + # --allow-tool shell(tail) + # --allow-tool shell(wc) + timeout-minutes: 20 + run: | + set -o pipefail + touch /tmp/gh-aw/agent-step-summary.md + # shellcheck disable=SC1003 + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.2 --skip-pull --enable-api-proxy \ + -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + GH_AW_PHASE: detection + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_VERSION: v0.61.1 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_AUTHOR_NAME: github-actions[bot] + GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com + GIT_COMMITTER_NAME: github-actions[bot] + XDG_CONFIG_HOME: /home/runner + - name: Parse threat detection results + id: parse_detection_results + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs'); + await main(); + - name: Upload threat detection log + if: always() && steps.detection_guard.outputs.run_detection == 'true' + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: detection + path: /tmp/gh-aw/threat-detection/detection.log + if-no-files-found: ignore + - name: Set detection conclusion + id: detection_conclusion + if: always() + env: + RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }} + DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }} + run: | + if [[ "$RUN_DETECTION" != "true" ]]; then + echo "conclusion=skipped" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection was not needed, marking as skipped" + elif [[ "$DETECTION_SUCCESS" == "true" ]]; then + echo "conclusion=success" >> "$GITHUB_OUTPUT" + echo "success=true" >> "$GITHUB_OUTPUT" + echo "Detection passed successfully" + else + echo "conclusion=failure" >> "$GITHUB_OUTPUT" + echo "success=false" >> "$GITHUB_OUTPUT" + echo "Detection found issues" + fi + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: (always()) && ((needs.agent.result != 'skipped') || (needs.activation.outputs.lockdown_check_failed == 'true')) + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + concurrency: + group: "gh-aw-conclusion-daily-repo-status" + cancel-in-progress: false + outputs: + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@be0029bbbaeef8c6bea6825f31d9593219b2dc28 # v0.61.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV" + - name: Process No-Op Messages + id: noop + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/9a76aba267225767b9b2e1623188d11ed9b58f11/workflows/daily-repo-status.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/noop.cjs'); + await main(); + - name: Record Missing Tool + id: missing_tool + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/9a76aba267225767b9b2e1623188d11ed9b58f11/workflows/daily-repo-status.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Handle Agent Failure + id: handle_agent_failure + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/9a76aba267225767b9b2e1623188d11ed9b58f11/workflows/daily-repo-status.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "daily-repo-status" + GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }} + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + - name: Handle No-Op Message + id: handle_noop_message + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/9a76aba267225767b9b2e1623188d11ed9b58f11/workflows/daily-repo-status.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + + safe_outputs: + needs: agent + if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + timeout-minutes: 15 + env: + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/daily-repo-status" + GH_AW_ENGINE_ID: "copilot" + GH_AW_WORKFLOW_ID: "daily-repo-status" + GH_AW_WORKFLOW_NAME: "Daily Repo Status" + GH_AW_WORKFLOW_SOURCE: "githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/githubnext/agentics/tree/9a76aba267225767b9b2e1623188d11ed9b58f11/workflows/daily-repo-status.md" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_issue_number: ${{ steps.process_safe_outputs.outputs.created_issue_number }} + created_issue_url: ${{ steps.process_safe_outputs.outputs.created_issue_url }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@be0029bbbaeef8c6bea6825f31d9593219b2dc28 # v0.61.1 + with: + destination: ${{ runner.temp }}/gh-aw/actions + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV" + - name: Configure GH_HOST for enterprise compatibility + shell: bash + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 + env: + GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_issue\":{\"close_older_issues\":true,\"labels\":[\"report\",\"daily-status\"],\"max\":1,\"title_prefix\":\"[repo-status] \"},\"missing_data\":{},\"missing_tool\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Output Items Manifest + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: safe-output-items + path: /tmp/safe-output-items.jsonl + if-no-files-found: warn + diff --git a/.github/workflows/daily-repo-status.md b/.github/workflows/daily-repo-status.md new file mode 100644 index 000000000..bfb75e29c --- /dev/null +++ b/.github/workflows/daily-repo-status.md @@ -0,0 +1,58 @@ +--- +description: | + This workflow creates daily repo status reports. It gathers recent repository + activity (issues, PRs, discussions, releases, code changes) and generates + engaging GitHub issues with productivity insights, community highlights, + and project recommendations. + +on: + schedule: daily + workflow_dispatch: + +permissions: + contents: read + issues: read + pull-requests: read + +network: defaults + +tools: + github: + # If in a public repo, setting `lockdown: false` allows + # reading issues, pull requests and comments from 3rd-parties + # If in a private repo this has no particular effect. + lockdown: false + +safe-outputs: + mentions: false + allowed-github-references: [] + create-issue: + title-prefix: "[repo-status] " + labels: [report, daily-status] + close-older-issues: true +source: githubnext/agentics/workflows/daily-repo-status.md@9a76aba267225767b9b2e1623188d11ed9b58f11 +engine: copilot +--- + +# Daily Repo Status + +Create an upbeat daily status report for the repo as a GitHub issue. + +## What to include + +- Recent repository activity (issues, PRs, discussions, releases, code changes) +- Progress tracking, goal reminders and highlights +- Project status and recommendations +- Actionable next steps for maintainers + +## Style + +- Be positive, encouraging, and helpful 🌟 +- Use emojis moderately for engagement +- Keep it concise - adjust length based on actual activity + +## Process + +1. Gather recent activity from the repository +2. Study the repository, its issues and its pull requests +3. Create a new GitHub issue with your findings and insights \ No newline at end of file diff --git a/.mcp.json b/.mcp.json index f53854090..f18a0f326 100644 --- a/.mcp.json +++ b/.mcp.json @@ -11,7 +11,7 @@ } }, "influxdb-docs-oauth": { - "comment": "Hosted InfluxDB documentation search (OAuth). No API key needed--authenticates via Google OAuth on first use. Rate limits: 40 req/hr, 200 req/day.", + "comment": "Hosted InfluxDB documentation search (OAuth). No API key needed--authenticates via Google or GitHub OAuth on first use. Rate limits: 40 req/hr, 200 req/day.", "type": "sse", "url": "https://influxdb-docs.mcp.kapa.ai" }, diff --git a/assets/js/code-controls.js b/assets/js/code-controls.js index 59ca50ec7..d8ce5a9f9 100644 --- a/assets/js/code-controls.js +++ b/assets/js/code-controls.js @@ -7,10 +7,11 @@ function initialize() { var appendHTML = `
- -
`; @@ -27,12 +28,17 @@ function initialize() { // Click outside of the code-controls to close them $(document).click(function () { - $('.code-controls').removeClass('open'); + $('.code-controls.open').each(function () { + $(this).removeClass('open'); + $(this).find('.code-controls-toggle').attr('aria-expanded', 'false'); + }); }); // Click the code controls toggle to open code controls $('.code-controls-toggle').click(function () { - $(this).parent('.code-controls').toggleClass('open'); + var $controls = $(this).parent('.code-controls'); + var isOpen = $controls.toggleClass('open').hasClass('open'); + $(this).attr('aria-expanded', String(isOpen)); }); // Stop event propagation for clicks inside of the code-controls div @@ -235,6 +241,34 @@ function initialize() { return info; } + ////////////////////////////////// ASK AI //////////////////////////////////// + + // Build a query from the code block and open Kapa via the ask-ai-open contract + $('.ask-ai-code').click(function () { + var codeElement = $(this) + .closest('.code-controls') + .prevAll('pre:has(code)')[0]; + if (!codeElement) return; + + var code = codeElement.innerText.trim(); + // Use the data-ask-ai-query attribute if the template provided one, + // otherwise build a generic query from the code content + var query = + $(codeElement).attr('data-ask-ai-query') || + 'Explain this code:\n```\n' + code.substring(0, 500) + '\n```'; + + // Delegate to the global ask-ai-open handler by synthesizing a click. + // Use native .click() instead of jQuery .trigger() so the event + // reaches the native document.addEventListener in ask-ai-trigger.js. + // No href — prevents scroll-to-top when the native click fires. + var triggerEl = document.createElement('a'); + triggerEl.className = 'ask-ai-open'; + triggerEl.dataset.query = query; + document.body.appendChild(triggerEl); + triggerEl.click(); + triggerEl.remove(); + }); + /////////////////////////////// FULL WINDOW CODE /////////////////////////////// /* diff --git a/assets/js/components/tc-dynamic-values.js b/assets/js/components/tc-dynamic-values.js new file mode 100644 index 000000000..4c99171a1 --- /dev/null +++ b/assets/js/components/tc-dynamic-values.js @@ -0,0 +1,92 @@ +/** + * Highlights Telegraf Controller dynamic values in code blocks. + * + * Wraps three pattern types in styled elements: + * - Parameters: &{name} or &{name:default} + * - Environment variables: ${VAR_NAME} + * - Secrets: @{store:secret_name} + * + * Applied to code blocks with class="tc-dynamic-values" via + * the data-component="tc-dynamic-values" attribute set by + * the render-codeblock hook. + */ + +const PATTERNS = [ + { regex: /&\{[^}]+\}/g, className: 'param' }, + { regex: /\$\{[^}]+\}/g, className: 'env' }, + { regex: /@\{[^:]+:[^}]+\}/g, className: 'secret' }, +]; + +/** + * Walk all text nodes inside the given element and wrap matches + * in elements. + */ +function highlightDynamicValues(codeEl) { + const walker = document.createTreeWalker(codeEl, NodeFilter.SHOW_TEXT); + const textNodes = []; + + while (walker.nextNode()) { + textNodes.push(walker.currentNode); + } + + for (const node of textNodes) { + const text = node.textContent; + let hasMatch = false; + + for (const { regex } of PATTERNS) { + regex.lastIndex = 0; + if (regex.test(text)) { + hasMatch = true; + break; + } + } + + if (!hasMatch) continue; + + const fragment = document.createDocumentFragment(); + let remaining = text; + + while (remaining.length > 0) { + let earliestMatch = null; + let earliestIndex = remaining.length; + let matchedPattern = null; + + for (const pattern of PATTERNS) { + pattern.regex.lastIndex = 0; + const match = pattern.regex.exec(remaining); + if (match && match.index < earliestIndex) { + earliestMatch = match; + earliestIndex = match.index; + matchedPattern = pattern; + } + } + + if (!earliestMatch) { + fragment.appendChild(document.createTextNode(remaining)); + break; + } + + if (earliestIndex > 0) { + fragment.appendChild( + document.createTextNode(remaining.slice(0, earliestIndex)) + ); + } + + const span = document.createElement('span'); + span.className = `tc-dynamic-value ${matchedPattern.className}`; + span.textContent = earliestMatch[0]; + fragment.appendChild(span); + + remaining = remaining.slice(earliestIndex + earliestMatch[0].length); + } + + node.parentNode.replaceChild(fragment, node); + } +} + +export default function TcDynamicValues({ component }) { + const codeEl = component.querySelector('code'); + if (codeEl) { + highlightDynamicValues(codeEl); + } +} diff --git a/assets/js/content-interactions.js b/assets/js/content-interactions.js index eb9b4e1bc..3de1386ea 100644 --- a/assets/js/content-interactions.js +++ b/assets/js/content-interactions.js @@ -122,7 +122,7 @@ function expandAccordions() { // Expand accordions on load based on URL anchor function openAccordionByHash() { - var anchor = window.location.hash; + var anchor = window.location.hash.split('?')[0]; function expandElement() { if ($(anchor).parents('.expand').length > 0) { diff --git a/assets/js/main.js b/assets/js/main.js index 826ad9a11..866238537 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -19,6 +19,7 @@ import * as pageContext from './page-context.js'; import * as pageFeedback from './page-feedback.js'; import * as tabbedContent from './tabbed-content.js'; import * as v3Wayfinding from './v3-wayfinding.js'; +import * as tcDownloads from './tc-downloads.js'; /** Import component modules * The component pattern organizes JavaScript, CSS, and HTML for a specific UI element or interaction: @@ -44,6 +45,7 @@ import ReleaseToc from './release-toc.js'; import { SearchButton } from './search-button.js'; import SidebarSearch from './components/sidebar-search.js'; import { SidebarToggle } from './sidebar-toggle.js'; +import TcDynamicValues from './components/tc-dynamic-values.js'; import Theme from './theme.js'; import ThemeSwitch from './theme-switch.js'; @@ -75,6 +77,7 @@ const componentRegistry = { 'search-button': SearchButton, 'sidebar-search': SidebarSearch, 'sidebar-toggle': SidebarToggle, + 'tc-dynamic-values': TcDynamicValues, theme: Theme, 'theme-switch': ThemeSwitch, }; @@ -162,6 +165,7 @@ function initModules() { pageFeedback.initialize(); tabbedContent.initialize(); v3Wayfinding.initialize(); + tcDownloads.initialize(); } /** diff --git a/assets/js/services/local-storage.js b/assets/js/services/local-storage.js index 8efccde12..22b778733 100644 --- a/assets/js/services/local-storage.js +++ b/assets/js/services/local-storage.js @@ -117,7 +117,10 @@ function getInfluxDBUrls() { initializeStorageItem('urls', JSON.stringify(DEFAULT_STORAGE_URLS)); } - return JSON.parse(localStorage.getItem(urlStorageKey)); + const storedUrls = JSON.parse(localStorage.getItem(urlStorageKey)); + // Backfill any new default keys missing from stored data (e.g., when new + // products like core/enterprise are added after a user's first visit). + return { ...DEFAULT_STORAGE_URLS, ...storedUrls }; } // Get the current or previous URL for a specific product or a custom url @@ -131,8 +134,8 @@ function getInfluxDBUrl(product) { const urlsString = localStorage.getItem(urlStorageKey); const urlsObj = JSON.parse(urlsString); - // Return the URL of the specified product - return urlsObj[product]; + // Return the URL of the specified product, falling back to the default + return urlsObj[product] ?? DEFAULT_STORAGE_URLS[product]; } /* diff --git a/assets/js/tc-downloads.js b/assets/js/tc-downloads.js new file mode 100644 index 000000000..cc17837d4 --- /dev/null +++ b/assets/js/tc-downloads.js @@ -0,0 +1,221 @@ +//////////////////////////////////////////////////////////////////////////////// +///////////////// Telegraf Controller gated downloads module //////////////////// +//////////////////////////////////////////////////////////////////////////////// + +import { toggleModal } from './modals.js'; + +const STORAGE_KEY = 'influxdata_docs_tc_dl'; +const QUERY_PARAM = 'ref'; +const QUERY_VALUE = 'tc'; + +// ─── localStorage helpers ─────────────────────────────────────────────────── + +function setDownloadKey() { + localStorage.setItem(STORAGE_KEY, 'true'); +} + +function hasDownloadKey() { + return localStorage.getItem(STORAGE_KEY) === 'true'; +} + +// ─── Query param helpers ──────────────────────────────────────────────────── + +function hasRefParam() { + // Check query string first (?ref=tc before the hash) + const params = new URLSearchParams(window.location.search); + if (params.get(QUERY_PARAM) === QUERY_VALUE) return true; + + // Also check inside the fragment (#heading?ref=tc) + const hash = window.location.hash; + const qIndex = hash.indexOf('?'); + if (qIndex !== -1) { + const hashParams = new URLSearchParams(hash.substring(qIndex)); + if (hashParams.get(QUERY_PARAM) === QUERY_VALUE) return true; + } + return false; +} + +function stripRefParam() { + const url = new URL(window.location.href); + + // Remove from query string + url.searchParams.delete(QUERY_PARAM); + + // Remove from fragment if present (#heading?ref=tc → #heading) + let hash = url.hash; + const qIndex = hash.indexOf('?'); + if (qIndex !== -1) { + const hashBase = hash.substring(0, qIndex); + const hashParams = new URLSearchParams(hash.substring(qIndex)); + hashParams.delete(QUERY_PARAM); + const remaining = hashParams.toString(); + hash = remaining ? `${hashBase}?${remaining}` : hashBase; + } + + window.history.replaceState({}, '', url.pathname + url.search + hash); +} + +// ─── Download link rendering ──────────────────────────────────────────────── + +function renderDownloadLinks(container, data) { + const version = data.version; + const platforms = data.platforms; + + let html = '
'; + + platforms.forEach((platform) => { + html += `

${platform.name}

`; + html += + '

' + + `Telegraf Controller v${version}` + + '

'; + html += '
'; + + platform.builds.forEach((build) => { + const link = + `${platform.name}` + + ` (${build.arch})`; + const sha = + `sha256:${build.sha256}` + + ''; + html += + '
' + + `
${link}
` + + `
${sha}
` + + '
'; + }); + + html += '
'; + }); + + container.innerHTML = html; +} + +// ─── Clipboard copy ───────────────────────────────────────────────────────── + +function copyToClipboard(sha, button) { + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText(sha).then(() => { + showCopiedFeedback(button); + }); + } else { + // Fallback for older browsers + const textArea = document.createElement('textarea'); + textArea.value = sha; + textArea.style.position = 'fixed'; + textArea.style.opacity = '0'; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + showCopiedFeedback(button); + } +} + +function showCopiedFeedback(button) { + const original = button.innerHTML; + button.innerHTML = ''; + setTimeout(() => { + button.innerHTML = original; + }, 2000); +} + +// ─── Marketo form ─────────────────────────────────────────────────────────── + +function initMarketoForm() { + /* global MktoForms2 */ + if (typeof MktoForms2 === 'undefined') { + console.error('tc-downloads: MktoForms2 not loaded'); + return; + } + + MktoForms2.setOptions({ + formXDPath: '/rs/972-GDU-533/images/marketo-xdframe-relative.html', + }); + + MktoForms2.loadForm( + 'https://get.influxdata.com', + '972-GDU-533', + 3195, + function (form) { + form.addHiddenFields({ mkto_content_name: 'Telegraf Enterprise Alpha' }); + + form.onSuccess(function () { + setDownloadKey(); + toggleModal(); + + // Redirect to self with ?ref=tc to trigger downloads on reload + const url = new URL(window.location.href); + url.searchParams.set(QUERY_PARAM, QUERY_VALUE); + window.location.href = url.toString(); + + // Prevent Marketo's default redirect + return false; + }); + } + ); +} + +// ─── View state management ────────────────────────────────────────────────── + +function showDownloads(area) { + const btn = area.querySelector('#tc-download-btn'); + const linksContainer = area.querySelector('#tc-downloads-links'); + + if (!linksContainer) return; + + // Parse download data from the JSON data attribute + const rawData = linksContainer.getAttribute('data-downloads'); + if (!rawData) return; + + let data; + try { + data = JSON.parse(atob(rawData)); + } catch (e) { + console.error('tc-downloads: failed to parse download data', e); + return; + } + + // Hide the download button + if (btn) btn.style.display = 'none'; + + // Render download links and show the container + renderDownloadLinks(linksContainer, data); + linksContainer.style.display = 'block'; +} + +// ─── Initialize ───────────────────────────────────────────────────────────── + +function initialize() { + // 1. Handle ?ref=tc query param on any page + if (hasRefParam()) { + setDownloadKey(); + stripRefParam(); + } + + const area = document.getElementById('tc-downloads-area'); + if (!area) return; // No shortcode on this page — no-op + + // 2. Check localStorage and show appropriate view + if (hasDownloadKey()) { + showDownloads(area); + } + + // 3. Initialize Marketo form + initMarketoForm(); + + // 4. Delegated click handler for SHA copy buttons + area.addEventListener('click', function (e) { + const copyBtn = e.target.closest('.tc-copy-sha'); + if (copyBtn) { + const sha = copyBtn.getAttribute('data-sha'); + if (sha) copyToClipboard(sha, copyBtn); + } + }); +} + +export { initialize }; diff --git a/assets/styles/layouts/_article.scss b/assets/styles/layouts/_article.scss index d3f56bccd..1b8584fd8 100644 --- a/assets/styles/layouts/_article.scss +++ b/assets/styles/layouts/_article.scss @@ -216,6 +216,7 @@ "article/tabbed-content", "article/tables", "article/tags", + "article/tc-downloads", "article/telegraf-plugins", "article/title", "article/truncate", diff --git a/assets/styles/layouts/_code-controls.scss b/assets/styles/layouts/_code-controls.scss index 36272a257..68353bed5 100644 --- a/assets/styles/layouts/_code-controls.scss +++ b/assets/styles/layouts/_code-controls.scss @@ -16,10 +16,12 @@ opacity: .5; transition: opacity .2s; border-radius: $radius; + border: none; + background: none; line-height: 0; - cursor: pointer; + cursor: pointer; - &:hover { + &:hover, &:focus-visible { opacity: 1; background-color: rgba($article-text, .1); backdrop-filter: blur(15px); @@ -35,21 +37,26 @@ backdrop-filter: blur(15px); display: none; - li { + button { + display: block; + width: 100%; + text-align: left; margin: 0; padding: .4rem .5rem .6rem; + border: none; + background: none; border-radius: $radius; color: $article-bold; font-size: .87rem; line-height: 0; - cursor: pointer; + cursor: pointer; - &:hover {background-color: rgba($article-text, .07)} - - &.copy-code, &.fullscreen-toggle { - .cf-icon {margin-right: .35rem;} + &:hover, &:focus-visible { + background-color: rgba($article-text, .07); } + .cf-icon {margin-right: .35rem;} + &.copy-code { .message { text-shadow: 0px 0px 8px rgba($article-text, 0); @@ -69,6 +76,8 @@ } } } + + li {margin: 0;} } &.open { diff --git a/assets/styles/layouts/_homepage.scss b/assets/styles/layouts/_homepage.scss index ca92588e9..0d321702c 100644 --- a/assets/styles/layouts/_homepage.scss +++ b/assets/styles/layouts/_homepage.scss @@ -278,8 +278,8 @@ position: relative; overflow: hidden; display: flex; - flex-direction: row; - align-items: center; + flex-direction: column; + // align-items: center; justify-content: space-between; .bg-overlay { @@ -302,9 +302,6 @@ } ul.product-links { - padding-left: 0; - margin: 0 3rem 0 2rem; - list-style: none; li:not(:last-child) {margin-bottom: .35rem;} diff --git a/assets/styles/layouts/_modals.scss b/assets/styles/layouts/_modals.scss index 2a149c378..fadb181eb 100644 --- a/assets/styles/layouts/_modals.scss +++ b/assets/styles/layouts/_modals.scss @@ -135,7 +135,8 @@ @import "modals/url-selector"; @import "modals/page-feedback"; @import "modals/flux-versions"; - @import "modals/_influxdb-gs-datepicker" + @import "modals/_influxdb-gs-datepicker"; + @import "modals/tc-downloads"; } diff --git a/assets/styles/layouts/article/_tc-downloads.scss b/assets/styles/layouts/article/_tc-downloads.scss new file mode 100644 index 000000000..a8b54d3d4 --- /dev/null +++ b/assets/styles/layouts/article/_tc-downloads.scss @@ -0,0 +1,104 @@ +/////////////////// Styles for inline TC download links //////////////////////// + +#tc-downloads-area { + margin: 0 0 2rem; + + #tc-download-btn { + display: inline-block; + } + + .tc-version { + font-size: 1rem; + color: rgba($article-text, .6); + margin-bottom: .5rem; + } + + .tc-build-table { + margin-bottom: 1rem; + } + + + .tc-build-row { + display: flex; + align-items: center; + border-bottom: 1px solid $article-hr; + + &:first-child { + border-top: 1px solid $article-hr; + } + } + + .tc-build-download { + flex: 1 1 auto; + margin-right: 1rem; + } + + .tc-download-link { + font-size: 1rem; + padding: .35rem 1rem; + white-space: nowrap; + } + + .tc-build-sha { + flex: 1 1 auto; + display: flex; + justify-content: flex-end; + gap: .1rem; + min-width: 0; + max-width: 25rem; + + code { + font-size: .8rem; + padding: .15rem .65rem; + color: $article-code; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .tc-copy-sha { + flex-shrink: 0; + background: $article-code-bg; + border: none; + border-radius: $radius; + padding: .2rem .6rem; + font-family: 'icomoon-v4'; + font-size: .9rem; + color: rgba($article-code, .85); + cursor: pointer; + transition: color .2s; + + &:hover { + color: $article-code-link-hover; + } + } + } +} + +//////////////////////////////// MEDIA QUERIES ///////////////////////////////// + +@include media(small) { + #tc-downloads-area { + .tc-build-row { + flex-direction: column; + align-items: flex-start; + gap: .5rem; + } + + .tc-build-download { + margin-right: 0; + width: 100%; + } + + .tc-download-link { + width: 100%; + text-align: center; + } + + .tc-build-sha { + width: 100%; + max-width: 100%; + margin-bottom: .5rem; + } + } +} diff --git a/assets/styles/layouts/modals/_tc-downloads.scss b/assets/styles/layouts/modals/_tc-downloads.scss new file mode 100644 index 000000000..a9def5ae8 --- /dev/null +++ b/assets/styles/layouts/modals/_tc-downloads.scss @@ -0,0 +1,226 @@ +////////////////////// Styles for the TC downloads modal //////////////////////// + +#tc-downloads { + + // ─── Reset Marketo's inline styles and defaults ──────────────────────────── + .mktoForm { + width: 100% !important; + font-family: $proxima !important; + font-size: 1rem !important; + color: $article-text !important; + padding: 0 !important; + } + + // Hide Marketo's offset/gutter spacers + .mktoOffset, + .mktoGutter { + display: none !important; + } + + // ─── Form layout: 2-column grid for first 4 fields ─────────────────────── + .mktoForm { + display: grid !important; + grid-template-columns: 1fr 1fr; + gap: 0 1.75rem; + } + + // Visible field rows (First Name, Last Name, Company, Job Title) + // occupy one grid cell each — pairs share a row automatically + .mktoFormRow { + margin-bottom: .5rem; + } + + // Hidden field rows collapse — they don't disrupt the grid + .mktoFormRow:has(input[type='hidden']) { + display: none; + } + + // Email, Privacy, and Submit span full width + .mktoFormRow:has(.mktoEmailField), + .mktoFormRow:has(.mktoCheckboxList), + .mktoButtonRow { + grid-column: 1 / -1; + } + + .mktoFieldDescriptor, + .mktoFieldWrap { + width: 100% !important; + margin-bottom: 0 !important; + } + + // ─── Labels ─────────────────────────────────────────────────────────────── + .mktoLabel { + display: flex !important; + align-items: baseline; + width: 100% !important; + font-family: $proxima !important; + font-weight: $medium !important; + font-size: .9rem !important; + color: $article-bold !important; + padding: .5rem 0 .1rem !important; + } + + .mktoAsterix { + order: 1; + color: #e85b5b !important; + float: none !important; + padding-left: .15rem; + } + + // ─── Text inputs ────────────────────────────────────────────────────────── + .mktoField.mktoTextField, + .mktoField.mktoEmailField { + width: 100% !important; + font-family: $proxima !important; + font-weight: $medium !important; + font-size: 1rem !important; + background: rgba($article-text, .06) !important; + border-radius: $radius !important; + border: 1px solid rgba($article-text, .06) !important; + padding: .5em !important; + color: $article-text !important; + transition-property: border; + transition-duration: .2s; + box-shadow: none !important; + + &:focus { + outline: none !important; + border-color: $sidebar-search-highlight !important; + } + + &::placeholder { + color: rgba($sidebar-search-text, .45) !important; + font-weight: normal !important; + font-style: italic !important; + } + } + + // ─── Checkbox / privacy consent ─────────────────────────────────────────── + .mktoFormRow:has(.mktoCheckboxList) .mktoAsterix { + display: none !important; + } + + .mktoCheckboxList { + width: 100% !important; + + label { + font-family: $proxima !important; + font-size: .85rem !important; + line-height: 1.4 !important; + color: rgba($article-text, .7) !important; + + &::after { + content: '*'; + color: #e85b5b; + font-weight: $medium; + font-size: .95rem; + font-style: normal; + } + + a { + color: $article-link !important; + font-weight: $medium; + text-decoration: none; + transition: color .2s; + + &:hover { + color: $article-link-hover !important; + } + } + } + + input[type='checkbox'] { + margin: .2rem .65rem 0 0; + } + } + + // ─── Submit button ──────────────────────────────────────────────────────── + .mktoButtonRow { + margin-top: 1rem; + display: flex; + justify-content: flex-end; + } + + .mktoButtonWrap { + margin-left: 0 !important; + } + + .mktoButton { + @include gradient($article-btn-gradient); + border: none !important; + border-radius: $radius !important; + padding: .65rem 1.5rem !important; + font-family: $proxima !important; + font-weight: $medium !important; + font-size: 1rem !important; + color: $g20-white !important; + cursor: pointer; + transition: opacity .2s; + + &:hover { + @include gradient($article-btn-gradient-hover); + } + } + + // ─── Validation errors ──────────────────────────────────────────────────── + // Marketo positions errors absolutely — make them flow inline instead + .mktoFieldWrap { + position: relative; + } + + .mktoError { + position: relative !important; + bottom: auto !important; + left: auto !important; + right: auto !important; + pointer-events: none; + + .mktoErrorArrow { + display: none !important; + } + + .mktoErrorMsg { + font-family: $proxima !important; + font-size: .8rem !important; + max-width: 100% !important; + background: none !important; + border: none !important; + color: #e85b5b !important; + padding: .15rem 0 0 !important; + box-shadow: none !important; + text-shadow: none !important; + } + } + + // ─── Custom error message ───────────────────────────────────────────────── + .tc-form-error { + margin: .75rem 0; + padding: .5rem .75rem; + background: rgba(#e85b5b, .1); + border: 1px solid rgba(#e85b5b, .3); + border-radius: $radius; + color: #e85b5b; + font-size: .9rem; + } + + // ─── Clear floats ───────────────────────────────────────────────────────── + .mktoClear { + clear: both; + } +} + +//////////////////////////////// MEDIA QUERIES ///////////////////////////////// + +@include media(small) { + #tc-downloads { + .mktoForm { + grid-template-columns: 1fr; + } + + .mktoFormRow:has(.mktoEmailField), + .mktoFormRow:has(.mktoCheckboxList), + .mktoButtonRow { + grid-column: auto; + } + } +} diff --git a/content/enterprise_influxdb/v1/administration/manage/clusters/rebalance.md b/content/enterprise_influxdb/v1/administration/manage/clusters/rebalance.md index 020133649..75bc3778c 100644 --- a/content/enterprise_influxdb/v1/administration/manage/clusters/rebalance.md +++ b/content/enterprise_influxdb/v1/administration/manage/clusters/rebalance.md @@ -289,8 +289,8 @@ Run the query on any data node for each retention policy and database. Here, we use InfluxDB's [CLI](/enterprise_influxdb/v1/tools/influx-cli/use-influx/) to execute the query: ``` -> ALTER RETENTION POLICY "" ON "" REPLICATION 3 -> +ALTER RETENTION POLICY "" ON "" REPLICATION 3 + ``` A successful `ALTER RETENTION POLICY` query returns no results. diff --git a/content/enterprise_influxdb/v1/administration/manage/users-and-permissions/authorization-influxql.md b/content/enterprise_influxdb/v1/administration/manage/users-and-permissions/authorization-influxql.md index f9bcf1bf6..a132289b7 100644 --- a/content/enterprise_influxdb/v1/administration/manage/users-and-permissions/authorization-influxql.md +++ b/content/enterprise_influxdb/v1/administration/manage/users-and-permissions/authorization-influxql.md @@ -124,11 +124,11 @@ CREATE USER WITH PASSWORD '' ###### CLI example ```js -> CREATE USER todd WITH PASSWORD 'influxdb41yf3' -> CREATE USER alice WITH PASSWORD 'wonder\'land' -> CREATE USER "rachel_smith" WITH PASSWORD 'asdf1234!' -> CREATE USER "monitoring-robot" WITH PASSWORD 'XXXXX' -> CREATE USER "$savyadmin" WITH PASSWORD 'm3tr1cL0v3r' +CREATE USER todd WITH PASSWORD 'influxdb41yf3' +CREATE USER alice WITH PASSWORD 'wonder\'land' +CREATE USER "rachel_smith" WITH PASSWORD 'asdf1234!' +CREATE USER "monitoring-robot" WITH PASSWORD 'XXXXX' +CREATE USER "$savyadmin" WITH PASSWORD 'm3tr1cL0v3r' ``` {{% note %}} @@ -169,13 +169,13 @@ CLI examples: `GRANT` `READ` access to `todd` on the `NOAA_water_database` database: ```sql -> GRANT READ ON "NOAA_water_database" TO "todd" +GRANT READ ON "NOAA_water_database" TO "todd" ``` `GRANT` `ALL` access to `todd` on the `NOAA_water_database` database: ```sql -> GRANT ALL ON "NOAA_water_database" TO "todd" +GRANT ALL ON "NOAA_water_database" TO "todd" ``` ##### `REVOKE` `READ`, `WRITE`, or `ALL` database privileges from an existing user @@ -189,13 +189,13 @@ CLI examples: `REVOKE` `ALL` privileges from `todd` on the `NOAA_water_database` database: ```sql -> REVOKE ALL ON "NOAA_water_database" FROM "todd" +REVOKE ALL ON "NOAA_water_database" FROM "todd" ``` `REVOKE` `WRITE` privileges from `todd` on the `NOAA_water_database` database: ```sql -> REVOKE WRITE ON "NOAA_water_database" FROM "todd" +REVOKE WRITE ON "NOAA_water_database" FROM "todd" ``` {{% note %}} @@ -230,7 +230,7 @@ SET PASSWORD FOR = '' CLI example: ```sql -> SET PASSWORD FOR "todd" = 'password4todd' +SET PASSWORD FOR "todd" = 'password4todd' ``` {{% note %}} @@ -250,6 +250,6 @@ DROP USER CLI example: ```sql -> DROP USER "todd" +DROP USER "todd" ``` diff --git a/content/enterprise_influxdb/v1/flux/get-started/syntax-basics.md b/content/enterprise_influxdb/v1/flux/get-started/syntax-basics.md index e48c0b79b..710cbb2bb 100644 --- a/content/enterprise_influxdb/v1/flux/get-started/syntax-basics.md +++ b/content/enterprise_influxdb/v1/flux/get-started/syntax-basics.md @@ -28,9 +28,9 @@ For example, simple addition: Assign an expression to a variable using the assignment operator, `=`. ```js -> s = "this is a string" -> i = 1 // an integer -> f = 2.0 // a floating point number +s = "this is a string" +i = 1 // an integer +f = 2.0 // a floating point number ``` Type the name of a variable to print its value: @@ -48,7 +48,7 @@ this is a string Flux also supports records. Each value in a record can be a different data type. ```js -> o = {name:"Jim", age: 42, "favorite color": "red"} +o = {name:"Jim", age: 42, "favorite color": "red"} ``` Use **dot notation** to access a properties of a record: diff --git a/content/enterprise_influxdb/v1/guides/downsample_and_retain.md b/content/enterprise_influxdb/v1/guides/downsample_and_retain.md index c544c276e..81c4238fd 100644 --- a/content/enterprise_influxdb/v1/guides/downsample_and_retain.md +++ b/content/enterprise_influxdb/v1/guides/downsample_and_retain.md @@ -70,7 +70,7 @@ the CQ has no `FOR` clause. #### 1. Create the database ```sql -> CREATE DATABASE "food_data" +CREATE DATABASE "food_data" ``` #### 2. Create a two-hour `DEFAULT` retention policy @@ -85,7 +85,7 @@ Use the statement to create a `DEFAULT` RP: ```sql -> CREATE RETENTION POLICY "two_hours" ON "food_data" DURATION 2h REPLICATION 1 DEFAULT +CREATE RETENTION POLICY "two_hours" ON "food_data" DURATION 2h REPLICATION 1 DEFAULT ``` That query creates an RP called `two_hours` that exists in the database @@ -116,7 +116,7 @@ Use the statement to create a non-`DEFAULT` retention policy: ```sql -> CREATE RETENTION POLICY "a_year" ON "food_data" DURATION 52w REPLICATION 1 +CREATE RETENTION POLICY "a_year" ON "food_data" DURATION 52w REPLICATION 1 ``` That query creates a retention policy (RP) called `a_year` that exists in the database diff --git a/content/enterprise_influxdb/v1/query_language/continuous_queries.md b/content/enterprise_influxdb/v1/query_language/continuous_queries.md index 1ca7d56b7..76cb98168 100644 --- a/content/enterprise_influxdb/v1/query_language/continuous_queries.md +++ b/content/enterprise_influxdb/v1/query_language/continuous_queries.md @@ -839,8 +839,7 @@ DROP CONTINUOUS QUERY ON Drop the `idle_hands` CQ from the `telegraf` database: ```sql -> DROP CONTINUOUS QUERY "idle_hands" ON "telegraf"` -> +DROP CONTINUOUS QUERY "idle_hands" ON "telegraf" ``` ### Altering continuous queries diff --git a/content/enterprise_influxdb/v1/query_language/explore-data.md b/content/enterprise_influxdb/v1/query_language/explore-data.md index a4b880ed7..1cf896f9b 100644 --- a/content/enterprise_influxdb/v1/query_language/explore-data.md +++ b/content/enterprise_influxdb/v1/query_language/explore-data.md @@ -380,8 +380,7 @@ The following query returns no data because it specifies a single tag key (`loca the `SELECT` clause: ```sql -> SELECT "location" FROM "h2o_feet" -> +SELECT "location" FROM "h2o_feet" ``` To return any data associated with the `location` tag key, the query's `SELECT` @@ -597,7 +596,7 @@ separating logic with parentheses. #### Select data that have specific timestamps ```sql -> SELECT * FROM "h2o_feet" WHERE time > now() - 7d +SELECT * FROM "h2o_feet" WHERE time > now() - 7d ``` The query returns data from the `h2o_feet` measurement that have [timestamps](/enterprise_influxdb/v1/concepts/glossary/#timestamp) @@ -1592,8 +1591,8 @@ the query's time range. Note that `fill(800)` has no effect on the query results. ```sql -> SELECT MEAN("water_level") FROM "h2o_feet" WHERE "location" = 'coyote_creek' AND time >= '2015-09-18T22:00:00Z' AND time <= '2015-09-18T22:18:00Z' GROUP BY time(12m) fill(800) -> +SELECT MEAN("water_level") FROM "h2o_feet" WHERE "location" = 'coyote_creek' AND time >= '2015-09-18T22:00:00Z' AND time <= '2015-09-18T22:18:00Z' GROUP BY time(12m) fill(800) + ``` ##### Queries with `fill(previous)` when the previous result falls outside the query's time range @@ -2639,7 +2638,7 @@ The whitespace between `-` or `+` and the [duration literal](/enterprise_influxd #### Specify a time range with relative time ```sql -> SELECT "water_level" FROM "h2o_feet" WHERE time > now() - 1h +SELECT "water_level" FROM "h2o_feet" WHERE time > now() - 1h ``` The query returns data with timestamps that occur within the past hour. @@ -2686,7 +2685,7 @@ a `GROUP BY time()` clause must provide an alternative upper bound in the Use the [CLI](/enterprise_influxdb/v1/tools/influx-cli/use-influx/) to write a point to the `NOAA_water_database` that occurs after `now()`: ```sql -> INSERT h2o_feet,location=santa_monica water_level=3.1 1587074400000000000 +INSERT h2o_feet,location=santa_monica water_level=3.1 1587074400000000000 ``` Run a `GROUP BY time()` query that covers data with timestamps between @@ -2722,8 +2721,8 @@ the lower bound to `now()` such that the query's time range is between `now()` and `now()`: ```sql -> SELECT MEAN("water_level") FROM "h2o_feet" WHERE "location"='santa_monica' AND time >= now() GROUP BY time(12m) fill(none) -> +SELECT MEAN("water_level") FROM "h2o_feet" WHERE "location"='santa_monica' AND time >= now() GROUP BY time(12m) fill(none) + ``` ### Configuring the returned timestamps @@ -2831,8 +2830,8 @@ includes an `m` and `water_level` is greater than three. #### Use a regular expression to specify a tag with no value in the WHERE clause ```sql -> SELECT * FROM "h2o_feet" WHERE "location" !~ /./ -> +SELECT * FROM "h2o_feet" WHERE "location" !~ /./ + ``` The query selects all data from the `h2o_feet` measurement where the `location` @@ -2989,8 +2988,8 @@ The query returns the integer form of `water_level`'s float [field values](/ente #### Cast float field values to strings (this functionality is not supported) ```sql -> SELECT "water_level"::string FROM "h2o_feet" LIMIT 4 -> +SELECT "water_level"::string FROM "h2o_feet" LIMIT 4 + ``` The query returns no data as casting a float field value to a string is not diff --git a/content/enterprise_influxdb/v1/query_language/manage-database.md b/content/enterprise_influxdb/v1/query_language/manage-database.md index d57aa6efd..45b5848fe 100644 --- a/content/enterprise_influxdb/v1/query_language/manage-database.md +++ b/content/enterprise_influxdb/v1/query_language/manage-database.md @@ -87,8 +87,8 @@ If you attempt to create a database that already exists, InfluxDB does nothing a ##### Create a database ``` -> CREATE DATABASE "NOAA_water_database" -> +CREATE DATABASE "NOAA_water_database" + ``` The query creates a database called `NOAA_water_database`. @@ -97,8 +97,8 @@ The query creates a database called `NOAA_water_database`. ##### Create a database with a specific retention policy ``` -> CREATE DATABASE "NOAA_water_database" WITH DURATION 3d REPLICATION 1 SHARD DURATION 1h NAME "liquid" -> +CREATE DATABASE "NOAA_water_database" WITH DURATION 3d REPLICATION 1 SHARD DURATION 1h NAME "liquid" + ``` The query creates a database called `NOAA_water_database`. @@ -114,8 +114,8 @@ DROP DATABASE Drop the database NOAA_water_database: ```bash -> DROP DATABASE "NOAA_water_database" -> +DROP DATABASE "NOAA_water_database" + ``` A successful `DROP DATABASE` query returns an empty result. @@ -135,19 +135,19 @@ DROP SERIES FROM WHERE =' DROP SERIES FROM "h2o_feet" +DROP SERIES FROM "h2o_feet" ``` Drop series with a specific tag pair from a single measurement: ```sql -> DROP SERIES FROM "h2o_feet" WHERE "location" = 'santa_monica' +DROP SERIES FROM "h2o_feet" WHERE "location" = 'santa_monica' ``` Drop all points in the series that have a specific tag pair from all measurements in the database: ```sql -> DROP SERIES WHERE "location" = 'santa_monica' +DROP SERIES WHERE "location" = 'santa_monica' ``` A successful `DROP SERIES` query returns an empty result. @@ -168,25 +168,25 @@ DELETE FROM WHERE [=''] | [
@@ -201,16 +218,6 @@

Other Products

-
-
-

Telegraf {{ $telegrafVersion }}

-

The collection agent that gathers time series data from many different sources.

-
- -

Chronograf {{ $chronografVersion }}

diff --git a/layouts/partials/article/special-state.html b/layouts/partials/article/special-state.html index fea71cd19..98cbe6b21 100644 --- a/layouts/partials/article/special-state.html +++ b/layouts/partials/article/special-state.html @@ -18,21 +18,63 @@ {{ if in $productPathWhitelist (print $product "/" $version )}}
-

{{ $displayName }} is in Private Alpha

+

{{ $displayName }} is in Public Beta

- {{ $displayName }} is in private alpha. If you are interested in being a - part of the private alpha program, please sign up: -

-

Sign Up for the Alpha

-

- While in alpha, {{ $displayName }} is not meant for production use. + {{ $displayName }} is in public beta and will be part of the future Telegraf Enterprise offering. + While in beta, {{ $displayName }} is not meant for production use. The {{ $displayName}} documentation is a work in progress, and we are actively working to improve it. If you have any questions or suggestions, please submit an issue. We welcome any and all contributions.

-
+
+

+ Beta expectations +

+ +
+
+

+ Provide beta feedback +

+ +
+

Join our public channels

diff --git a/layouts/partials/footer/modals.html b/layouts/partials/footer/modals.html index 9830135dd..56f27291f 100644 --- a/layouts/partials/footer/modals.html +++ b/layouts/partials/footer/modals.html @@ -14,6 +14,9 @@ {{ if $inStdlib }} {{ partial "footer/modals/flux-influxdb-versions.html" . }} {{ end }} + {{ if .Page.HasShortcode "telegraf/tc-downloads" }} + {{ partial "footer/modals/tc-downloads.html" . }} + {{ end }}
\ No newline at end of file diff --git a/layouts/partials/footer/modals/tc-downloads.html b/layouts/partials/footer/modals/tc-downloads.html new file mode 100644 index 000000000..882c25545 --- /dev/null +++ b/layouts/partials/footer/modals/tc-downloads.html @@ -0,0 +1,11 @@ + diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html index 494bc0183..359d50781 100644 --- a/layouts/partials/sidebar.html +++ b/layouts/partials/sidebar.html @@ -35,6 +35,8 @@ {{ .Scratch.Set "searchPlaceholder" "Search the docs" }} {{ else if (eq $currentVersion nil) }} {{ .Scratch.Set "searchPlaceholder" (print "Search " (index .Site.Data.products $product).name) }} +{{ else if (eq $product "telegraf") }} + {{ .Scratch.Set "searchPlaceholder" (print "Search " (cond (eq $currentVersion "v1") "Telegraf" "Telegraf Controller")) }} {{ else if eq $product "influxdb" }} {{ if eq $currentVersion "v3" }} {{ .Scratch.Set "searchPlaceholder" "Search InfluxDB OSS v3" }} diff --git a/layouts/partials/topnav/product-selector.html b/layouts/partials/topnav/product-selector.html index 7f2271c20..25089d004 100644 --- a/layouts/partials/topnav/product-selector.html +++ b/layouts/partials/topnav/product-selector.html @@ -90,7 +90,7 @@ Identify products by their product path. Dictionary schema:

Telegraf

  • {{ template "productLink" (merge (dict "productPath" "telegraf/v1") $templateDefaults) }}
  • -
  • {{ template "productLink" (merge (dict "productPath" "telegraf/controller" "state" "alpha") $templateDefaults) }}
  • +
  • {{ template "productLink" (merge (dict "productPath" "telegraf/controller" "state" "beta") $templateDefaults) }}
diff --git a/layouts/shortcodes/telegraf/dynamic-values.html b/layouts/shortcodes/telegraf/dynamic-values.html deleted file mode 100644 index ec7d76bb9..000000000 --- a/layouts/shortcodes/telegraf/dynamic-values.html +++ /dev/null @@ -1,21 +0,0 @@ -{{- /* Define more precise regex patterns for each dynamic value type */ -}} -{{- /* Note: markdownify converts & to & so we need to match that */ -}} -{{- $paramsRegex := `&\{[^}]+\}` -}} -{{- $envsRegex := `\$\{[^}]+\}` -}} -{{- $secretsRegex := `@\{[^:]+:[^}]+\}` -}} - -{{- /* Get the inner content and markdownify it */ -}} -{{- $code := .Inner | markdownify -}} - -{{- /* Apply replacements for each type of dynamic value */ -}} -{{- /* Replace parameters with span class="param" */ -}} -{{- $code = replaceRE $paramsRegex `$0` $code -}} - -{{- /* Replace environment variables with span class="env" */ -}} -{{- $code = replaceRE $envsRegex `$0` $code -}} - -{{- /* Replace secrets with span class="secret" */ -}} -{{- $code = replaceRE $secretsRegex `$0` $code -}} - -{{- /* Output the processed code */ -}} -{{ $code | safeHTML }} \ No newline at end of file diff --git a/layouts/shortcodes/telegraf/tc-downloads.html b/layouts/shortcodes/telegraf/tc-downloads.html new file mode 100644 index 000000000..a97f4ffcb --- /dev/null +++ b/layouts/shortcodes/telegraf/tc-downloads.html @@ -0,0 +1,37 @@ +{{/* + tc-downloads shortcode + Renders a gated download experience for Telegraf Controller. + - Shows a "Download" button that opens a contact form modal. + - After form submission (or email link with ?ref=tc), JS renders + download links from the JSON data attribute. + - Data sourced from data/tc_downloads.yml (metadata only — URLs are + constructed here at build time). +*/}} +{{- $data := .Site.Data.tc_downloads -}} +{{- $baseURL := "https://telegraf-controller-artifacts.s3.us-east-1.amazonaws.com" -}} +{{- $version := $data.version -}} + +{{/* Build enriched platform data with constructed URLs */}} +{{- $platforms := slice -}} +{{- range $data.platforms -}} + {{- $builds := slice -}} + {{- range .builds -}} + {{- $ext := .ext | default "" -}} + {{- $filename := printf "telegraf_controller-%s-%s%s" .os .arch $ext -}} + {{- $url := printf "%s/v%s/%s" $baseURL $version $filename -}} + {{- $build := dict "arch" .arch "os" .os "sha256" .sha256 "filename" $filename "url" $url -}} + {{- $builds = $builds | append $build -}} + {{- end -}} + {{- $platforms = $platforms | append (dict "name" .name "builds" $builds) -}} +{{- end -}} + +{{- $enriched := dict "version" $version "platforms" $platforms -}} + diff --git a/lefthook.yml b/lefthook.yml index 316f4ee7a..eebc5be9d 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -152,7 +152,16 @@ pre-push: commands: packages-audit: tags: frontend security - run: yarn audit + run: | + default_branch=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') || default_branch="master" + current_branch=$(git branch --show-current) + yarn audit; status=$? + if [ $status -ne 0 ] && [ "$current_branch" != "$default_branch" ]; then + echo "⚠️ yarn audit found vulnerabilities (warning only — non-default branch '$current_branch')" + echo " Create an issue: https://github.com/influxdata/docs-v2/issues/new?title=yarn+audit+vulnerabilities&labels=security" + exit 0 + fi + exit $status e2e-shortcode-examples: tags: [frontend, test] diff --git a/package.json b/package.json index 9eb534436..54667ff8a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "resolutions": { "serialize-javascript": "^6.0.2", "tar": "7.5.11", - "lodash-es": "^4.17.23" + "lodash-es": "^4.17.23", + "dompurify": ">=3.3.2" }, "devDependencies": { "@eslint/js": "^10.0.1", @@ -48,7 +49,7 @@ "dependencies": { "@types/turndown": "^5.0.6", "axios": "^1.13.5", - "glob": "^10.3.10", + "glob": "^13.0.6", "gray-matter": "^4.0.3", "jquery": "^3.7.1", "js-cookie": "^3.0.5", diff --git a/static/img/telegraf/controller-account-page.png b/static/img/telegraf/controller-account-page.png new file mode 100644 index 000000000..c21f59a7c Binary files /dev/null and b/static/img/telegraf/controller-account-page.png differ diff --git a/static/img/telegraf/controller-agents-list.png b/static/img/telegraf/controller-agents-list.png index b46ab5bfa..4dfca4c97 100644 Binary files a/static/img/telegraf/controller-agents-list.png and b/static/img/telegraf/controller-agents-list.png differ diff --git a/static/img/telegraf/controller-command-builder-dl.png b/static/img/telegraf/controller-command-builder-dl.png new file mode 100644 index 000000000..2e3e3eeba Binary files /dev/null and b/static/img/telegraf/controller-command-builder-dl.png differ diff --git a/static/img/telegraf/controller-create-token.png b/static/img/telegraf/controller-create-token.png new file mode 100644 index 000000000..617f12794 Binary files /dev/null and b/static/img/telegraf/controller-create-token.png differ diff --git a/static/img/telegraf/controller-invite-user.png b/static/img/telegraf/controller-invite-user.png new file mode 100644 index 000000000..f059cc89e Binary files /dev/null and b/static/img/telegraf/controller-invite-user.png differ diff --git a/static/img/telegraf/controller-settings.png b/static/img/telegraf/controller-settings.png new file mode 100644 index 000000000..7cd013e97 Binary files /dev/null and b/static/img/telegraf/controller-settings.png differ diff --git a/static/img/telegraf/controller-setup-owner-account.png b/static/img/telegraf/controller-setup-owner-account.png new file mode 100644 index 000000000..9df863661 Binary files /dev/null and b/static/img/telegraf/controller-setup-owner-account.png differ diff --git a/static/img/telegraf/controller-transfer-ownership.png b/static/img/telegraf/controller-transfer-ownership.png new file mode 100644 index 000000000..2960654f4 Binary files /dev/null and b/static/img/telegraf/controller-transfer-ownership.png differ diff --git a/yarn.lock b/yarn.lock index 49b022d29..f4c6fd7f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -283,18 +283,6 @@ "@iconify/types" "^2.0.0" mlly "^1.8.0" -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - "@isaacs/fs-minipass@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" @@ -314,11 +302,6 @@ resolved "https://registry.yarnpkg.com/@mixmark-io/domino/-/domino-2.2.0.tgz#4e8ec69bf1afeb7a14f0628b7e2c0f35bdb336c3" integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw== -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@puppeteer/browsers@2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.13.0.tgz#10f980c6d65efeff77f8a3cac6e1a7ac10604500" @@ -804,11 +787,6 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" - integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -816,11 +794,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^6.1.0: - version "6.2.3" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" - integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== - anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -1140,13 +1113,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== - dependencies: - balanced-match "^1.0.0" - brace-expansion@^5.0.2: version "5.0.4" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.4.tgz#614daaecd0a688f660bbbc909a8748c3d80d4336" @@ -2005,10 +1971,10 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -dompurify@^3.2.5: - version "3.3.2" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.3.2.tgz#58c515d0f8508b8749452a028aa589ad80b36325" - integrity sha512-6obghkliLdmKa56xdbLOpUZ43pAR6xFy1uOrxBaIDjT+yaRuuybLjGS9eVBoSR/UPU5fq3OXClEHLJNGvbxKpQ== +dompurify@>=3.3.2, dompurify@^3.2.5: + version "3.3.3" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.3.3.tgz#680cae8af3e61320ddf3666a3bc843f7b291b2b6" + integrity sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA== optionalDependencies: "@types/trusted-types" "^2.0.7" @@ -2021,11 +1987,6 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -2560,9 +2521,9 @@ flat-cache@^4.0.0: keyv "^4.5.4" flatted@^3.2.9: - version "3.3.3" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" - integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + version "3.4.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== fn.name@1.x.x: version "1.1.0" @@ -2581,14 +2542,6 @@ for-each@^0.3.3, for-each@^0.3.5: dependencies: is-callable "^1.2.7" -foreground-child@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" - integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== - dependencies: - cross-spawn "^7.0.6" - signal-exit "^4.0.1" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -2753,17 +2706,14 @@ glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob@^10.3.10: - version "10.5.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.5.0.tgz#8ec0355919cd3338c28428a23d4f24ecc5fe738c" - integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== +glob@^13.0.6: + version "13.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-13.0.6.tgz#078666566a425147ccacfbd2e332deb66a2be71d" + integrity sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw== dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" + minimatch "^10.2.2" + minipass "^7.1.3" + path-scurry "^2.0.2" global-dirs@^3.0.0: version "3.0.1" @@ -3238,15 +3188,6 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - jquery@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" @@ -3606,12 +3547,7 @@ longest-streak@^3.0.0: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.1.0.tgz#62fa67cd958742a1574af9f39866364102d90cd4" integrity sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g== -lru-cache@^10.2.0: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - -lru-cache@^11.2.4, lru-cache@^11.2.5, lru-cache@^11.2.6: +lru-cache@^11.0.0, lru-cache@^11.2.4, lru-cache@^11.2.5, lru-cache@^11.2.6: version "11.2.6" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.6.tgz#356bf8a29e88a7a2945507b31f6429a65a192c58" integrity sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ== @@ -4126,19 +4062,12 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.4: - version "9.0.9" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.9.tgz#9b0cb9fcb78087f6fd7eababe2511c4d3d60574e" - integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== - dependencies: - brace-expansion "^2.0.2" - minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: +minipass@^7.0.4, minipass@^7.1.2, minipass@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.3.tgz#79389b4eb1bb2d003a9bba87d492f2bd37bdc65b" integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== @@ -4372,11 +4301,6 @@ pac-resolver@^7.0.1: degenerator "^5.0.0" netmask "^2.0.2" -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - package-manager-detector@^1.3.0: version "1.6.0" resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.6.0.tgz#70d0cf0aa02c877eeaf66c4d984ede0be9130734" @@ -4438,13 +4362,13 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== +path-scurry@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.2.tgz#6be0d0ee02a10d9e0de7a98bae65e182c9061f85" + integrity sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg== dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + lru-cache "^11.0.0" + minipass "^7.1.2" pathe@^2.0.1, pathe@^2.0.3: version "2.0.3" @@ -5049,11 +4973,6 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - slash@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" @@ -5177,15 +5096,6 @@ streamx@^2.12.5, streamx@^2.15.0, streamx@^2.21.0: fast-fifo "^1.3.2" text-decoder "^1.1.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -5195,15 +5105,6 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - string.prototype.includes@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" @@ -5252,13 +5153,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -5266,13 +5160,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" - integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== - dependencies: - ansi-regex "^6.2.2" - strip-bom-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" @@ -5888,15 +5775,6 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -5915,15 +5793,6 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"