From a7c29c38309719c893168568dc9c3b7beb80ba4e Mon Sep 17 00:00:00 2001 From: Mahmoud Mabrouk Date: Thu, 18 Dec 2025 19:34:42 +0100 Subject: [PATCH 1/2] ci: add PR comment deploy command Add workflow to trigger deployments from PR comments using /deploy command. --- .../workflows/05-deploy-from-pr-comment.yml | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 .github/workflows/05-deploy-from-pr-comment.yml diff --git a/.github/workflows/05-deploy-from-pr-comment.yml b/.github/workflows/05-deploy-from-pr-comment.yml new file mode 100644 index 000000000..4eb2d759d --- /dev/null +++ b/.github/workflows/05-deploy-from-pr-comment.yml @@ -0,0 +1,213 @@ +name: Deploy from PR Comment + +on: + issue_comment: + types: [created] + +jobs: + deploy: + name: Trigger Deployment + # Only run on PR comments that start with /deploy + if: | + github.event.issue.pull_request && + startsWith(github.event.comment.body, '/deploy') + runs-on: ubuntu-latest + + steps: + - name: Parse deploy command + id: parse + uses: actions/github-script@v7 + with: + script: | + const comment = context.payload.comment.body.trim(); + const lines = comment.split('\n')[0]; // Only first line + const parts = lines.split(/\s+/); + + // Expected: /deploy [component] [--flags] + // e.g., /deploy staging + // e.g., /deploy demo api-only + // e.g., /deploy beta web-only --migration-check + + const environments = ['staging', 'demo', 'beta']; + const components = ['all-components', 'all-but-web', 'api-only', 'web-only', 'services-only', 'none']; + + let environment = null; + let component = 'all-components'; // default + let migrationCheck = false; + let apiTag = ''; + let webTag = ''; + let servicesTag = ''; + + for (const part of parts.slice(1)) { // Skip '/deploy' + if (environments.includes(part)) { + environment = part; + } else if (components.includes(part)) { + component = part; + } else if (part === '--migration-check') { + migrationCheck = true; + } else if (part.startsWith('--api-tag=')) { + apiTag = part.replace('--api-tag=', ''); + } else if (part.startsWith('--web-tag=')) { + webTag = part.replace('--web-tag=', ''); + } else if (part.startsWith('--services-tag=')) { + servicesTag = part.replace('--services-tag=', ''); + } + } + + if (!environment) { + core.setFailed('Missing environment. Usage: /deploy [component] [--flags]'); + return; + } + + // Map environment to workflow file + const workflowMap = { + 'beta': '22-deploy-to-cloud-beta.yml', + 'staging': '23-deploy-to-cloud-staging.yml', + 'demo': '24-deploy-to-cloud-demo.yml' + }; + + core.setOutput('environment', environment); + core.setOutput('component', component); + core.setOutput('workflow', workflowMap[environment]); + core.setOutput('migration_check', migrationCheck); + core.setOutput('api_tag', apiTag); + core.setOutput('web_tag', webTag); + core.setOutput('services_tag', servicesTag); + + console.log(`Environment: ${environment}`); + console.log(`Component: ${component}`); + console.log(`Workflow: ${workflowMap[environment]}`); + console.log(`Migration check: ${migrationCheck}`); + + - name: Get PR branch + id: pr + uses: actions/github-script@v7 + with: + script: | + const pr = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.issue.number + }); + + const branch = pr.data.head.ref; + const sha = pr.data.head.sha.substring(0, 7); + + core.setOutput('branch', branch); + core.setOutput('sha', sha); + + console.log(`PR Branch: ${branch}`); + console.log(`PR SHA: ${sha}`); + + - name: Add reaction to comment + uses: actions/github-script@v7 + with: + script: | + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: context.payload.comment.id, + content: 'rocket' + }); + + - name: Trigger deployment workflow + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.PRIVATE_REPO_PAT }} + script: | + const environment = '${{ steps.parse.outputs.environment }}'; + const component = '${{ steps.parse.outputs.component }}'; + const workflow = '${{ steps.parse.outputs.workflow }}'; + const branch = '${{ steps.pr.outputs.branch }}'; + const migrationCheck = '${{ steps.parse.outputs.migration_check }}' === 'true'; + const apiTag = '${{ steps.parse.outputs.api_tag }}'; + const webTag = '${{ steps.parse.outputs.web_tag }}'; + const servicesTag = '${{ steps.parse.outputs.services_tag }}'; + + console.log(`Triggering ${workflow} with branch: ${branch}, component: ${component}`); + + await github.rest.actions.createWorkflowDispatch({ + owner: 'Agenta-AI', + repo: 'agenta_cloud', + workflow_id: workflow, + ref: 'main', + inputs: { + 'public-branch': branch, + 'components-to-deploy': component, + 'migration-check': String(migrationCheck), + 'database-switch': 'false', + 'include-tracing': 'false', + 'rollback-tag': 'skip', + 'api-tag': apiTag, + 'web-tag': webTag, + 'services-tag': servicesTag + } + }); + + console.log('✅ Deployment triggered successfully!'); + + - name: Post success comment + uses: actions/github-script@v7 + with: + script: | + const environment = '${{ steps.parse.outputs.environment }}'; + const component = '${{ steps.parse.outputs.component }}'; + const branch = '${{ steps.pr.outputs.branch }}'; + const sha = '${{ steps.pr.outputs.sha }}'; + + const envUrls = { + 'staging': 'https://staging.agenta.ai', + 'demo': 'https://demo.agenta.ai', + 'beta': 'https://beta.agenta.ai' + }; + + const body = `🚀 **Deployment triggered!** + + | Parameter | Value | + |-----------|-------| + | Environment | \`${environment}\` | + | Branch | \`${branch}\` (${sha}) | + | Components | \`${component}\` | + + 🔗 [View deployment workflow](https://github.com/Agenta-AI/agenta_cloud/actions) + 🌐 Environment URL: ${envUrls[environment] || 'N/A'} + + _Deployment takes ~5-10 minutes. Check the workflow link for progress._`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + body: body + }); + + - name: Post failure comment + if: failure() + uses: actions/github-script@v7 + with: + script: | + const body = `❌ **Deployment failed to trigger** + + Please check the [workflow logs](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) for details. + + **Usage:** + \`\`\` + /deploy [component] [--flags] + + Environments: staging, demo, beta + Components: all-components (default), all-but-web, api-only, web-only, services-only + Flags: --migration-check, --api-tag=, --web-tag=, --services-tag= + \`\`\` + + **Examples:** + - \`/deploy staging\` - Deploy all components to staging + - \`/deploy demo api-only\` - Deploy only API to demo + - \`/deploy beta web-only --migration-check\` - Deploy web to beta with migration check + `; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + body: body + }); From 54abc59e53c5eb099b2961e51c58678485fb8cbe Mon Sep 17 00:00:00 2001 From: Mahmoud Mabrouk Date: Thu, 18 Dec 2025 19:38:18 +0100 Subject: [PATCH 2/2] Potential fix for code scanning alert no. 142: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/05-deploy-from-pr-comment.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/05-deploy-from-pr-comment.yml b/.github/workflows/05-deploy-from-pr-comment.yml index 4eb2d759d..4caacd9b0 100644 --- a/.github/workflows/05-deploy-from-pr-comment.yml +++ b/.github/workflows/05-deploy-from-pr-comment.yml @@ -1,4 +1,9 @@ name: Deploy from PR Comment +permissions: + contents: read + issues: write + pull-requests: read + actions: write on: issue_comment: