diff --git a/.github/workflows/create-manifest.yml b/.github/workflows/create-manifest.yml new file mode 100644 index 000000000..c23de79b5 --- /dev/null +++ b/.github/workflows/create-manifest.yml @@ -0,0 +1,54 @@ +name: Create Manifest E2E + +on: + push: + pull_request: + +jobs: + create-manifest: + name: Run on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: package-lock.json + + - name: Install dependencies (workspaces) + run: npm i + + - name: Run create-manifest (with parameters) + env: + NODE_ENV: test + working-directory: packages/create-manifest + run: >- + node --loader ts-node/esm bin/dev.js + ci-test-${{ runner.os }} + --backendFile=https://raw.githubusercontent.com/mnfst/manifest/main/packages/create-manifest/assets/standalone/manifest.yml + + - name: Verify generated files and parameters + run: node scripts/verify-create-manifest.mjs packages/create-manifest/ci-test-${{ runner.os }} + + - name: Run create-manifest with windsurf flag + env: + NODE_ENV: test + working-directory: packages/create-manifest + run: >- + node --loader ts-node/esm bin/dev.js + ci-test-windsurf-${{ runner.os }} + --windsurf + --backendFile=https://raw.githubusercontent.com/mnfst/manifest/main/packages/create-manifest/assets/standalone/manifest.yml + + - name: Verify windsurf flag functionality + run: node scripts/verify-create-manifest.mjs packages/create-manifest/ci-test-windsurf-${{ runner.os }} --expect-windsurf diff --git a/scripts/verify-create-manifest.mjs b/scripts/verify-create-manifest.mjs new file mode 100644 index 000000000..cab34c8fb --- /dev/null +++ b/scripts/verify-create-manifest.mjs @@ -0,0 +1,103 @@ +#!/usr/bin/env node +import fs from 'node:fs' +import path from 'node:path' + +function fail(msg) { + console.error(`FAIL: ${msg}`) + process.exitCode = 1 +} + +function ok(msg) { + console.log(`OK: ${msg}`) +} + +const args = process.argv.slice(2) +if (args.length < 1) { + console.error('Usage: node scripts/verify-create-manifest.mjs [--expect-windsurf]') + process.exit(2) +} + +const projectName = args[0] +const expectWindsurf = args.includes('--expect-windsurf') + +const base = path.resolve(projectName) + +// sanity existence checks +if (fs.existsSync(base)) { + ok(`project folder exists: ${base}`) +} else { + fail(`project folder missing: ${base}`) +} + +const mustExist = [ + 'manifest.yml', + '.manifest', + '.vscode', + '.vscode/extensions.json', + '.vscode/settings.json', + '.gitignore', + 'package.json', + '.env', + 'README.md' +] + +for (const rel of mustExist) { + const p = path.join(base, rel) + if (fs.existsSync(p)) { + ok(`${rel} exists`) + } else { + fail(`${rel} missing`) + } +} + +// Check manifest.yml has content and expected key from the provided backend file +try { + const manifest = fs.readFileSync(path.join(base, 'manifest.yml'), 'utf8') + if (manifest.trim().length > 0 && /entities:\s*$/m.test(manifest)) { + ok('manifest.yml seems valid (contains entities)') + } else { + fail('manifest.yml does not contain expected content') + } +} catch (e) { + fail(`cannot read manifest.yml: ${e}`) +} + +// Ensure the dependency was added +try { + const pkg = JSON.parse(fs.readFileSync(path.join(base, 'package.json'), 'utf8')) + if (pkg?.dependencies?.manifest) { + ok('package.json includes manifest dependency') + } else { + fail('package.json missing manifest dependency') + } +} catch (e) { + fail(`cannot read/parse package.json: ${e}`) +} + +// Verify .gitignore contains expected lines +try { + const gi = fs.readFileSync(path.join(base, '.gitignore'), 'utf8') + const required = ['node_modules', '.env', 'public', '.manifest'] + for (const entry of required) { + if (gi.includes(entry)) { + ok(`.gitignore contains ${entry}`) + } else { + fail(`.gitignore missing ${entry}`) + } + } +} catch (e) { + fail(`cannot read .gitignore: ${e}`) +} + +// Optionally verify a flag effect (works with parameters) +if (expectWindsurf) { + const windsurfFile = path.join(base, '.windsurf', 'rules', 'manifest.md') + if (fs.existsSync(windsurfFile)) { + ok('windsurf rules created via flag') + } else { + fail('windsurf rules missing though flag was provided') + } +} + +process.exit(process.exitCode ?? 0) +