Skip to content

Commit

Permalink
refactor(*): make build result CSP compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
sumimakito committed Feb 26, 2025
1 parent 348f381 commit d596940
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 38 deletions.
1 change: 1 addition & 0 deletions .ci/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ services:
KONG_ADMIN_LISTEN: "0.0.0.0:8001"
KONG_ANONYMOUS_REPORTS: "off"
KONG_ROUTER_FLAVOR:
KONG_ADMIN_GUI_CSP_HEADER:
restart: always
depends_on:
&kong-depends_on
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/.reusable_e2e_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ on:
load-test-image-from-artifact:
type: boolean
default: false
enable-csp-header:
type: boolean
default: false

jobs:
e2e-tests:
Expand Down Expand Up @@ -78,7 +81,7 @@ jobs:
uses: actions/download-artifact@v4
with:
name: docker-test-image

- name: Load test image
if: ${{ inputs.load-test-image-from-artifact }}
run: |
Expand All @@ -98,6 +101,7 @@ jobs:
env:
GATEWAY_IMAGE: ${{ inputs.gateway-image }}
KONG_ROUTER_FLAVOR: ${{ matrix.router-flavor }}
KONG_ADMIN_GUI_CSP_HEADER: ${{ inputs.enable-csp-header && 'on' || 'off' }}
run: |
_compose_exit=0
docker compose -f .ci/docker-compose.yml up -d kong --wait || _compose_exit=$?
Expand All @@ -119,6 +123,13 @@ jobs:
docker compose -f .ci/docker-compose.yml logs
exit $_compose_exit
- name: Ensure CSP header
if: ${{ inputs.enable-csp-header }}
run: |
header_lines=$(curl -s -D - -o /dev/null http://localhost:8002/index.html)
echo $header_lines
echo $header_lines | grep -q "Content-Security-Policy: default-src 'self';"
- name: Run E2E tests
timeout-minutes: 10
env:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,24 @@ jobs:
uses: ./.github/workflows/.reusable_test_image.yml
needs: build
secrets: inherit
with:
gateway-image: docker.io/kong/kong-dev:pr-14287-ubuntu # TODO: Revert this line before merging

e2e-tests:
name: E2E Tests
needs: build-test-image
uses: ./.github/workflows/.reusable_e2e_tests.yml
secrets: inherit
with:
gateway-image: ${{ needs.build-test-image.outputs.image }}
load-test-image-from-artifact: true

e2e-tests-csp-on:
name: E2E Tests (CSP on)
needs: build-test-image
uses: ./.github/workflows/.reusable_e2e_tests.yml
secrets: inherit
with:
gateway-image: ${{ needs.build-test-image.outputs.image }}
load-test-image-from-artifact: true
enable-csp-header: true
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@material-design-icons/font": "^0.14.13",
"axios": "^1.7.7",
"dayjs": "^1.11.13",
"monaco-editor": "0.52.0",
"monaco-editor": "0.52.2",
"pinia": "^3.0.1",
"vue": "^3.5.12",
"vue-router": "^4.4.5"
Expand Down Expand Up @@ -76,7 +76,6 @@
"typescript": "^5.4.5",
"vite": "^6.1.1",
"vite-plugin-html": "^3.2.2",
"vite-plugin-monaco-editor": "^1.1.0",
"vue-tsc": "^2.1.4"
},
"browserslist": [
Expand Down
30 changes: 4 additions & 26 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { registerGlobalComponents } from './registerGlobalComponents'
import './styles/index'
import { createPinia } from 'pinia'

// This only sets up worker initializers. They will be lazy-loaded when needed.
import '@/monaco-workers'

const i18n = createI18n<typeof english>('en-us', english, { isGlobal: true })

const app = createApp(App)
Expand Down
9 changes: 9 additions & 0 deletions src/monaco-workers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Injecting workers for monaco-editor

import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'

self.MonacoEnvironment = {
getWorker() {
return new EditorWorker()
},
}
9 changes: 9 additions & 0 deletions tests/playwright/base-test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { test as pwTest, type BrowserContext, type Page } from '@playwright/test'
import config from '@pw-config'
import { withNavigation } from './commands/withNavigation'
import { failOnCSPViolations } from './helpers/console'

export interface SharedState {
context?: BrowserContext | null
Expand Down Expand Up @@ -69,7 +70,15 @@ const baseTest = (sharedState: SharedState | null = {}) => {
// make playwright always run tests from first to last when retry happens
t.describe.configure({ mode: 'serial' })

let unregisterCSPViolationWatcher: () => void | undefined
t.beforeAll(async ({ page })=>{
if (config.use.failOnCSPViolations) {
unregisterCSPViolationWatcher = failOnCSPViolations(page)
}
})

t.afterAll(async ({ context, page }) => {
unregisterCSPViolationWatcher?.()
await page.close()
await context.close()
})
Expand Down
16 changes: 16 additions & 0 deletions tests/playwright/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
KM_TEST_GUI_URL?: string
// We have fallback for this env variable in .env
KM_TEST_API_URL: string

/**
* String-presented boolean
*/
KM_TEST_FAIL_ON_CSP_VIOLATIONS?: string
}
}
}

