* update cf worker hostname
* set remote_url cookie from param
* ephemeral backends v1
* nit
* Run queue server
* ntis
* timeout
* better db process management
* commit hash and worktree
* nit use map
* nit
* err handling
* Revert "err handling"
This reverts commit 19de00c0c0.
* nits
* auto cleanup
* Ephemeral backend command action
* remove checkout
* checkout ee repo
* nits
* process.env.GIT_EE_DEPLOY_KEY_FILE
* resumeURLs logic
* nit
* use windmill flow for ephemeral backend action
* fixes
* new token
* worktree pools
* Delete GH secret on cleanup
* linux deploy
* nit
* nit
* unhandled promises
* nit
* fix docker bridge IP on linux
* pass cf_frontend_url to wmill flow
* git fetch
* release worktree when binary started
* send error
* logger
* logging
* logging 2
* delete log files periodically
* redirect to raw app with logs
* CORS
* MANAGER_AUTH_TOKEN
* Check organization membership
* nit
* bwrap
* nit
* return timeoutAt in resumeUrl
* nit
* Change password
* nit remove https
159 lines
5.9 KiB
YAML
159 lines
5.9 KiB
YAML
name: Spawn Ephemeral Backend
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created]
|
|
workflow_dispatch:
|
|
inputs:
|
|
pr_number:
|
|
description: "PR number"
|
|
required: true
|
|
type: number
|
|
|
|
jobs:
|
|
spawn-backend:
|
|
# Only run on PR comments that contain /spawn-backend, or manual dispatch
|
|
if: |
|
|
github.event_name == 'workflow_dispatch' ||
|
|
(github.event.issue.pull_request && contains(github.event.comment.body, '/spawn-backend'))
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
pull-requests: write
|
|
contents: read
|
|
|
|
steps:
|
|
- name: Check organization membership
|
|
if: github.event_name == 'issue_comment'
|
|
id: check-org-member
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const commenter = context.payload.comment.user.login;
|
|
|
|
try {
|
|
const membership = await github.rest.orgs.checkMembershipForUser({
|
|
org: 'windmill-labs',
|
|
username: commenter
|
|
});
|
|
|
|
core.setOutput('is_member', 'true');
|
|
console.log(`✓ User ${commenter} is a member of windmill-labs`);
|
|
} catch (error) {
|
|
core.setOutput('is_member', 'false');
|
|
console.log(`✗ User ${commenter} is not a member of windmill-labs`);
|
|
}
|
|
|
|
- name: Post unauthorized comment
|
|
if: |
|
|
github.event_name == 'issue_comment' &&
|
|
steps.check-org-member.outputs.is_member == 'false'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: context.issue.number,
|
|
body: `❌ Unauthorized: Only members of the windmill-labs organization can spawn ephemeral backends.`
|
|
});
|
|
|
|
- name: Fail if not org member
|
|
if: |
|
|
github.event_name == 'issue_comment' &&
|
|
steps.check-org-member.outputs.is_member == 'false'
|
|
run: |
|
|
echo "Error: User is not a member of windmill-labs organization"
|
|
exit 1
|
|
|
|
- name: Get PR details
|
|
id: pr-details
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const prNumber = context.eventName === 'workflow_dispatch'
|
|
? context.payload.inputs.pr_number
|
|
: context.issue.number;
|
|
|
|
const pr = await github.rest.pulls.get({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
pull_number: prNumber
|
|
});
|
|
|
|
// Get branch name and format it for Cloudflare Pages
|
|
// Replace '/' with '-' for the URL
|
|
const branchName = pr.data.head.ref;
|
|
const formattedBranch = branchName.replace(/\//g, '-');
|
|
const cfFrontendUrl = `https://${formattedBranch}.windmill.pages.dev`;
|
|
|
|
core.setOutput('commit_hash', pr.data.head.sha);
|
|
core.setOutput('pr_number', prNumber);
|
|
core.setOutput('branch_name', branchName);
|
|
core.setOutput('cf_frontend_url', cfFrontendUrl);
|
|
|
|
- name: Check manager URL
|
|
id: check-manager-url
|
|
run: |
|
|
if [ -z "${{ secrets.EPHEMERAL_BACKEND_QUEUE_URL }}" ]; then
|
|
echo "manager_url_set=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "manager_url_set=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Post error comment if manager not running
|
|
if: steps.check-manager-url.outputs.manager_url_set == 'false'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const prNumber = context.eventName === 'workflow_dispatch'
|
|
? Number(context.payload.inputs.pr_number)
|
|
: context.issue.number;
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
body: `❌ Manager URL not set (did you start the ephemeral backend manager?)\n\nThe ephemeral backend manager needs to be running to spawn backends. Please start the manager first.`
|
|
});
|
|
|
|
- name: Fail if manager not running
|
|
if: steps.check-manager-url.outputs.manager_url_set == 'false'
|
|
run: |
|
|
echo "Error: EPHEMERAL_BACKEND_QUEUE_URL secret is not set"
|
|
exit 1
|
|
|
|
- name: Trigger Windmill flow
|
|
if: steps.check-manager-url.outputs.manager_url_set == 'true'
|
|
id: trigger-flow
|
|
run: |
|
|
JOB_UUID=$(curl -s -X POST "https://app.windmill.dev/api/w/windmill-labs/jobs/run/f/f/all/run_ephemeral_backend" \
|
|
-H "Authorization: Bearer ${{ secrets.WINDMILL_RUN_FLOW_TOKEN }}" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"manager_url": "${{ secrets.EPHEMERAL_BACKEND_QUEUE_URL }}",
|
|
"commit_hash": "${{ steps.pr-details.outputs.commit_hash }}",
|
|
"pr_number": ${{ steps.pr-details.outputs.pr_number }},
|
|
"cf_frontend_url": "${{ steps.pr-details.outputs.cf_frontend_url }}"
|
|
}' | tr -d '"')
|
|
|
|
echo "Job UUID: $JOB_UUID"
|
|
echo "job_uuid=$JOB_UUID" >> $GITHUB_OUTPUT
|
|
|
|
- name: Post comment with job link
|
|
if: steps.check-manager-url.outputs.manager_url_set == 'true'
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const jobUuid = '${{ steps.trigger-flow.outputs.job_uuid }}';
|
|
const appUrl = `https://app.windmill.dev/public/windmill-labs/a106bad0256c1dfa7a4f9279c42b1a4b#${jobUuid}`;
|
|
const prNumber = context.eventName === 'workflow_dispatch'
|
|
? Number(context.payload.inputs.pr_number)
|
|
: context.issue.number;
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: prNumber,
|
|
body: `🚀 Spawning new ephemeral backend!\n\n${appUrl}`
|
|
});
|