From 42e2aa1bf5ea65a83b39ddb59142dd47ac6022f6 Mon Sep 17 00:00:00 2001 From: Ian Jennings Date: Thu, 24 Apr 2025 10:39:31 -0500 Subject: [PATCH 1/4] remove ts errors --- src/schema.ts | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/schema.ts b/src/schema.ts index 4368c26..e1ed93e 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,14 +1,25 @@ import * as vscode from 'vscode'; -import { parseDocument, Document } from 'yaml'; +import { parseDocument, isMap, isSeq, Pair, Node, Document } from 'yaml'; import { getPackagePath } from './npm'; import Ajv from 'ajv'; const findNodeByPath = (doc: Document.Parsed, path: string): any => { + const parts = path.split('/').slice(1); // Remove leading slash + let currentNode: any = doc.contents; + for (const part of parts) { + if (isMap(currentNode)) { + const pair = currentNode.items.find((item: any) => item.key?.value === part); + currentNode = pair?.value; + } else if (isSeq(currentNode)) { + const index = parseInt(part, 10); + currentNode = currentNode.items[index]; + } else { + return null; + } + } - const parts = path.split('/').slice(1); // Remove leading slash - const node = doc.getIn(parts, true); // Get original YAML node, not JSON-converted - return node?.cstNode || node?.key?.cstNode || null; + return currentNode?.cstNode ?? null; // Return CST node, which has `range` }; export function validate(context: vscode.ExtensionContext) { @@ -26,30 +37,28 @@ export function validate(context: vscode.ExtensionContext) { const diagnostics: vscode.Diagnostic[] = []; try { - const doc = parseDocument(text, { keepCstNodes: true }); - - const jsonData = doc.toJSON(); // Just for AJV + const doc = parseDocument(text, { keepSourceTokens: true }); + const jsonData = doc.toJSON(); const valid = ajv.validate(schema, jsonData); if (!valid && ajv.errors) { for (const error of ajv.errors) { const cstNode = findNodeByPath(doc, error.instancePath || ''); - const range = cstNode?.rangeAsLinePos; - if (range) { - const startPos = new vscode.Position(range.start.line, range.start.col); - const endPos = new vscode.Position(range.end.line, range.end.col); + if (cstNode?.range) { + const [startOffset, endOffset] = cstNode.range; + const startPos = document.positionAt(startOffset); + const endPos = document.positionAt(endOffset); - const diagnostic = new vscode.Diagnostic( + diagnostics.push(new vscode.Diagnostic( new vscode.Range(startPos, endPos), - error.instancePath + ' ' + error.message || 'Validation error', + `${error.instancePath || '/'} ${error.message ?? 'Validation error'}`, vscode.DiagnosticSeverity.Error - ); - diagnostics.push(diagnostic); + )); } else { diagnostics.push(new vscode.Diagnostic( - new vscode.Range(0, 0, 0, 999), - error.instancePath + ' ' + error.message || 'Validation error (no position info)', + new vscode.Range(0, 0, 0, 1), + `${error.instancePath || '/'} ${error.message ?? 'Validation error (no position info)'}`, vscode.DiagnosticSeverity.Error )); } @@ -57,7 +66,7 @@ export function validate(context: vscode.ExtensionContext) { } } catch (err: any) { diagnostics.push(new vscode.Diagnostic( - new vscode.Range(0, 0, 0, 999), + new vscode.Range(0, 0, 0, 1), `YAML Parse error: ${err.message}`, vscode.DiagnosticSeverity.Error )); From d7624a81fc2847a0c78016f21818d43761bf40c9 Mon Sep 17 00:00:00 2001 From: Ian Jennings Date: Thu, 24 Apr 2025 10:43:24 -0500 Subject: [PATCH 2/4] actually fix ts errors --- .github/workflows/testdriver.yml | 61 ++++++++++++++++++++++++++++++++ src/schema.ts | 42 ++++++++++++++-------- test.js | 0 testdriver/lifecycle/prerun.yaml | 19 ++++++++++ testdriver/testdriver.yaml | 0 5 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/testdriver.yml create mode 100644 test.js create mode 100644 testdriver/lifecycle/prerun.yaml create mode 100644 testdriver/testdriver.yaml diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml new file mode 100644 index 0000000..a3690d4 --- /dev/null +++ b/.github/workflows/testdriver.yml @@ -0,0 +1,61 @@ +name: TestDriver.ai + +permissions: + actions: read + contents: read + statuses: write + pull-requests: write + +on: + push: + branches: ["main"] + pull_request: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" + +jobs: + gather-test-files: + name: Gather Test Files + runs-on: ubuntu-latest + outputs: + test_files: ${{ steps.test_list.outputs.files }} + steps: + - name: Check out repository + uses: actions/checkout@v2 + with: + ref: ${{ github.event.ref }} + + - name: Find all test files and extract filenames + id: test_list + run: | + FILES=$(ls ./testdriver/*.yaml) + FILENAMES=$(basename -a $FILES) + FILES_JSON=$(echo "$FILENAMES" | jq -R -s -c 'split("\n")[:-1]') + echo "::set-output name=files::$FILES_JSON" + test: + needs: gather-test-files + runs-on: ubuntu-latest + strategy: + matrix: + os: [linux, windows] + test: ${{ fromJson(needs.gather-test-files.outputs.test_files) }} + fail-fast: false + name: ${{ matrix.os }} - ${{ matrix.test }} + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - uses: testdriverai/action@main + with: + os: ${{ contains(matrix.os, 'windows') && 'windows' || 'linux' }} + version: "5.3.13" + prerun: | + exit + key: ${{ secrets.TESTDRIVER_API_KEY }} + prompt: | + 1. /run testdriver/${{ matrix.test }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + FORCE_COLOR: "3" + WEBSITE_URL: "example.com" diff --git a/src/schema.ts b/src/schema.ts index e1ed93e..885d398 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -1,25 +1,31 @@ import * as vscode from 'vscode'; -import { parseDocument, isMap, isSeq, Pair, Node, Document } from 'yaml'; +import { parseDocument, isMap, isSeq, Pair, Node, Scalar, YAMLMap, YAMLSeq, Document } from 'yaml'; import { getPackagePath } from './npm'; import Ajv from 'ajv'; -const findNodeByPath = (doc: Document.Parsed, path: string): any => { - const parts = path.split('/').slice(1); // Remove leading slash - let currentNode: any = doc.contents; +const buildPathMap = (node: Node | null, path = '', map = new Map()): Map => { + if (!node) return map; + map.set(path, node); - for (const part of parts) { - if (isMap(currentNode)) { - const pair = currentNode.items.find((item: any) => item.key?.value === part); - currentNode = pair?.value; - } else if (isSeq(currentNode)) { - const index = parseInt(part, 10); - currentNode = currentNode.items[index]; - } else { - return null; + if (isMap(node)) { + for (const item of (node as YAMLMap).items) { + const key = item.key instanceof Scalar ? String(item.key.value) : String(item.key); + const newPath = `${path}/${key}`; + if (item.value && typeof item.value === 'object') { + buildPathMap(item.value as Node, newPath, map); + } } + } else if (isSeq(node)) { + (node as YAMLSeq).items.forEach((item, index) => { + const newPath = `${path}/${index}`; + if (item && typeof item === 'object') { + map.set(newPath, item as Node); + buildPathMap(item as Node, newPath, map); + } + }); } - return currentNode?.cstNode ?? null; // Return CST node, which has `range` + return map; }; export function validate(context: vscode.ExtensionContext) { @@ -38,12 +44,18 @@ export function validate(context: vscode.ExtensionContext) { try { const doc = parseDocument(text, { keepSourceTokens: true }); + const pathMap = buildPathMap(doc.contents); const jsonData = doc.toJSON(); const valid = ajv.validate(schema, jsonData); if (!valid && ajv.errors) { for (const error of ajv.errors) { - const cstNode = findNodeByPath(doc, error.instancePath || ''); + let node = pathMap.get(error.instancePath || ''); + if (!node && error.instancePath) { + const parentPath = error.instancePath.split('/').slice(0, -1).join('/'); + node = pathMap.get(parentPath || ''); + } + const cstNode = (node as any)?.cstNode; if (cstNode?.range) { const [startOffset, endOffset] = cstNode.range; diff --git a/test.js b/test.js new file mode 100644 index 0000000..e69de29 diff --git a/testdriver/lifecycle/prerun.yaml b/testdriver/lifecycle/prerun.yaml new file mode 100644 index 0000000..8ad3e0c --- /dev/null +++ b/testdriver/lifecycle/prerun.yaml @@ -0,0 +1,19 @@ +version: 5.1.1 +session: 67f00511acbd9ccac373edf7 +steps: + - prompt: launch chrome + commands: + - command: exec + lang: shell + linux: | + jumpapp google-chrome --disable-fre --no-default-browser-check --no-first-run "${TD_WEBSITE}" & + exit + mac: | + open -na "Google Chrome" --args --disable-fre --no-default-browser-check --no-first-run --disable-features=PasswordManagerEnabled "${TD_WEBSITE}" & + exit + windows: + Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "${TD_WEBSITE}" + exit + - command: wait-for-text + text: "Google Chrome" + timeout: 30000 diff --git a/testdriver/testdriver.yaml b/testdriver/testdriver.yaml new file mode 100644 index 0000000..e69de29 From 915270a29c3e18328e8d627ecfe893c876346dbd Mon Sep 17 00:00:00 2001 From: Ian Jennings Date: Thu, 24 Apr 2025 10:44:06 -0500 Subject: [PATCH 3/4] remove gen files --- .github/workflows/build.yaml | 74 -------------------------------- .github/workflows/testdriver.yml | 61 -------------------------- testdriver/lifecycle/prerun.yaml | 19 -------- testdriver/testdriver.yaml | 0 4 files changed, 154 deletions(-) delete mode 100644 .github/workflows/build.yaml delete mode 100644 .github/workflows/testdriver.yml delete mode 100644 testdriver/lifecycle/prerun.yaml delete mode 100644 testdriver/testdriver.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index 09b4758..0000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,74 +0,0 @@ -name: Build VSIX and Upload Artifact - -on: - workflow_dispatch: - push: - -jobs: - build-and-upload: - runs-on: ubuntu-latest - - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '18' - - - name: Install global dependencies - run: | - npm install -g typescript prettier eslint vsce - - - name: Install project dependencies - run: npm install - - - name: Build .vsix package - run: npm run build - - - name: Set .vsix file path - id: get_vsix - run: | - VERSION=$(jq -r '.version' package.json) - VSIX_PATH="./testdriver-${VERSION}.vsix" - if [ ! -f "$VSIX_PATH" ]; then - echo "VSIX file not found at $VSIX_PATH" - exit 1 - fi - echo "vsix_path=$VSIX_PATH" >> $GITHUB_OUTPUT - - - name: Extract version from package.json - id: get_version - run: | - VERSION=$(jq -r '.version' package.json) - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Upload .vsix as artifact - uses: actions/upload-artifact@v4 - with: - name: vscode-extension - path: ${{ steps.get_vsix.outputs.vsix_path }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitHub Release - id: create_release - uses: actions/create-release@v1 - with: - tag_name: v${{ steps.get_version.outputs.version }} - release_name: Release v${{ steps.get_version.outputs.version }} - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload .vsix to GitHub Release - uses: actions/upload-release-asset@v1 - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ${{ steps.get_vsix.outputs.vsix_path }} - asset_name: testdriver.vsix - asset_content_type: application/octet-stream - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml deleted file mode 100644 index a3690d4..0000000 --- a/.github/workflows/testdriver.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: TestDriver.ai - -permissions: - actions: read - contents: read - statuses: write - pull-requests: write - -on: - push: - branches: ["main"] - pull_request: - workflow_dispatch: - schedule: - - cron: "0 0 * * *" - -jobs: - gather-test-files: - name: Gather Test Files - runs-on: ubuntu-latest - outputs: - test_files: ${{ steps.test_list.outputs.files }} - steps: - - name: Check out repository - uses: actions/checkout@v2 - with: - ref: ${{ github.event.ref }} - - - name: Find all test files and extract filenames - id: test_list - run: | - FILES=$(ls ./testdriver/*.yaml) - FILENAMES=$(basename -a $FILES) - FILES_JSON=$(echo "$FILENAMES" | jq -R -s -c 'split("\n")[:-1]') - echo "::set-output name=files::$FILES_JSON" - test: - needs: gather-test-files - runs-on: ubuntu-latest - strategy: - matrix: - os: [linux, windows] - test: ${{ fromJson(needs.gather-test-files.outputs.test_files) }} - fail-fast: false - name: ${{ matrix.os }} - ${{ matrix.test }} - steps: - - name: Check out repository - uses: actions/checkout@v2 - - - uses: testdriverai/action@main - with: - os: ${{ contains(matrix.os, 'windows') && 'windows' || 'linux' }} - version: "5.3.13" - prerun: | - exit - key: ${{ secrets.TESTDRIVER_API_KEY }} - prompt: | - 1. /run testdriver/${{ matrix.test }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - FORCE_COLOR: "3" - WEBSITE_URL: "example.com" diff --git a/testdriver/lifecycle/prerun.yaml b/testdriver/lifecycle/prerun.yaml deleted file mode 100644 index 8ad3e0c..0000000 --- a/testdriver/lifecycle/prerun.yaml +++ /dev/null @@ -1,19 +0,0 @@ -version: 5.1.1 -session: 67f00511acbd9ccac373edf7 -steps: - - prompt: launch chrome - commands: - - command: exec - lang: shell - linux: | - jumpapp google-chrome --disable-fre --no-default-browser-check --no-first-run "${TD_WEBSITE}" & - exit - mac: | - open -na "Google Chrome" --args --disable-fre --no-default-browser-check --no-first-run --disable-features=PasswordManagerEnabled "${TD_WEBSITE}" & - exit - windows: - Start-Process "C:/Program Files/Google/Chrome/Application/chrome.exe" -ArgumentList "--start-maximized", "${TD_WEBSITE}" - exit - - command: wait-for-text - text: "Google Chrome" - timeout: 30000 diff --git a/testdriver/testdriver.yaml b/testdriver/testdriver.yaml deleted file mode 100644 index e69de29..0000000 From 6c6c8a21dd4d7f4d8bd8090245bce91448b6f03b Mon Sep 17 00:00:00 2001 From: Ian Jennings Date: Thu, 24 Apr 2025 10:44:36 -0500 Subject: [PATCH 4/4] dont delete build script --- .github/workflows/build.yaml | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..09b4758 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,74 @@ +name: Build VSIX and Upload Artifact + +on: + workflow_dispatch: + push: + +jobs: + build-and-upload: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '18' + + - name: Install global dependencies + run: | + npm install -g typescript prettier eslint vsce + + - name: Install project dependencies + run: npm install + + - name: Build .vsix package + run: npm run build + + - name: Set .vsix file path + id: get_vsix + run: | + VERSION=$(jq -r '.version' package.json) + VSIX_PATH="./testdriver-${VERSION}.vsix" + if [ ! -f "$VSIX_PATH" ]; then + echo "VSIX file not found at $VSIX_PATH" + exit 1 + fi + echo "vsix_path=$VSIX_PATH" >> $GITHUB_OUTPUT + + - name: Extract version from package.json + id: get_version + run: | + VERSION=$(jq -r '.version' package.json) + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Upload .vsix as artifact + uses: actions/upload-artifact@v4 + with: + name: vscode-extension + path: ${{ steps.get_vsix.outputs.vsix_path }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + id: create_release + uses: actions/create-release@v1 + with: + tag_name: v${{ steps.get_version.outputs.version }} + release_name: Release v${{ steps.get_version.outputs.version }} + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload .vsix to GitHub Release + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ${{ steps.get_vsix.outputs.vsix_path }} + asset_name: testdriver.vsix + asset_content_type: application/octet-stream + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}