This commit is contained in:
8
.github/dependabot.yml
vendored
Normal file
8
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
updates:
|
||||||
|
- commit-message:
|
||||||
|
prefix: fix
|
||||||
|
directory: /
|
||||||
|
package-ecosystem: github-actions
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
version: 2
|
||||||
35
.github/workflows/changelog.yml
vendored
Normal file
35
.github/workflows/changelog.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
jobs:
|
||||||
|
changelog:
|
||||||
|
name: changelog
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
submodules: true
|
||||||
|
- id: previoustag
|
||||||
|
name: Get Latest Tag
|
||||||
|
run: |-
|
||||||
|
echo ::set-output name=tag::$(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||||
|
echo $(git describe --tags "$(git rev-list --tags --max-count=1)")
|
||||||
|
- id: changelog
|
||||||
|
if: github.ref_name == 'main'
|
||||||
|
name: Generate new Tag
|
||||||
|
uses: TriPSs/conventional-changelog-action@v6
|
||||||
|
with:
|
||||||
|
fallback-version: ${{ steps.previoustag.outputs.tag }}
|
||||||
|
git-url: ${{ github.server_url != 'https://github.com' && 'git.yusufali.ca' || 'github.com' }}
|
||||||
|
github-token: ${{ github.token }}
|
||||||
|
output-file: false
|
||||||
|
skip-ci: false
|
||||||
|
skip-commit: true
|
||||||
|
skip-version-file: true
|
||||||
|
tag-prefix: ''
|
||||||
|
name: CHANGELOG
|
||||||
|
'on':
|
||||||
|
workflow_dispatch: {}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
run-name: CHANGELOG
|
||||||
33
.github/workflows/commit.yml
vendored
Normal file
33
.github/workflows/commit.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
jobs:
|
||||||
|
commitlint:
|
||||||
|
name: commitlint
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
submodules: true
|
||||||
|
- uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 23.1
|
||||||
|
- name: Install commitlint
|
||||||
|
run: |
|
||||||
|
if [ -f package.json ]; then
|
||||||
|
rm package*.json
|
||||||
|
fi
|
||||||
|
npm install -g @commitlint/cli @commitlint/config-conventional
|
||||||
|
if [ ! -f "commitlint.config.js" ]; then
|
||||||
|
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
|
||||||
|
fi
|
||||||
|
- if: github.event_name == 'push'
|
||||||
|
name: Lint Commit Message
|
||||||
|
run: commitlint --from=HEAD~1 --verbose
|
||||||
|
- if: github.event_name == 'pull_request'
|
||||||
|
name: Lint Pull Request
|
||||||
|
run: commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
|
||||||
|
name: COMMIT LINT
|
||||||
|
'on':
|
||||||
|
pull_request: {}
|
||||||
|
run-name: COMMIT LINT
|
||||||
55
.github/workflows/dependabot-auto-merge.yml
vendored
Normal file
55
.github/workflows/dependabot-auto-merge.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
jobs:
|
||||||
|
dependabot:
|
||||||
|
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
||||||
|
name: dependabot
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- env:
|
||||||
|
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
PR_URL: ${{github.event.pull_request.html_url}}
|
||||||
|
name: Enable auto-merge for Dependabot
|
||||||
|
run: gh pr merge --auto --merge "$PR_URL"
|
||||||
|
devopsbot:
|
||||||
|
if: github.event.pull_request.title == 'devopsbot update'
|
||||||
|
name: devopsbot
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
submodules: true
|
||||||
|
- &id001
|
||||||
|
name: Setup GitHub CLI
|
||||||
|
uses: ksivamuthu/actions-setup-gh-cli@v3
|
||||||
|
- env:
|
||||||
|
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
PR_URL: ${{github.event.pull_request.html_url}}
|
||||||
|
name: Enable auto-merge for Dependabot
|
||||||
|
run: gh pr merge --auto --merge "$PR_URL"
|
||||||
|
rennovatebot:
|
||||||
|
if: github.event.pull_request.user.login == 'renovate_bot'
|
||||||
|
name: rennovatebot
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
submodules: true
|
||||||
|
- *id001
|
||||||
|
- env:
|
||||||
|
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||||
|
PR_URL: ${{github.event.pull_request.html_url}}
|
||||||
|
name: Enable auto-merge for Dependabot
|
||||||
|
run: gh pr merge --auto --merge "$PR_URL"
|
||||||
|
name: Dependabot Auto-Merge
|
||||||
|
'on':
|
||||||
|
pull_request: {}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
run-name: Dependabot Auto-Merge
|
||||||
60
.github/workflows/publish.yml
vendored
Normal file
60
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
name: 'Publish'
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 100
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 'latest'
|
||||||
|
|
||||||
|
- name: Install lint
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
npm install -g @commitlint/cli @commitlint/config-conventional
|
||||||
|
if [ ! -f "commitlint.config.js" ]; then
|
||||||
|
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Lint Commit Message
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
shell: bash
|
||||||
|
run: commitlint --from=HEAD~2 --verbose
|
||||||
|
|
||||||
|
- name: Lint Pull Request
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
shell: bash
|
||||||
|
run: commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
|
||||||
|
|
||||||
|
- name: "Get Previous tag"
|
||||||
|
id: previoustagold
|
||||||
|
uses: "WyriHaximus/github-action-get-previous-tag@v1"
|
||||||
|
|
||||||
|
- name: Conventional Changelog Action
|
||||||
|
id: changelog
|
||||||
|
if: github.ref_name == 'main'
|
||||||
|
uses: TriPSs/conventional-changelog-action@v6
|
||||||
|
with:
|
||||||
|
github-token: ${{ github.token }}
|
||||||
|
git-url: ${{ github.server_url != 'https://github.com' && 'git.yusufali.ca' || 'github.com' }}
|
||||||
|
tag-prefix: ""
|
||||||
|
output-file: false
|
||||||
|
skip-version-file: true
|
||||||
|
skip-commit: true
|
||||||
|
skip-ci: false
|
||||||
|
skip-tag: ${{ github.ref_name != 'main' }}
|
||||||
|
fallback-version: ${{ steps.previoustagold.outputs.tag }}
|
||||||
|
|
||||||
22
.github/workflows/test.yml
vendored
Normal file
22
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: 'Unit Tests'
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unittest:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Test Local Action
|
||||||
|
id: test
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
debug: 'true'
|
||||||
50
README.md
Normal file
50
README.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Coding Automator Action
|
||||||
|
|
||||||
|
Send issue comments to the coding agent so it can pick up and work on tasks mentioned with `@bot`.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Send Tasks to Agent
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created, edited]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dispatch:
|
||||||
|
if: contains(github.event.comment.body, '@bot')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: read
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Send task to coding agent
|
||||||
|
uses: git.yusufali.ca/automation/action@main
|
||||||
|
with:
|
||||||
|
api_url: ${{ secrets.AGENT_API_URL }} # default: https://api.servc.io
|
||||||
|
api_token: ${{ secrets.AGENT_TOKEN }} # optional, required for authenticated API calls
|
||||||
|
bot_route: coder-agent # default: codebot
|
||||||
|
debug: false
|
||||||
|
env:
|
||||||
|
# Used to fetch the first issue comment for context; provided automatically by Actions
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
- Trigger on `issue_comment` events that contain `@bot`.
|
||||||
|
- The action fetches the **first comment** on the issue (when available) to capture the original task and strips the `@bot` mention. If none exists, it falls back to the triggering comment.
|
||||||
|
- It posts the task, repo info, and issue number to the configured agent API route.
|
||||||
|
- Agent responses are logged to the workflow output; failures set the step as failed.
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
- `api_url` (default `https://api.servc.io`): Agent API endpoint.
|
||||||
|
- `api_token` (optional): Token sent as `Apitoken` header for authenticated calls.
|
||||||
|
- `bot_route` (default `codebot`): Agent route to target.
|
||||||
|
- `debug` (default `false`): When `true`, logs the payload and configuration for troubleshooting.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Ensure `issues: read` permission so the action can fetch the first comment for context.
|
||||||
|
- The action respects `GITHUB_SERVER_URL` for GitHub Enterprise environments.
|
||||||
22
action.yml
Normal file
22
action.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: 'Coding Automator'
|
||||||
|
description: 'Sends a coding automation task to coding bot'
|
||||||
|
inputs:
|
||||||
|
api_url:
|
||||||
|
description: 'api url'
|
||||||
|
default: 'https://api.servc.io'
|
||||||
|
required: false
|
||||||
|
api_token:
|
||||||
|
description: 'API token for authentication'
|
||||||
|
default: ''
|
||||||
|
required: false
|
||||||
|
bot_route:
|
||||||
|
default: 'codebot'
|
||||||
|
required: false
|
||||||
|
debug:
|
||||||
|
description: 'Enable debug mode'
|
||||||
|
default: 'false'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'node20'
|
||||||
|
main: 'dist/index.js'
|
||||||
176
dist/index.js
vendored
Normal file
176
dist/index.js
vendored
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/******/ (() => { // webpackBootstrap
|
||||||
|
/******/ var __webpack_modules__ = ({
|
||||||
|
|
||||||
|
/***/ 495:
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = eval("require")("@actions/core");
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 99:
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = eval("require")("@actions/github");
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ });
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var __webpack_module_cache__ = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __nccwpck_require__(moduleId) {
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||||
|
/******/ if (cachedModule !== undefined) {
|
||||||
|
/******/ return cachedModule.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||||
|
/******/ // no module.id needed
|
||||||
|
/******/ // no module.loaded needed
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ var threw = true;
|
||||||
|
/******/ try {
|
||||||
|
/******/ __webpack_modules__[moduleId](module, module.exports, __nccwpck_require__);
|
||||||
|
/******/ threw = false;
|
||||||
|
/******/ } finally {
|
||||||
|
/******/ if(threw) delete __webpack_module_cache__[moduleId];
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ /* webpack/runtime/compat */
|
||||||
|
/******/
|
||||||
|
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
var __webpack_exports__ = {};
|
||||||
|
const core = __nccwpck_require__(495);
|
||||||
|
const github = __nccwpck_require__(99);
|
||||||
|
|
||||||
|
const sanitizeTask = (text) => (text || '').replace(/@bot\b[:]?\s*/gi, '').trim();
|
||||||
|
|
||||||
|
async function fetchFirstIssueComment(repoFullName, issueNumber, githubToken, serverUrl) {
|
||||||
|
if (!repoFullName || !issueNumber) return null;
|
||||||
|
|
||||||
|
const url = `${serverUrl}/api/v1/repos/${repoFullName}/issues/${issueNumber}/comments?limit=1`;
|
||||||
|
const headers = { Accept: 'application/vnd.github+json' };
|
||||||
|
|
||||||
|
if (githubToken) {
|
||||||
|
headers.Authorization = `Bearer ${githubToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, { headers });
|
||||||
|
if (!response.ok) {
|
||||||
|
core.warning(`Failed to fetch issue comments (${response.status}): ${response.statusText}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comments = await response.json();
|
||||||
|
if (!Array.isArray(comments) || comments.length === 0) return null;
|
||||||
|
|
||||||
|
return sanitizeTask(comments[0]?.body);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Error fetching issue comments: ${error}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const apiUrl = core.getInput('api_url') || 'https://api.servc.io';
|
||||||
|
const apiToken = core.getInput('api_token');
|
||||||
|
const botRoute = core.getInput('bot_route') || 'codebot';
|
||||||
|
const debug = (core.getInput('debug') || 'false').toLowerCase() === 'true';
|
||||||
|
const serverUrl = (process.env.GITHUB_SERVER_URL || github.context.serverUrl || 'https://git.yusufali.ca').replace(/\/$/, '');
|
||||||
|
|
||||||
|
const payload = github.context.payload;
|
||||||
|
const commentBody = payload?.comment?.body || '';
|
||||||
|
const issueNumber = payload?.issue?.number;
|
||||||
|
const repoName = payload?.repository?.full_name;
|
||||||
|
const repoUrl = payload?.repository?.clone_url;
|
||||||
|
const githubToken = process.env.GITHUB_TOKEN;
|
||||||
|
|
||||||
|
if (!commentBody) {
|
||||||
|
core.setFailed('No comment body found in the event payload');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const task =
|
||||||
|
(await fetchFirstIssueComment(repoName, issueNumber, githubToken, serverUrl)) ||
|
||||||
|
sanitizeTask(commentBody);
|
||||||
|
|
||||||
|
if (!task) {
|
||||||
|
core.setFailed('Unable to determine the task to send to the agent');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestPayload = {
|
||||||
|
type: 'input',
|
||||||
|
route: botRoute,
|
||||||
|
argumentId: 'plain',
|
||||||
|
force: true,
|
||||||
|
instanceId: null,
|
||||||
|
inputs: {
|
||||||
|
method: 'run_task',
|
||||||
|
inputs: {
|
||||||
|
repo_name: repoName,
|
||||||
|
repo_url: repoUrl,
|
||||||
|
issue_number: String(issueNumber),
|
||||||
|
task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
core.info(`API URL: ${apiUrl}`);
|
||||||
|
core.info(`Route: ${botRoute}`);
|
||||||
|
core.info(`Server URL: ${serverUrl}`);
|
||||||
|
core.info(`Using auth: ${Boolean(apiToken)}`);
|
||||||
|
core.info(`Request payload: ${JSON.stringify(requestPayload)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (apiToken) {
|
||||||
|
headers.Apitoken = apiToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(apiUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(requestPayload)
|
||||||
|
});
|
||||||
|
|
||||||
|
const responseText = await response.text();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
core.setFailed(`Agent API request failed (${response.status}): ${responseText}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Agent response: ${responseText}`);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Error sending task to agent: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
|
module.exports = __webpack_exports__;
|
||||||
|
/******/ })()
|
||||||
|
;
|
||||||
114
index.js
Normal file
114
index.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
const core = require('@actions/core');
|
||||||
|
const github = require('@actions/github');
|
||||||
|
|
||||||
|
const sanitizeTask = (text) => (text || '').replace(/@bot\b[:]?\s*/gi, '').trim();
|
||||||
|
|
||||||
|
async function fetchFirstIssueComment(repoFullName, issueNumber, githubToken, serverUrl) {
|
||||||
|
if (!repoFullName || !issueNumber) return null;
|
||||||
|
|
||||||
|
const url = `${serverUrl}/api/v1/repos/${repoFullName}/issues/${issueNumber}/comments?limit=1`;
|
||||||
|
const headers = { Accept: 'application/vnd.github+json' };
|
||||||
|
|
||||||
|
if (githubToken) {
|
||||||
|
headers.Authorization = `Bearer ${githubToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, { headers });
|
||||||
|
if (!response.ok) {
|
||||||
|
core.warning(`Failed to fetch issue comments (${response.status}): ${response.statusText}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const comments = await response.json();
|
||||||
|
if (!Array.isArray(comments) || comments.length === 0) return null;
|
||||||
|
|
||||||
|
return sanitizeTask(comments[0]?.body);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Error fetching issue comments: ${error}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
const apiUrl = core.getInput('api_url') || 'https://api.servc.io';
|
||||||
|
const apiToken = core.getInput('api_token');
|
||||||
|
const botRoute = core.getInput('bot_route') || 'codebot';
|
||||||
|
const debug = (core.getInput('debug') || 'false').toLowerCase() === 'true';
|
||||||
|
const serverUrl = (process.env.GITHUB_SERVER_URL || github.context.serverUrl || 'https://git.yusufali.ca').replace(/\/$/, '');
|
||||||
|
|
||||||
|
const payload = github.context.payload;
|
||||||
|
const commentBody = payload?.comment?.body || '';
|
||||||
|
const issueNumber = payload?.issue?.number;
|
||||||
|
const repoName = payload?.repository?.full_name;
|
||||||
|
const repoUrl = payload?.repository?.clone_url;
|
||||||
|
const githubToken = process.env.GITHUB_TOKEN;
|
||||||
|
|
||||||
|
if (!commentBody) {
|
||||||
|
core.setFailed('No comment body found in the event payload');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const task =
|
||||||
|
(await fetchFirstIssueComment(repoName, issueNumber, githubToken, serverUrl)) ||
|
||||||
|
sanitizeTask(commentBody);
|
||||||
|
|
||||||
|
if (!task) {
|
||||||
|
core.setFailed('Unable to determine the task to send to the agent');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestPayload = {
|
||||||
|
type: 'input',
|
||||||
|
route: botRoute,
|
||||||
|
argumentId: 'plain',
|
||||||
|
force: true,
|
||||||
|
instanceId: null,
|
||||||
|
inputs: {
|
||||||
|
method: 'run_task',
|
||||||
|
inputs: {
|
||||||
|
repo_name: repoName,
|
||||||
|
repo_url: repoUrl,
|
||||||
|
issue_number: String(issueNumber),
|
||||||
|
task
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
core.info(`API URL: ${apiUrl}`);
|
||||||
|
core.info(`Route: ${botRoute}`);
|
||||||
|
core.info(`Server URL: ${serverUrl}`);
|
||||||
|
core.info(`Using auth: ${Boolean(apiToken)}`);
|
||||||
|
core.info(`Request payload: ${JSON.stringify(requestPayload)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (apiToken) {
|
||||||
|
headers.Apitoken = apiToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(apiUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(requestPayload)
|
||||||
|
});
|
||||||
|
|
||||||
|
const responseText = await response.text();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
core.setFailed(`Agent API request failed (${response.status}): ${responseText}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.info(`Agent response: ${responseText}`);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Error sending task to agent: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
283
package-lock.json
generated
Normal file
283
package-lock.json
generated
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
{
|
||||||
|
"name": "devops-actions-telemetry",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "devops-actions-telemetry",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "2.0.1",
|
||||||
|
"@actions/github": "6.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/core": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-oBfqT3GwkvLlo1fjvhQLQxuwZCGTarTE5OuZ2Wg10hvhBj7LRIlF611WT4aZS6fDhO5ZKlY7lCAZTlpmyaHaeg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/exec": "^2.0.0",
|
||||||
|
"@actions/http-client": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/core/node_modules/@actions/http-client": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6",
|
||||||
|
"undici": "^5.28.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/exec": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/io": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/github": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/http-client": "^2.2.0",
|
||||||
|
"@octokit/core": "^5.0.1",
|
||||||
|
"@octokit/plugin-paginate-rest": "^9.2.2",
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": "^10.4.0",
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/request-error": "^5.1.1",
|
||||||
|
"undici": "^5.28.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/http-client": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6",
|
||||||
|
"undici": "^5.25.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/io": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@fastify/busboy": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/auth-token": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/auth-token": "^4.0.0",
|
||||||
|
"@octokit/graphql": "^7.1.0",
|
||||||
|
"@octokit/request": "^8.3.1",
|
||||||
|
"@octokit/request-error": "^5.1.0",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"before-after-hook": "^2.2.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/endpoint": {
|
||||||
|
"version": "9.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||||
|
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^13.1.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/request": "^8.3.0",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "22.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz",
|
||||||
|
"integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg=="
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-paginate-rest": {
|
||||||
|
"version": "9.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
|
||||||
|
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^12.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@octokit/core": "5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "20.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||||
|
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||||
|
"version": "12.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||||
|
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||||
|
"version": "10.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||||
|
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^12.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@octokit/core": "5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "20.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||||
|
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA=="
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||||
|
"version": "12.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||||
|
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/request": {
|
||||||
|
"version": "8.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||||
|
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/endpoint": "^9.0.6",
|
||||||
|
"@octokit/request-error": "^5.1.1",
|
||||||
|
"@octokit/types": "^13.1.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/request-error": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^13.1.0",
|
||||||
|
"deprecation": "^2.0.0",
|
||||||
|
"once": "^1.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/types": {
|
||||||
|
"version": "13.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz",
|
||||||
|
"integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^22.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/before-after-hook": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
||||||
|
},
|
||||||
|
"node_modules/deprecation": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tunnel": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "5.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||||
|
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@fastify/busboy": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/universal-user-agent": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
package.json
Normal file
16
package.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "actions-automation",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/core": "2.0.1",
|
||||||
|
"@actions/github": "6.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user