mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 08:00:59 +00:00
4f998cc231
* feat: add GitHub as a native trigger service Add GitHub webhooks as a native trigger, allowing users to trigger scripts/flows from repository events (push, PR, issues, etc.) via OAuth-based webhook management. Backend: - DB migration adding 'github' to native_trigger_service, TRIGGER_KIND, and job_trigger_kind enums - Full External trait implementation: create/update/delete/get webhooks, per-trigger sync verification, webhook payload preparation - Paginated repos endpoint (up to 1000 repos) - OAuth flow with admin:repo_hook and read:user scopes Frontend: - GitHub trigger form with repo picker and MultiSelect event selector - Workspace integration settings with setup instructions - Trigger badge, editor, and wrapper integration - GithubIcon updated to support size/class props (matching other icons) - Hub template reference for starter scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: show GitHub in sidebar when triggers exist Add github_used to the getUsedTriggers endpoint so the sidebar picks up GitHub as an active trigger kind. Also document this step in the native- trigger skill so future services don't miss it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: on-demand GitHub repo search instead of bulk fetch Replace the upfront pagination through all repos with a debounced search flow: load 30 most-recently-updated repos by default, then query GitHub's /search/repositories API (scoped to the authenticated user via user:@me and restricted to name matches via in:name) as the user types. Frontend uses runed's Debounced + resource to wire the Select's filterText to the backend query with 300ms debouncing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: request `repo` OAuth scope to list private GitHub repos `admin:repo_hook` grants webhook management but not repo listing — so /user/repos and /search/repositories returned only public repos. Switch to `repo` (full repo scope, which is a superset and also covers webhook management). Users who already connected GitHub need to disconnect and reconnect to pick up the broader scope. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * revert: fetch all GitHub repos upfront instead of searching on demand Revert the debounced search flow — paginate through /user/repos (up to 1000) on form open. Simpler UX: repos are all there from the start, the Select's built-in client-side filter handles finding one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: typed 404 detection + add GitHub flow template reference Replace fragile e.to_string().contains("404") matching with a proper http_error_status helper that downcasts through anyhow to the typed HttpRequestError and reads the StatusCode. Also wire the hub flow template (id 80) into NATIVE_TRIGGER_SERVICES. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update GitHub script template hub ID to 28202 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: align GitHub trigger with Nextcloud/Google patterns Addresses review feedback from Claude and cubic. Backend: - `delete()` now only swallows NotFound (DB missing row) and 404 (API webhook already deleted); non-404/DB errors propagate so callers know cleanup failed. Matches Nextcloud's delete pattern exactly. - `get_owner_repo_from_db` returns `Result<Option<(String, String)>>` instead of an error on missing row (matches Google's delete flow). Frontend: - `loading: boolean` (required) + `$bindable()` with no default — matches Nextcloud, satisfies CLAUDE.md banned-pattern rule. - Wrap `loadRepos()` in `$effect` reacting to `$workspaceStore` so repos load once the store is available and refresh on workspace switch. - Replace raw `fetch('/api/.../native_triggers/github/repos')` with the generated `NativeTriggerService.listGithubRepos(...)` typed client. Adds `/repos` route + `GithubRepoEntry` schema to openapi.yaml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
132 lines
3.4 KiB
JavaScript
132 lines
3.4 KiB
JavaScript
import { sveltekit } from '@sveltejs/kit/vite'
|
|
import { readFileSync } from 'fs'
|
|
import { fileURLToPath } from 'url'
|
|
import mkcert from 'vite-plugin-mkcert'
|
|
|
|
const file = fileURLToPath(new URL('package.json', import.meta.url))
|
|
const json = readFileSync(file, 'utf8')
|
|
const version = JSON.parse(json)
|
|
|
|
const remoteUrl =
|
|
process.env.REMOTE ??
|
|
(process.env.BACKEND_PORT
|
|
? `http://localhost:${process.env.BACKEND_PORT}`
|
|
: 'https://app.windmill.dev/')
|
|
|
|
let plugin = {
|
|
name: 'configure-response-headers',
|
|
configureServer: (server) => {
|
|
server.middlewares.use((_req, res, next) => {
|
|
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin')
|
|
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp')
|
|
next()
|
|
})
|
|
}
|
|
}
|
|
|
|
/** @type {import('vite').UserConfig} */
|
|
const config = {
|
|
server: {
|
|
https: process.env.HTTPS === 'true',
|
|
allowedHosts: [
|
|
'localhost',
|
|
'127.0.0.1',
|
|
'0.0.0.0',
|
|
'rubendev.wimill.xyz',
|
|
'windmill.xyz',
|
|
'app.windmill.xyz',
|
|
'public.windmill.xyz',
|
|
'hugo.ngrok.pro'
|
|
],
|
|
port: parseInt(process.env.FRONTEND_PORT) || 3000,
|
|
cors: { origin: '*' },
|
|
proxy: {
|
|
'^/\\.well-known/.*': {
|
|
target: remoteUrl,
|
|
changeOrigin: true,
|
|
cookieDomainRewrite: 'localhost'
|
|
},
|
|
'^/api/w/[^/]+/s3_proxy/.*': {
|
|
target: remoteUrl,
|
|
changeOrigin: false, // Important for signature to be correct
|
|
cookieDomainRewrite: 'localhost',
|
|
configure: (proxy, options) => {
|
|
proxy.on('proxyReq', (proxyReq, req, res) => {
|
|
// Prevent collapsing slashes during URL normalization
|
|
const originalPath = req.url
|
|
|
|
proxyReq.path = originalPath
|
|
})
|
|
}
|
|
},
|
|
'^/api/.*': {
|
|
target: remoteUrl,
|
|
changeOrigin: true,
|
|
cookieDomainRewrite: 'localhost'
|
|
},
|
|
'^/ws/.*': {
|
|
target: process.env.REMOTE_LSP ?? process.env.REMOTE_EXTRA ?? 'https://app.windmill.dev',
|
|
changeOrigin: true,
|
|
ws: true
|
|
},
|
|
'^/ws_mp/.*': {
|
|
target: process.env.REMOTE_MP ?? process.env.REMOTE_EXTRA ?? 'https://app.windmill.dev',
|
|
changeOrigin: true,
|
|
ws: true
|
|
},
|
|
'^/ws_debug/.*': {
|
|
target: process.env.REMOTE_DEBUG ?? process.env.REMOTE_EXTRA ?? 'https://app.windmill.dev',
|
|
changeOrigin: true,
|
|
ws: true
|
|
},
|
|
'^/ui_builder/.*': {
|
|
target: 'http://localhost:4000',
|
|
changeOrigin: true,
|
|
headers: {
|
|
'Cross-Origin-Opener-Policy': 'same-origin',
|
|
'Cross-Origin-Embedder-Policy': 'require-corp',
|
|
'Cross-Origin-Resource-Policy': 'cross-origin'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
preview: { port: 3001 },
|
|
plugins: [sveltekit(), ...(process.env.HTTPS === 'true' ? [mkcert()] : []), plugin],
|
|
define: { __pkg__: version },
|
|
optimizeDeps: {
|
|
include: ['highlight.js', 'highlight.js/lib/core', 'monaco-vim'],
|
|
exclude: [
|
|
'@codingame/monaco-vscode-standalone-typescript-language-features',
|
|
'@codingame/monaco-vscode-standalone-languages',
|
|
'windmill-client'
|
|
]
|
|
},
|
|
worker: { format: 'es' },
|
|
resolve: {
|
|
alias: {
|
|
path: 'path-browserify',
|
|
'monaco-editor/esm/vs/editor/contrib/hover/browser/hover':
|
|
'monaco-editor/esm/vs/editor/contrib/hover/browser/hoverContribution'
|
|
},
|
|
dedupe: ['vscode', 'monaco-editor']
|
|
},
|
|
assetsInclude: ['**/*.wasm'],
|
|
test: {
|
|
expect: { requireAssertions: true },
|
|
projects: [
|
|
{
|
|
extends: './vite.config.js',
|
|
test: {
|
|
name: 'server',
|
|
environment: 'node',
|
|
include: ['src/**/*.{test,spec}.{js,ts}'],
|
|
exclude: ['src/**/*.svelte.{test,spec}.{js,ts}'],
|
|
setupFiles: ['src/lib/test-setup.ts']
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
export default config
|