remcode
Version:
Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.
139 lines (138 loc) • 5.89 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitHubActions = void 0;
const logger_1 = require("../utils/logger");
const logger = (0, logger_1.getLogger)('GitHubActions');
class GitHubActions {
constructor(client) {
this.client = client;
}
/**
* List workflows in a repository
*/
async listWorkflows(owner, repo) {
logger.info(`Listing workflows for ${owner}/${repo}`);
const response = await this.client.makeRequest(`/repos/${owner}/${repo}/actions/workflows`);
return response.workflows || [];
}
/**
* Get workflow by ID or filename
*/
async getWorkflow(owner, repo, workflowIdOrFilename) {
// Handle both numeric IDs and filename paths
const isNumeric = /^\d+$/.test(workflowIdOrFilename);
const endpoint = `/repos/${owner}/${repo}/actions/workflows/${workflowIdOrFilename}`;
logger.info(`Getting workflow ${workflowIdOrFilename} for ${owner}/${repo}`);
return this.client.makeRequest(endpoint);
}
/**
* List workflow runs for a specific workflow or all workflows in a repo
*/
async getWorkflowRuns(owner, repo, workflowId, options = {}) {
let endpoint = workflowId
? `/repos/${owner}/${repo}/actions/workflows/${workflowId}/runs`
: `/repos/${owner}/${repo}/actions/runs`;
// Add query parameters for branch and status filtering
const queryParams = [];
if (options.branch) {
queryParams.push(`branch=${options.branch}`);
}
if (options.status) {
queryParams.push(`status=${options.status}`);
}
if (queryParams.length > 0) {
endpoint += `?${queryParams.join('&')}`;
}
logger.info(`Getting workflow runs for ${owner}/${repo}${workflowId ? `/${workflowId}` : ''}`);
const response = await this.client.makeRequest(endpoint);
return response.workflow_runs || [];
}
/**
* Trigger a workflow dispatch event
*/
async triggerWorkflow(owner, repo, workflowId, ref = 'main', inputs) {
logger.info(`Triggering workflow: ${workflowId} on ref ${ref}`);
await this.client.createWorkflowDispatch(owner, repo, workflowId, ref, inputs);
logger.info(`Successfully triggered workflow ${workflowId}`);
}
/**
* Get the status of a specific workflow run
*/
async getWorkflowStatus(owner, repo, runId) {
try {
logger.info(`Getting workflow run status: ${runId}`);
const workflowRun = await this.client.makeRequest(`/repos/${owner}/${repo}/actions/runs/${runId}`);
return workflowRun;
}
catch (error) {
logger.error(`Failed to get workflow run status: ${error instanceof Error ? error.message : String(error)}`);
return null;
}
}
/**
* Get jobs for a specific workflow run
*/
async getWorkflowJobs(owner, repo, runId) {
logger.info(`Getting jobs for workflow run: ${runId}`);
const response = await this.client.makeRequest(`/repos/${owner}/${repo}/actions/runs/${runId}/jobs`);
return response.jobs || [];
}
/**
* Download workflow run logs
*/
async downloadWorkflowLogs(owner, repo, runId) {
logger.info(`Downloading logs for workflow run: ${runId}`);
const response = await this.client.makeRequest(`/repos/${owner}/${repo}/actions/runs/${runId}/logs`, 'GET', undefined, { responseType: 'arraybuffer' });
return Buffer.from(response);
}
/**
* Cancel a workflow run
*/
async cancelWorkflowRun(owner, repo, runId) {
logger.info(`Cancelling workflow run: ${runId}`);
await this.client.makeRequest(`/repos/${owner}/${repo}/actions/runs/${runId}/cancel`, 'POST');
logger.info(`Successfully cancelled workflow run ${runId}`);
}
/**
* Re-run a workflow
*/
async rerunWorkflow(owner, repo, runId, onlyFailedJobs = false) {
const endpoint = onlyFailedJobs
? `/repos/${owner}/${repo}/actions/runs/${runId}/rerun-failed-jobs`
: `/repos/${owner}/${repo}/actions/runs/${runId}/rerun`;
logger.info(`Re-running workflow run: ${runId}${onlyFailedJobs ? ' (failed jobs only)' : ''}`);
await this.client.makeRequest(endpoint, 'POST');
logger.info(`Successfully re-ran workflow run ${runId}`);
}
/**
* Wait for a workflow run to complete, with polling and timeout
*/
async waitForWorkflowCompletion(owner, repo, runId, timeoutMs = 300000, pollIntervalMs = 5000) {
logger.info(`Waiting for workflow completion: ${runId} (timeout: ${timeoutMs}ms, polling: ${pollIntervalMs}ms)`);
const startTime = Date.now();
let lastStatus = '';
while (true) {
// Check if we've timed out
if (Date.now() - startTime > timeoutMs) {
throw new Error(`Workflow run ${runId} did not complete within the timeout period (${timeoutMs}ms)`);
}
// Get the current status
const run = await this.getWorkflowStatus(owner, repo, runId);
if (!run) {
throw new Error(`Workflow run ${runId} not found`);
}
// Log status changes
if (run.status !== lastStatus) {
logger.info(`Workflow run ${runId} status: ${run.status}${run.conclusion ? ` (${run.conclusion})` : ''}`);
lastStatus = run.status;
}
// Check if the workflow has completed
if (run.status === 'completed') {
return run;
}
// Wait before polling again
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
}
}
}
exports.GitHubActions = GitHubActions;
;