Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/mega-linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: JS/TS linting (MegaLinter)

on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main
workflow_dispatch:

env:
# Full-codebase run only when manually triggered or pushed to the
# default branch; pull requests only lint their changed files.
VALIDATE_ALL_CODEBASE: ${{ github.event_name != 'pull_request' }}

jobs:
megalinter:
name: MegaLinter
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
security-events: write
steps:
- name: Checkout the latest commit
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: MegaLinter
uses: oxsecurity/megalinter@v9
env:
VALIDATE_ALL_CODEBASE: ${{ env.VALIDATE_ALL_CODEBASE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload MegaLinter reports
if: success() || failure()
uses: actions/upload-artifact@v4
with:
name: megalinter-reports
path: |
megalinter-reports
retention-days: 7
9 changes: 9 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Ignored findings for gitleaks/betterleaks (REPOSITORY_BETTERLEAKS in MegaLinter).
# betterleaks is backward-compatible with gitleaks and reads this file automatically
# (default --gitleaks-ignore-path is the repo root), so no extra MegaLinter config is needed.
#
# Each line is a finding fingerprint: <file>:<rule id>:<line>
# These are confirmed false positives: example GUIDs used in Azure Table Storage
# documentation samples (RowKey/PartitionKey), not real secrets.
versioned_docs/version-v6.0.0/framework/regextranslation.mdx:generic-api-key:80
versioned_docs/version-v6.0.0/dashboard/flows/04_import-flow-traces/import-flows-via-la.mdx:generic-api-key:216
68 changes: 68 additions & 0 deletions .mega-linter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Configuration for MegaLinter
# See all available variables at https://megalinter.io/latest/config-file/
---
# Only lint files changed in the pull request by default; the workflow
# overrides this to `true` for manual/full-codebase runs.
VALIDATE_ALL_CODEBASE: false

# Scope this run to a deliberate set of linters: JS/TS via our own ESLint
# config, plus CI/config/style/security checks that have no other coverage
# in this repo. Prose/spelling already has dedicated workflows (Vale,
# spell-check-on-pr, typos), so markdown/spell linters are intentionally
# left out here to avoid duplicate or conflicting reports.
ENABLE_LINTERS:
- JAVASCRIPT_ES
- TYPESCRIPT_ES
- ACTION_ACTIONLINT
- REPOSITORY_BETTERLEAKS
- YAML_YAMLLINT
- CSS_STYLELINT
- POWERSHELL_POWERSHELL
- COPYPASTE_JSCPD

# Use the project's own ESLint/tsc configs instead of MegaLinter defaults.
# MegaLinter bundles its own ESLint/plugins, which can't see this repo's
# eslint.config.js plugins (typescript-eslint, eslint-plugin-react, ...).
# Install the project's pnpm dependencies first and run the local ESLint
# binary so it resolves the same plugins used locally and in `npm run lint`.
JAVASCRIPT_ES_CONFIG_FILE: eslint.config.js
JAVASCRIPT_ES_CLI_EXECUTABLE: node_modules/.bin/eslint
JAVASCRIPT_ES_PRE_COMMANDS:
- command: corepack enable pnpm
cwd: workspace
continue_if_failed: false
- command: pnpm install --frozen-lockfile --ignore-scripts
cwd: workspace
continue_if_failed: false

TYPESCRIPT_ES_CONFIG_FILE: eslint.config.js
TYPESCRIPT_ES_TSCONFIG_FILE: tsconfig.json
TYPESCRIPT_ES_CLI_EXECUTABLE: node_modules/.bin/eslint
TYPESCRIPT_ES_PRE_COMMANDS:
- command: corepack enable pnpm
cwd: workspace
continue_if_failed: false
- command: pnpm install --frozen-lockfile --ignore-scripts
cwd: workspace
continue_if_failed: false

FILTER_REGEX_EXCLUDE: '(node_modules|\.docusaurus|build|preview|versioned_docs|versioned_sidebars|static|cypress/screenshots|\.netlify|\.lighthouseci|pnpm-lock\.yaml|deno\.lock)'

# jscpd's default language support would otherwise also scan the large
# generated knowledge.json/v6-knowledge.json data dumps and the Bicep
# parameter reference JSON in src/data — structured data, not code, where
# repeated shapes are inherent to the schema rather than a duplication smell.
COPYPASTE_JSCPD_FILTER_REGEX_INCLUDE: '(^src/|^cypress/|^netlify/|^scripts/)'
COPYPASTE_JSCPD_FILTER_REGEX_EXCLUDE: '^src/data/'

# GitHub Actions workflow conventions trip up yamllint's defaults; use our
# relaxed ruleset (see .yamllint.yml).
YAML_YAMLLINT_CONFIG_FILE: .yamllint.yml

SHOW_ELAPSED_TIME: true
FILEIO_REPORTER: false

# Write a summary table (per-linter pass/fail + error counts) to the GitHub
# Actions job summary, visible directly on the workflow run without opening
# individual logs. GITHUB_STEP_SUMMARY is set automatically by Actions.
MARKDOWN_SUMMARY_REPORTER: true
13 changes: 13 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
extends: default

rules:
# GitHub Actions workflows conventionally omit the `---` document marker;
# none of this repo's existing workflows use one.
document-start: disable
# YAML 1.1 treats bare `on`/`off` as booleans, which flags the standard
# GitHub Actions `on:` trigger key as a false positive.
truthy:
check-keys: false
# Long regex filters/URLs in comments are common in this repo's configs.
line-length:
max: 200
2 changes: 1 addition & 1 deletion cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = defineConfig({
e2e: {
supportFile: false,
baseUrl: 'http://localhost:3000/',
setupNodeEvents(on, config) {
setupNodeEvents(_on, _config) {
// implement node event listeners here
},
},
Expand Down
129 changes: 129 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// @ts-check
const js = require('@eslint/js');
const tseslint = require('typescript-eslint');
const react = require('eslint-plugin-react');
const reactHooks = require('eslint-plugin-react-hooks');
const cypress = require('eslint-plugin-cypress');
const globals = require('globals');

const CJS_CONFIG_FILES = [
'*.config.js',
'babel.config.js',
'sidebars.js',
'eslint.config.js',
];

module.exports = tseslint.config(
{
// Build output and generated/vendored content are never linted.
ignores: [
'.docusaurus/**',
'build/**',
'node_modules/**',
'versioned_docs/**',
'versioned_sidebars/**',
'static/**',
'preview/**',
'cypress/screenshots/**',
'.netlify/**',
'.lighthouseci/**',
],
},
js.configs.recommended,
{
// TypeScript-aware rules only apply to actual TypeScript files.
files: ['**/*.{ts,tsx}'],
extends: [...tseslint.configs.recommended],
rules: {
// Existing code has legacy `any` usage; keep it visible without
// failing CI until it's cleaned up incrementally.
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': 'warn',
},
},
{
// React components: browser code across JS, JSX, TS and TSX.
files: ['src/**/*.{js,jsx,ts,tsx}'],
...react.configs.flat.recommended,
languageOptions: {
...react.configs.flat.recommended.languageOptions,
globals: {
...globals.browser,
},
},
plugins: {
...react.configs.flat.recommended.plugins,
'react-hooks': reactHooks,
},
rules: {
...react.configs.flat.recommended.rules,
...react.configs.flat['jsx-runtime'].rules,
...Object.fromEntries(
Object.entries(reactHooks.configs['recommended-latest'].rules).map(
([rule, severity]) => [
rule,
// Keep the classic, high-confidence hook-order check as an
// error; the newer React Compiler-readiness checks are
// useful signal but shouldn't block CI on existing code yet.
rule === 'react-hooks/rules-of-hooks' ? severity : 'warn',
]
)
),
'no-unused-vars': 'warn',
// Prop types are covered by TypeScript in this codebase.
'react/prop-types': 'off',
'react/no-unescaped-entities': 'warn',
},
settings: {
react: {
version: 'detect',
},
},
},
{
// Cypress end-to-end tests and support files.
files: ['cypress/**/*.js', 'cypress.config.js'],
...cypress.configs.recommended,
languageOptions: {
...cypress.configs.recommended.languageOptions,
globals: {
...globals.node,
...cypress.configs.recommended.languageOptions.globals,
},
},
rules: {
...cypress.configs.recommended.rules,
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
},
{
// Node-run CommonJS config/build scripts.
files: CJS_CONFIG_FILES,
languageOptions: {
sourceType: 'commonjs',
globals: {
...globals.node,
},
},
},
{
// Other plain Node scripts (e.g. Prism theme definitions).
files: ['src/prism/*.js'],
languageOptions: {
sourceType: 'commonjs',
globals: {
...globals.node,
},
},
},
{
// Deno-based Netlify edge functions.
files: ['netlify/edge-functions/**/*.js'],
languageOptions: {
globals: {
...globals.browser,
Deno: 'readonly',
},
},
}
);
15 changes: 14 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"cy:run": "cypress run",
"test": "start-server-and-test start http://localhost:3000 cy:run",
"index:push": "pwsh scripts/refresh-search-index.ps1",
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"issue-templates:sync-versions": "pwsh scripts/update-issue-template-versions.ps1"
},
"dependencies": {
Expand Down Expand Up @@ -52,11 +55,21 @@
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.10.2",
"@docusaurus/theme-classic": "3.10.2",
"@docusaurus/plugin-content-docs": "3.10.2",
"@docusaurus/types": "3.10.2",
"@docusaurus/tsconfig": "^3.10.2",
"cypress": "^15.13.1",
"dotenv": "^17.4.2",
"start-server-and-test": "^2.1.5"
"eslint": "^9.39.5",
"@eslint/js": "^9.39.5",
"eslint-plugin-cypress": "^6.4.3",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"globals": "^17.8.0",
"start-server-and-test": "^2.1.5",
"typescript": "^5.9.3",
"typescript-eslint": "^8.65.0"
},
"engines": {
"node": ">=20.0"
Expand Down
Loading
Loading