export {}
15 changes: 15 additions & 0 deletions tests/playwright/helpers/console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,18 @@ export const observeConsole = (page: Page) => {

return [messages, teardown] as const
}

export const failOnCSPViolations = (page: Page): () => void => {
const message = (message: ConsoleMessage) => {
if ((message.type() === 'error' || message.type() === 'warning') && /violates.*Content Security Policy/.test(message.text())) {
throw new Error(message.text())
}
}
console.log('[Console Helper] Registered CSP violation watcher. Tests will fail if a CSP violation is detected.')
page.on('console', message)

return () => {
page.off('console', message)
console.log('[Console Helper] CSP violation watcher unregistered.')
}
}
5 changes: 4 additions & 1 deletion tests/playwright/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as dotenv from 'dotenv'

dotenv.config({ path: '../../.env' })

const config: PlaywrightTestConfig = {
const config: PlaywrightTestConfig<{
failOnCSPViolations: boolean
}> = {
reporter: [['junit', { outputFile: './test-results/playwright.xml' }]],
testDir: '.', // Using default value here. Let's keep it here to prevent it from being forgotten in future migrations.
retries: 1,
Expand All @@ -20,6 +22,7 @@ const config: PlaywrightTestConfig = {
contextOptions: {
permissions: ['clipboard-read', 'clipboard-write'],
},
failOnCSPViolations: /^1|true$/i.test(process.env.KM_TEST_FAIL_ON_CSP_VIOLATIONS ?? ''),
},
}

Expand Down
5 changes: 3 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
"tests/*": ["tests/*"],
"config": ["src/config.ts"]
},
"moduleResolution": "node",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"allowJs": true,
"noImplicitAny": false,
"types": [
"vite/client"
"vite/client",
"monaco-editor",
]
},
"exclude": ["node_modules", "dist", "coverage", "tests"]
Expand Down
6 changes: 0 additions & 6 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import path from 'path'
import autoprefixer from 'autoprefixer'
import { createHtmlPlugin } from 'vite-plugin-html'
import { visualizer } from 'rollup-plugin-visualizer'
import monacoEditorPlugin from 'vite-plugin-monaco-editor'

const basePath = process.env.NODE_ENV !== 'production' || process.env.DISABLE_BASE_PATH === 'true' ? '/' : '/__km_base__/'

Expand Down Expand Up @@ -33,11 +32,6 @@ export default defineConfig({
},
},
}),
// See: https://github.com/vdesjs/vite-plugin-monaco-editor/issues/21
// eslint-disable-next-line @typescript-eslint/no-explicit-any
((monacoEditorPlugin as any).default as typeof monacoEditorPlugin)({
languageWorkers: ['editorWorkerService'],
}),
visualizer({
filename: path.resolve(__dirname, 'bundle-analyzer/stats-treemap.html'),
template: 'treemap', // sunburst|treemap|network
Expand Down

0 comments on commit d596940

Please sign in to comment.