diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 000000000..b8826f538 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,47 @@ +name: Examples astro check + +on: + push: + branches: + - main + pull_request: + paths: + - 'examples/**' + - '.github/workflows/check.yml' + - 'scripts/smoke/check.js' + - 'packages/astro/src/@types/astro.ts' + +env: + ASTRO_TELEMETRY_DISABLED: true + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ secrets.TURBO_TEAM }} + FORCE_COLOR: true + +jobs: + check: + name: astro check + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v3 + + - name: Setup PNPM + uses: pnpm/action-setup@v2.2.1 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Build + run: pnpm run build + + - name: Status + run: git status + + - name: astro check + run: pnpm run test:check-examples diff --git a/examples/framework-lit/src/pages/index.astro b/examples/framework-lit/src/pages/index.astro index 4f0dbc309..d193842a0 100644 --- a/examples/framework-lit/src/pages/index.astro +++ b/examples/framework-lit/src/pages/index.astro @@ -19,6 +19,11 @@ import { MyCounter } from '../components/my-counter.js';

Test app

- + + {/** + * Our VS Code extension does not currently properly typecheck attributes on Lit components + * As such, the following code will result in a TypeScript error inside the editor, nonetheless, it works in Astro! + * @ts-expect-error */} + diff --git a/examples/non-html-pages/src/pages/index.astro b/examples/non-html-pages/src/pages/index.astro index 18fe9b9da..921400acd 100644 --- a/examples/non-html-pages/src/pages/index.astro +++ b/examples/non-html-pages/src/pages/index.astro @@ -12,9 +12,11 @@ // can fetch them directly in the browser. const response = await fetch(`/about.json`); const data = await response.json(); - document.getElementById( - 'result' - ).innerHTML = `Load complete!
Built with: ${data.name}!`; + const resultHeader = document.getElementById('result'); + + if (resultHeader) { + resultHeader.innerHTML = `Load complete!
Built with: ${data.name}!`; + } diff --git a/examples/portfolio/src/components/PortfolioPreview.astro b/examples/portfolio/src/components/PortfolioPreview.astro index 3d0a91522..bf59f100f 100644 --- a/examples/portfolio/src/components/PortfolioPreview.astro +++ b/examples/portfolio/src/components/PortfolioPreview.astro @@ -1,4 +1,11 @@ --- +import type { MarkdownInstance } from 'astro'; +import type { Project } from '../types'; + +interface Props { + project: MarkdownInstance +} + const { frontmatter, url } = Astro.props.project; --- diff --git a/examples/portfolio/src/layouts/project.astro b/examples/portfolio/src/layouts/project.astro index f02f89c74..c4025dc39 100644 --- a/examples/portfolio/src/layouts/project.astro +++ b/examples/portfolio/src/layouts/project.astro @@ -2,11 +2,16 @@ import MainHead from '../components/MainHead.astro'; import Footer from '../components/Footer.astro'; import Nav from '../components/Nav.astro'; +import type { Project } from '../types'; + +interface Props { + content: Project; +} const { content } = Astro.props; --- - +
- +

Product Listing

diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index f85137fd2..4ffa96751 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -11,8 +11,9 @@ "astro": "astro" }, "dependencies": { - "astro": "^1.4.7", "@astrojs/tailwind": "^2.0.2", + "@types/canvas-confetti": "^1.4.3", + "astro": "^1.4.7", "autoprefixer": "^10.4.7", "canvas-confetti": "^1.5.1", "postcss": "^8.4.14", diff --git a/examples/with-tailwindcss/src/components/Button.astro b/examples/with-tailwindcss/src/components/Button.astro index ef7af656b..79060699b 100644 --- a/examples/with-tailwindcss/src/components/Button.astro +++ b/examples/with-tailwindcss/src/components/Button.astro @@ -11,5 +11,9 @@ diff --git a/package.json b/package.json index 675d305ce..e1d71d61c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "test": "turbo run test --output-logs=new-only --concurrency=1 --filter=astro --filter=create-astro --filter=\"@astrojs/*\"", "test:match": "cd packages/astro && pnpm run test:match", "test:smoke": "turbo run build --filter=\"@example/*\" --filter=\"astro.build\" --filter=\"docs\" --output-logs=new-only --concurrency=1", + "test:check-examples": "node ./scripts/smoke/check.js", "test:vite-ci": "turbo run test --filter=astro --output-logs=new-only --no-deps --concurrency=1", "test:e2e": "cd packages/astro && pnpm playwright install && pnpm run test:e2e", "test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00cc78cb5..d0b656a7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -324,6 +324,7 @@ importers: examples/with-tailwindcss: specifiers: '@astrojs/tailwind': ^2.0.2 + '@types/canvas-confetti': ^1.4.3 astro: ^1.4.7 autoprefixer: ^10.4.7 canvas-confetti: ^1.5.1 @@ -331,6 +332,7 @@ importers: tailwindcss: ^3.0.24 dependencies: '@astrojs/tailwind': link:../../packages/integrations/tailwind + '@types/canvas-confetti': 1.4.3 astro: link:../../packages/astro autoprefixer: 10.4.12_postcss@8.4.17 canvas-confetti: 1.5.1 @@ -3435,6 +3437,7 @@ importers: kleur: ^4.1.4 svelte: ^3.48.0 tar: ^6.1.11 + tsconfig-resolver: ^3.0.1 dependencies: '@astrojs/webapi': link:../packages/webapi adm-zip: 0.5.9 @@ -3444,6 +3447,8 @@ importers: kleur: 4.1.5 svelte: 3.50.1 tar: 6.1.11 + devDependencies: + tsconfig-resolver: 3.0.1 packages: @@ -9397,6 +9402,10 @@ packages: '@types/node': 18.8.2 dev: true + /@types/canvas-confetti/1.4.3: + resolution: {integrity: sha512-UwFPTsW1ZwVyo/ETp4hPSikSD7yl2V42E3VWBF5P/0+DHO4iajyceWv7hfNdZ2AX5tkZnuViiBWOqyCPohU2FQ==} + dev: false + /@types/chai-as-promised/7.1.5: resolution: {integrity: sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==} dependencies: @@ -9521,7 +9530,6 @@ packages: /@types/json5/0.0.30: resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==} - dev: false /@types/mdast/3.0.10: resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} @@ -13620,7 +13628,6 @@ packages: resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} engines: {node: '>=6'} hasBin: true - dev: false /jsonc-parser/2.3.1: resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} @@ -16803,7 +16810,6 @@ packages: /strip-bom/4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} - dev: false /strip-comments/2.0.1: resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} @@ -17157,7 +17163,6 @@ packages: resolve: 1.22.1 strip-bom: 4.0.0 type-fest: 0.13.1 - dev: false /tsconfig/7.0.0: resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==} diff --git a/scripts/package.json b/scripts/package.json index 5759362d1..39f58947a 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -16,5 +16,8 @@ "kleur": "^4.1.4", "svelte": "^3.48.0", "tar": "^6.1.11" + }, + "devDependencies": { + "tsconfig-resolver": "^3.0.1" } } diff --git a/scripts/smoke/check.js b/scripts/smoke/check.js new file mode 100644 index 000000000..447a76edc --- /dev/null +++ b/scripts/smoke/check.js @@ -0,0 +1,84 @@ +// @ts-check + +import { spawn } from 'child_process'; +import { readdirSync, readFileSync, writeFileSync } from 'fs'; +import * as path from 'path'; +import { tsconfigResolverSync } from 'tsconfig-resolver'; + +function checkExamples() { + let examples = readdirSync('./examples', { withFileTypes: true }); + examples = examples.filter((dirent) => dirent.isDirectory()); + + console.log(`Running astro check on ${examples.length} examples...`); + + Promise.all( + examples.map( + (example) => + new Promise((resolve) => { + const originalConfig = prepareExample(example.name); + let data = ''; + const child = spawn('node', ['../../packages/astro/astro.js', 'check'], { + cwd: path.join('./examples', example.name), + env: { ...process.env, FORCE_COLOR: 'true' }, + }); + + child.stdout.on('data', function (buffer) { + data += buffer.toString(); + }); + + child.on('exit', (code) => { + if (code !== 0) { + console.error(data); + } + if (originalConfig) { + resetExample(example.name, originalConfig); + } + resolve(code); + }); + }) + ) + ).then((codes) => { + if (codes.some((code) => code !== 0)) { + process.exit(1); + } + + console.log("No errors found!"); + }); +} + +/** + * @param {string} examplePath + */ +function prepareExample(examplePath) { + const tsconfigPath = path.join('./examples/', examplePath, 'tsconfig.json'); + const tsconfig = tsconfigResolverSync({ filePath: tsconfigPath, cache: false }); + let originalConfig = undefined; + + if (tsconfig.exists) { + tsconfig.config.extends = 'astro/tsconfigs/strictest'; + originalConfig = readFileSync(tsconfigPath).toString(); + + if (!tsconfig.config.compilerOptions) { + tsconfig.config.compilerOptions = {}; + } + + tsconfig.config.compilerOptions = Object.assign(tsconfig.config.compilerOptions, { + types: tsconfig.config.compilerOptions.types ?? [], // Speeds up tests + }); + } + + writeFileSync(tsconfigPath, JSON.stringify(tsconfig.config)); + + return originalConfig; +} + +/** + * @param {string} examplePath + * @param {string} originalConfig + */ +function resetExample(examplePath, originalConfig) { + const tsconfigPath = path.join('./examples/', examplePath, 'tsconfig.json'); + writeFileSync(tsconfigPath, originalConfig); +} + +checkExamples();