* feat(yaml-validator)!: unify flow, schedule, and trigger validation - replace FlowValidator with WindmillYamlValidator.validate(doc, target) - generate schedule/trigger schemas from backend OpenAPI and OpenFlow refs - add schedule/trigger/filename-target tests and update AI agent fixtures - bump windmill-yaml-validator to 2.0.0 BREAKING CHANGE: FlowValidator and validateFlow() are replaced by WindmillYamlValidator.validate(doc, target). * add lint command * add deno-compat script and docs for local yaml-validator testing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: make nullable fields pass yaml validation Add nullable: true to static_asset_config and authentication_resource_path in HttpTrigger schema. Post-process generated JSON schemas to add null to enums with nullable: true (AJV doesn't handle OpenAPI 3.0 nullable + enum). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add nullable to all Option<T> fields in trigger and schedule OpenAPI schemas Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(frontend): handle nullable fields from updated OpenAPI types Add ?? undefined coalescing at assignment sites where generated types now include | null from the OpenAPI nullable additions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(lint): show allowed values in enum validation errors Instead of "must be equal to one of the allowed values", now shows "must be one of: 'r', 'w', 'rw'" for enum validation failures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add nullable to Edit/New trigger and schedule OpenAPI schemas Ensures create/update request body types accept null for the same fields that GET response types return as nullable, enabling clean round-tripping without type mismatches. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * use published package * publish * refactor(lint): remove unused --includes/--excludes/--extra-includes CLI options These options were defined but never wired to the file filtering logic. The lint command still respects includes/excludes from wmill.yaml via mergeConfigWithConfigFile. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(lint): handle additionalProperties errors and expand test coverage Add formatting for AJV additionalProperties keyword to show the unknown property name. Add unit tests for all formatValidationError branches and integration tests for --json report shape, --fail-on-warn with mixed files, non-existent directory, and enum error output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add realistic validator tests for schedules, triggers, and edge cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add email trigger validation support Add email trigger schema generation, validation, and linting. Email triggers are no longer skipped with a warning — they are validated like all other trigger types. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore(cli): bump windmill-yaml-validator to 1.1.1 (email trigger support) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * publish * rm * fix: address PR review feedback for lint command - Add email to trigger kinds test loop instead of separate test - Add email to ValidationTarget docs in README - Type formatYamlDiagnostics param directly instead of unsafe cast - Destructure json option before mergeConfigWithConfigFile for clarity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(cli): add --lint option to sync push command Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.2 KiB
Bash
Executable File
97 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
script_dirpath="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
output_dirpath="${script_dirpath}/src/gen"
|
|
tmp_dirpath="$(mktemp -d)"
|
|
|
|
cleanup() {
|
|
rm -rf "${tmp_dirpath}"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
mkdir -p "${output_dirpath}"
|
|
mkdir -p "${output_dirpath}/triggers"
|
|
|
|
node -e "
|
|
const fs = require('fs');
|
|
const yaml = require('js-yaml');
|
|
|
|
const openflowPath = '${script_dirpath}/../openflow.openapi.yaml';
|
|
const backendPath = '${script_dirpath}/../backend/windmill-api/openapi.yaml';
|
|
const openflowOutputPath = '${output_dirpath}/openflow.json';
|
|
const backendOutputPath = '${tmp_dirpath}/backend-openapi.json';
|
|
|
|
const openflowData = yaml.load(fs.readFileSync(openflowPath, 'utf8'));
|
|
const backendData = yaml.load(fs.readFileSync(backendPath, 'utf8'));
|
|
|
|
fs.writeFileSync(openflowOutputPath, JSON.stringify(openflowData, null, 2) + '\\n');
|
|
fs.writeFileSync(backendOutputPath, JSON.stringify(backendData, null, 2) + '\\n');
|
|
"
|
|
|
|
# Remove discriminator mapping from openflow.json as it's not supported by ajv
|
|
node -e "
|
|
const fs = require('fs');
|
|
const filePath = '${output_dirpath}/openflow.json';
|
|
|
|
try {
|
|
const schema = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
|
|
function removeMapping(obj) {
|
|
if (obj && typeof obj === 'object') {
|
|
if (obj.discriminator?.mapping) delete obj.discriminator.mapping;
|
|
for (const v of Object.values(obj)) removeMapping(v);
|
|
}
|
|
}
|
|
|
|
removeMapping(schema);
|
|
|
|
// Remove discriminator entirely from ToolValue as it doesn't work with allOf in FlowModuleTool
|
|
if (schema.components?.schemas?.ToolValue?.discriminator) {
|
|
delete schema.components.schemas.ToolValue.discriminator;
|
|
console.log('Removed discriminator from ToolValue schema');
|
|
}
|
|
|
|
fs.writeFileSync(filePath, JSON.stringify(schema, null, 2));
|
|
console.log('Removed discriminator mappings from openflow.json');
|
|
} catch (e) {
|
|
console.error('Error removing discriminator mappings:', e);
|
|
}
|
|
"
|
|
|
|
node "${script_dirpath}/scripts/generate-resource-schemas.js" \
|
|
"${tmp_dirpath}/backend-openapi.json" \
|
|
"${output_dirpath}/openflow.json" \
|
|
"${output_dirpath}"
|
|
|
|
# AJV does not handle OpenAPI 3.0 `nullable: true` combined with `enum` — null must
|
|
# be explicitly listed in the enum for validation to accept null values.
|
|
# We post-process all generated JSON schemas to add null to such enums.
|
|
node -e "
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
function addNullToNullableEnums(obj) {
|
|
if (!obj || typeof obj !== 'object') return;
|
|
if (Array.isArray(obj)) { obj.forEach(addNullToNullableEnums); return; }
|
|
if (obj.nullable === true && Array.isArray(obj.enum) && !obj.enum.includes(null)) {
|
|
obj.enum.push(null);
|
|
}
|
|
for (const v of Object.values(obj)) addNullToNullableEnums(v);
|
|
}
|
|
|
|
const files = [
|
|
'${output_dirpath}/openflow.json',
|
|
'${output_dirpath}/schedule.json',
|
|
...fs.readdirSync('${output_dirpath}/triggers').map(f => path.join('${output_dirpath}/triggers', f))
|
|
].filter(f => f.endsWith('.json'));
|
|
|
|
for (const file of files) {
|
|
const schema = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
addNullToNullableEnums(schema);
|
|
fs.writeFileSync(file, JSON.stringify(schema, null, 2) + '\n');
|
|
}
|
|
console.log('Added null to nullable enums in generated schemas');
|
|
"
|