Merge pull request #1053 from mjbvz/ridiculous-carp

Add validation scripts
This commit is contained in:
Matt Bierner
2024-06-27 10:36:21 -07:00
committed by GitHub
5 changed files with 141 additions and 33 deletions

14
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: CI
on:
pull_request:
branches: [ $default-branch ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: node ./.scripts/validate.js

View File

@ -164,16 +164,14 @@ const samples = [
{
description: 'webpack-sample',
path: 'webpack-sample',
excludeFromReadme: true,
guide: null,
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
{
description: 'esbuild-sample',
path: 'esbuild-sample',
excludeFromReadme: true,
guide: null,
guide: '/api/working-with-extensions/bundling-extension',
apis: [],
contributions: []
},
@ -276,6 +274,20 @@ const samples = [
apis: [],
contributions: []
},
{
description: 'Chat Sample',
path: 'chat-sample',
guide: null,
apis: [],
contributions: []
},
{
description: 'Notifications Sample',
path: 'notifications-sample',
guide: null,
apis: [],
contributions: []
},
{ description: 'configuration-sample', excludeFromReadme: true, path: 'configuration-sample', guide: null, apis: [], contributions: [] },
{ description: 'contentprovider-sample', excludeFromReadme: true, path: 'contentprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'nodefs-provider-sample', excludeFromReadme: true, path: 'nodefs-provider-sample', guide: null, apis: [], contributions: [] },
@ -285,10 +297,14 @@ const samples = [
{ description: 'fsconsumer-sample', excludeFromReadme: true, path: 'fsconsumer-sample', guide: null, apis: [], contributions: [] },
{ description: 'github-authentication-sample', excludeFromReadme: true, path: 'github-authentication-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-sample', excludeFromReadme: true, path: 'helloworld-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-minimal-sample', excludeFromReadme: true, path: 'helloworld-minimal-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-sample', excludeFromReadme: true, path: 'helloworld-test-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-web-sample', excludeFromReadme: true, path: 'helloworld-web-sample', guide: null, apis: [], contributions: [] },
{ description: 'helloworld-test-cli-sample', excludeFromReadme: true, path: 'helloworld-test-cli-sample', guide: null, apis: [], contributions: [] },
{ description: 'inline-completions', excludeFromReadme: true, path: 'inline-completions', guide: null, apis: [], contributions: [] },
{ description: 'notebook-renderer-react-sample', excludeFromReadme: true, path: 'notebook-renderer-react-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-format-code-action-sample', excludeFromReadme: true, path: 'notebook-format-code-action-sample', guide: null, apis: [], contributions: [] },
{ description: 'notebook-serializer-sample', excludeFromReadme: true, path: 'notebook-serializer-sample', guide: null, apis: [], contributions: [] },
{ description: 'proposed-api-sample', excludeFromReadme: true, path: 'proposed-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'virtual-document-sample', excludeFromReadme: true, path: 'virtual-document-sample', guide: null, apis: [], contributions: [] },
{ description: 'welcome-view-content-sample', excludeFromReadme: true, path: 'welcome-view-content-sample', guide: null, apis: [], contributions: [] },
@ -296,6 +312,10 @@ const samples = [
{ description: 'drop-on-document', excludeFromReadme: true, path: 'drop-on-document', guide: null, apis: [], contributions: [] },
{ description: 'uri-handler-sample', excludeFromReadme: true, path: 'uri-handler-sample', guide: null, apis: [], contributions: [] },
{ description: 'authenticationprovider-sample', excludeFromReadme: true, path: 'authenticationprovider-sample', guide: null, apis: [], contributions: [] },
{ description: 'jupyter-kernel-execution-sample', excludeFromReadme: true, path: 'jupyter-kernel-execution-sample', guide: null, apis: [], contributions: [] },
{ description: 'shell-integration-sample', excludeFromReadme: true, path: 'shell-integration-sample', guide: null, apis: [], contributions: [] },
{ description: 'tabs-api-sample', excludeFromReadme: true, path: 'tabs-api-sample', guide: null, apis: [], contributions: [] },
{ description: 'telemetry-sample', excludeFromReadme: true, path: 'telemetry-sample', guide: null, apis: [], contributions: [] },
]
/** LSP specific samples */
@ -344,6 +364,13 @@ const lspSamples = [
apis: [],
contributions: []
},
{
description: 'LSP User Input Sample',
path: 'lsp-user-input-sample',
guide: null,
apis: [],
contributions: []
},
]
/**
* LSP specific samples

View File

@ -1,5 +1,5 @@
// @ts-check
const fs = require('fs')
const { samples, lspSamples } = require('./samples')
const TABLE_HEAD = `<!-- SAMPLES_BEGIN -->
@ -12,46 +12,66 @@ const LSP_TABLE_HEAD = `<!-- LSP_SAMPLES_BEGIN -->
const LSP_TABLE_END = `<!-- LSP_SAMPLES_END -->`
const getTableRow = sample => {
const descriptionCell = `[${sample.description}](https://github.com/Microsoft/vscode-extension-samples/tree/main/${sample.path})`
let guideCell
if (!sample.guide) {
guideCell = 'N/A'
} else if (sample.guide && sample.guide.startsWith('http')) {
guideCell = sample.guide
} else {
guideCell = `[${sample.guide}](https://code.visualstudio.com${sample.guide})`
}
const descriptionCell = `[${sample.description}](https://github.com/Microsoft/vscode-extension-samples/tree/main/${sample.path})`
let guideCell
if (!sample.guide) {
guideCell = 'N/A'
} else if (sample.guide && sample.guide.startsWith('http')) {
guideCell = sample.guide
} else {
guideCell = `[${sample.guide}](https://code.visualstudio.com${sample.guide})`
}
const apis = sample.apis.map(api => {
return `[${api}](https://code.visualstudio.com/api/references/vscode-api#${api})`
})
const contributions = sample.contributions.map(c => {
return `[contributes.${c}](https://code.visualstudio.com/api/references/contribution-points#contributes.${c})`
})
const apiAndContributionCell = apis.concat(contributions).join('<br>')
const apis = sample.apis.map(api => {
return `[${api}](https://code.visualstudio.com/api/references/vscode-api#${api})`
})
const contributions = sample.contributions.map(c => {
return `[contributes.${c}](https://code.visualstudio.com/api/references/contribution-points#contributes.${c})`
})
const apiAndContributionCell = apis.concat(contributions).join('<br>')
return `| ${descriptionCell} | ${guideCell} | ${apiAndContributionCell} |`
return `| ${descriptionCell} | ${guideCell} | ${apiAndContributionCell} |`
}
const getSamplesTable = samples => {
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
return `${TABLE_HEAD.trim()}
return `${TABLE_HEAD.trim()}
${samplesMd}
${TABLE_END.trim()}`
}
const getLSPSamplesTable = samples => {
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
const samplesMd = samples.map(s => getTableRow(s)).join('\n')
return `${LSP_TABLE_HEAD.trim()}
return `${LSP_TABLE_HEAD.trim()}
${samplesMd}
${LSP_TABLE_END.trim()}`
}
const readme = fs.readFileSync('README.md', 'utf-8')
const newReadme = readme
.replace(/<!-- SAMPLES_BEGIN -->(.|\n)*<!-- SAMPLES_END -->/gm, getSamplesTable(samples.filter(x => !x.excludeFromReadme)))
.replace(/<!-- LSP_SAMPLES_BEGIN -->(.|\n)*<!-- LSP_SAMPLES_END -->/gm, getLSPSamplesTable(lspSamples))
/**
* Update the README with the latest samples.
*
* @returns {boolean} true if the README was updated, false otherwise.
*/
function updateReadme(dryRun = false) {
const readme = fs.readFileSync('README.md', 'utf-8')
const newReadme = readme
.replace(/<!-- SAMPLES_BEGIN -->(.|\n)*<!-- SAMPLES_END -->/gm, getSamplesTable(samples.filter(x => !x.excludeFromReadme)))
.replace(/<!-- LSP_SAMPLES_BEGIN -->(.|\n)*<!-- LSP_SAMPLES_END -->/gm, getLSPSamplesTable(lspSamples))
fs.writeFileSync('README.md', newReadme)
if (readme !== newReadme) {
if (!dryRun) {
fs.writeFileSync('README.md', newReadme)
}
return true;
} else {
return false;
}
}
exports.updateReadme = updateReadme;
if (require.main === module) {
updateReadme();
}

43
.scripts/validate.js Normal file
View File

@ -0,0 +1,43 @@
// @ts-check
const path = require('path');
const { samples, lspSamples } = require('./samples');
const fs = require('fs');
const root = path.join(__dirname, '..');
/**
* Validates that all samples are correctly listed in `.scripts/samples.js`.
*/
function validateSamplesAreListed() {
const allSamples = samples.concat(lspSamples);
const samplesByPath = new Map();
for (const sample of allSamples) {
samplesByPath.set(sample.path, sample);
}
for (const fileName of fs.readdirSync(root)) {
if (!fileName.endsWith('-sample') || fileName.startsWith('.')) {
continue;
}
const sampleEntry = samplesByPath.get(fileName);
if (!sampleEntry) {
throw new Error(`Sample '${fileName}' is not listed in samples.js`);
}
}
}
/**
* Validates that all samples are correctly listed in `.scripts/samples.js`.
*/
function validateReadmeUpdated() {
const { updateReadme } = require('./update-readme');
if (updateReadme(true)) {
throw new Error(`Readme not updated. Run 'node .scripts/update-readme.js' to update the readme.`);
}
}
validateSamplesAreListed();
validateReadmeUpdated();

View File

@ -51,8 +51,8 @@ You need to have [node](https://nodejs.org/en/) and [npm](https://nodejs.org/en/
| [Color Theme Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/theme-sample) | [/api/extension-guides/color-theme](https://code.visualstudio.com/api/extension-guides/color-theme) | [contributes.themes](https://code.visualstudio.com/api/references/contribution-points#contributes.themes) |
| [Product Icon Theme Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/product-icon-theme-sample) | [/api/extension-guides/product-icon-theme](https://code.visualstudio.com/api/extension-guides/product-icon-theme) | [contributes.productIconThemes](https://code.visualstudio.com/api/references/contribution-points#contributes.productIconThemes) |
| [Vim Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/vim-sample) | N/A | [commands](https://code.visualstudio.com/api/references/vscode-api#commands)<br>[StatusBarItem](https://code.visualstudio.com/api/references/vscode-api#StatusBarItem)<br>[window.createStatusBarItem](https://code.visualstudio.com/api/references/vscode-api#window.createStatusBarItem)<br>[TextEditorCursorStyle](https://code.visualstudio.com/api/references/vscode-api#TextEditorCursorStyle)<br>[window.activeTextEditor](https://code.visualstudio.com/api/references/vscode-api#window.activeTextEditor)<br>[Position](https://code.visualstudio.com/api/references/vscode-api#Position)<br>[Range](https://code.visualstudio.com/api/references/vscode-api#Range)<br>[Selection](https://code.visualstudio.com/api/references/vscode-api#Selection)<br>[TextEditor](https://code.visualstudio.com/api/references/vscode-api#TextEditor)<br>[TextEditorRevealType](https://code.visualstudio.com/api/references/vscode-api#TextEditorRevealType)<br>[TextDocument](https://code.visualstudio.com/api/references/vscode-api#TextDocument) |
| [webpack-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/webpack-sample) | [api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [esbuild-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/esbuild-sample) | [api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [webpack-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/webpack-sample) | [/api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [esbuild-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/esbuild-sample) | [/api/working-with-extensions/bundling-extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension) | |
| [Source Control Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/source-control-sample) | [/api/extension-guides/scm-provider](https://code.visualstudio.com/api/extension-guides/scm-provider) | [workspace.workspaceFolders](https://code.visualstudio.com/api/references/vscode-api#workspace.workspaceFolders)<br>[SourceControl](https://code.visualstudio.com/api/references/vscode-api#SourceControl)<br>[SourceControlResourceGroup](https://code.visualstudio.com/api/references/vscode-api#SourceControlResourceGroup)<br>[scm.createSourceControl](https://code.visualstudio.com/api/references/vscode-api#scm.createSourceControl)<br>[TextDocumentContentProvider](https://code.visualstudio.com/api/references/vscode-api#TextDocumentContentProvider)<br>[contributes.menus](https://code.visualstudio.com/api/references/contribution-points#contributes.menus) |
| [Commenting API Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/comment-sample) | N/A | |
| [Document Editing Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/document-editing-sample) | N/A | [commands](https://code.visualstudio.com/api/references/vscode-api#commands) |
@ -65,6 +65,9 @@ You need to have [node](https://nodejs.org/en/) and [npm](https://nodejs.org/en/
| [Getting Started Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/getting-started-sample) | N/A | |
| [notebook-renderer-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/notebook-renderer-sample) | [/api/extension-guides/notebook#notebook-renderer](https://code.visualstudio.com/api/extension-guides/notebook#notebook-renderer) | [contributes.notebookRenderer](https://code.visualstudio.com/api/references/contribution-points#contributes.notebookRenderer) |
| [notebook-extend-markdown-renderer-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/notebook-extend-markdown-renderer-sample) | [/api/extension-guides/notebook#notebook-renderer](https://code.visualstudio.com/api/extension-guides/notebook#notebook-renderer) | [contributes.notebookRenderer](https://code.visualstudio.com/api/references/contribution-points#contributes.notebookRenderer) |
| [jupyter-server-provider-sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/jupyter-server-provider-sample) | N/A | |
| [Chat Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/chat-sample) | N/A | |
| [Notifications Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/notifications-sample) | N/A | |
<!-- SAMPLES_END -->
### Language Server Protocol Samples
@ -78,6 +81,7 @@ You need to have [node](https://nodejs.org/en/) and [npm](https://nodejs.org/en/
| [LSP Log Streaming Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/lsp-log-streaming-sample) | N/A | |
| [LSP Multi Root Server Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/lsp-multi-server-sample) | https://github.com/Microsoft/vscode/wiki/Extension-Authoring:-Adopting-Multi-Root-Workspace-APIs#language-client--language-server | |
| [LSP Web Extension Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/lsp-web-extension-sample) | [/api/language-extensions/language-server-extension-guide](https://code.visualstudio.com/api/language-extensions/language-server-extension-guide) | |
| [LSP User Input Sample](https://github.com/Microsoft/vscode-extension-samples/tree/main/lsp-user-input-sample) | N/A | |
<!-- LSP_SAMPLES_END -->
## License