Compare commits

..

4 Commits

Author SHA1 Message Date
Chris Farhood 8e9c7e9aba fix: add missing direct devDeps (eslint, prettier, typescript)
Adds eslint@^8.57.1, prettier@^3.0.0, typescript@^5.6.2 as direct
devDependencies so pnpm --frozen-lockfile exposes their binaries
in node_modules/.bin for CI lint/type-check/format-check steps.

Fixes PRI-564.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-06 12:25:03 +00:00
Chris Farhood e6165487ad fix: add pnpm-lock.yaml for reproducible builds
Generated from package-lock.json via pnpm import.
Fixes PRI-551.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-04 19:34:28 +00:00
privilegedescalation-engineer[bot] 85c839bc19 fix(e2e): scope heading locators to main content area (#50)
Replace bare getByRole("heading", { name: /Intel GPU — .../i }) calls
with page.locator('main').getByRole('heading', { name: '...' }) so that
each locator matches exactly one element and Playwright strict mode is
satisfied.

The main element is the appropriate scoping container for plugin page
content. Exact name matching (without regex) is used to be precise about
which heading is being targeted.

Co-authored-by: Test User <test@example.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-04 17:20:38 +00:00
privilegedescalation-engineer[bot] 00c29e36dd fix: override lodash >=4.18.0 to patch code injection vulnerability (#51)
* fix: override lodash >=4.18.0 to patch code injection vulnerability

GHSA-r5fr-rjxr-66jc is a code injection vulnerability in lodash
below 4.18.0. The vulnerable transitive dependency comes through
@kinvolk/headlamp-plugin.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: update package-lock.json to satisfy lodash override

The package.json override requires lodash >=4.18.0, but the lockfile
had 4.17.23. Regenerated lockfile with npm install --include=dev.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

* fix(e2e): scope heading locators to main content area

Cherry-picked from PR #50 to fix E2E test failures on lodash PR.

Co-Authored-By: Paperclip <noreply@paperclip.ing>

---------

Co-authored-by: Gandalf the Greybeard <gandalf@privilegedescalation.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-03 17:44:15 +00:00
7 changed files with 11525 additions and 73 deletions
-53
View File
@@ -1,53 +0,0 @@
{
"config": {
// Line length — not enforced for docs with code examples
"MD013": false,
// First line heading — files use YAML frontmatter, not headings
"MD041": false,
// Emphasis as heading — common pattern for Option 1/2/3 sections
"MD036": false,
// No duplicate heading — changelog files repeat section names intentionally
"MD024": false,
// Fenced code language — not always applicable for diagram blocks
"MD040": false,
// Table column style — table alignment is visual, not semantic
"MD060": false,
// Ordered list item prefix — number resets are intentional in documents
"MD029": false,
// No inline HTML — each elements are valid in valid Markdown
"MD033": false,
// List marker space — spacing after list markers varies by editor
"MD030": false,
// Blanks around headings — not always needed in compact docs
"MD022": false,
// Blanks around lists — not always needed in compact docs
"MD032": false,
// Blanks around fences — not always needed between adjacent blocks
"MD031": false,
// Multiple blanks — editor artifacts, not semantic
"MD012": false,
// Single title — files may have multiple H1 sections
"MD025": false,
// Trailing spaces — editor artifacts
"MD009": false,
// Bare URLs — URL shortening not always needed
"MD034": false,
// Single trailing newline — editor artifacts
"MD047": false,
// Trailing punctuation — heading punctuation is intentional
"MD026": false,
// Space in emphasis — double-asterisk bold spacing varies by renderer
"MD037": false,
// No hard tabs — some generated docs use tabs for indentation
"MD010": false,
// Code block style — generated docs may use inconsistent styles
"MD046": false,
// Comment style — generated docs have no comments
"MD048": false,
// Commands show output — shell examples intentionally show only commands
"MD014": false
},
"ignores": [
"docs/api-reference/generated/**"
]
}
-1
View File
@@ -1 +0,0 @@
docs/api-reference/generated/**
+21 -13
View File
@@ -19,16 +19,18 @@ test.describe('Intel GPU plugin smoke tests', () => {
// Should navigate to the overview route
await expect(page).toHaveURL(/\/intel-gpu$/);
await expect(page.getByRole('heading', { name: /Intel GPU — Overview/i })).toBeVisible();
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
).toBeVisible();
});
test('overview page renders GPU device list or empty state', async ({ page }) => {
await page.goto('/c/main/intel-gpu');
// Overview heading should be present
await expect(page.getByRole('heading', { name: /Intel GPU — Overview/i })).toBeVisible({
timeout: 15_000,
});
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
).toBeVisible({ timeout: 15_000 });
// Either a populated table/list or an empty-state indicator must be visible
const hasTable = await page.locator('table').first().isVisible().catch(() => false);
@@ -43,9 +45,9 @@ test.describe('Intel GPU plugin smoke tests', () => {
test('device plugins page renders or shows empty state', async ({ page }) => {
await page.goto('/c/main/intel-gpu/device-plugins');
await expect(page.getByRole('heading', { name: /Intel GPU — Device Plugins/i })).toBeVisible({
timeout: 15_000,
});
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Device Plugins' })
).toBeVisible({ timeout: 15_000 });
const hasTable = await page.locator('table').first().isVisible().catch(() => false);
const hasEmptyState = await page
@@ -61,18 +63,24 @@ test.describe('Intel GPU plugin smoke tests', () => {
// not after clicking the parent entry from the overview. Test route
// accessibility via direct navigation — each route must render its heading.
await page.goto('/c/main/intel-gpu');
await expect(page.getByRole('heading', { name: /Intel GPU — Overview/i })).toBeVisible({
timeout: 15_000,
});
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Overview' })
).toBeVisible({ timeout: 15_000 });
await page.goto('/c/main/intel-gpu/nodes');
await expect(page.getByRole('heading', { name: /Intel GPU — Nodes/i })).toBeVisible({ timeout: 15_000 });
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Nodes' })
).toBeVisible({ timeout: 15_000 });
await page.goto('/c/main/intel-gpu/pods');
await expect(page.getByRole('heading', { name: /Intel GPU — Pods/i })).toBeVisible({ timeout: 15_000 });
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Pods' })
).toBeVisible({ timeout: 15_000 });
await page.goto('/c/main/intel-gpu/metrics');
await expect(page.getByRole('heading', { name: /Intel GPU — Metrics/i })).toBeVisible({ timeout: 15_000 });
await expect(
page.locator('main').getByRole('heading', { name: 'Intel GPU — Metrics' })
).toBeVisible({ timeout: 15_000 });
});
test('plugin settings page shows intel-gpu plugin entry', async ({ page }) => {
+3 -3
View File
@@ -11600,9 +11600,9 @@
}
},
"node_modules/lodash": {
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"dev": true,
"license": "MIT"
},
+5 -1
View File
@@ -36,14 +36,18 @@
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"eslint": "^8.57.1",
"jsdom": "^24.0.0",
"prettier": "^3.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^5.3.0",
"typescript": "^5.6.2",
"vitest": "^3.0.5"
},
"overrides": {
"tar": "^7.5.11",
"undici": "^7.24.3"
"undici": "^7.24.3",
"lodash": ">=4.18.0"
}
}
+11494
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -40,7 +40,7 @@ if ! kubectl auth can-i delete configmaps -n "$E2E_NAMESPACE" --quiet 2>/dev/nul
fi
echo "=== E2E Headlamp Deployment ==="
echo " Image: ghcr.io/headlamp-plugins/headlamp:${HEADLAMP_VERSION}"
echo " Image: ghcr.io/headlamp-k8s/headlamp:${HEADLAMP_VERSION}"
echo " Namespace: $E2E_NAMESPACE"
echo " Release: $E2E_RELEASE"
@@ -101,7 +101,7 @@ spec:
securityContext: {}
containers:
- name: headlamp
image: ghcr.io/headlamp-plugins/headlamp:${HEADLAMP_VERSION}
image: ghcr.io/headlamp-k8s/headlamp:${HEADLAMP_VERSION}
imagePullPolicy: IfNotPresent
securityContext:
runAsNonRoot: true