Skip to content

Commit

Permalink
refactor: interactive variable and break apart functions
Browse files Browse the repository at this point in the history
  • Loading branch information
0x4007 committed Oct 4, 2024
1 parent 025e1fd commit 4528b3e
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 172 deletions.
13 changes: 3 additions & 10 deletions .github/workflows/start-program.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.UBIQUITY_OS_CONFIGURATION_AGENT_PAT }}
persist-credentials: true # Ensure credentials are persisted for subsequent steps

- name: Configure Git to use PAT
run: |
git config --global url."https://${{ secrets.UBIQUITY_OS_CONFIGURATION_AGENT_PAT }}:@github.com/".insteadOf "https://github.com/"

- name: Setup Node.js
uses: actions/setup-node@v4
Expand All @@ -29,12 +22,12 @@ jobs:
cache: "npm"

- name: Install dependencies
run: bun install
run: npm install

- name: Run start script
run: bun start "${{ github.event.inputs.input_string }}"
run: npm start "${{ github.event.inputs.input_string }}"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
INPUT_STRING: ${{ github.event.inputs.input_string }}
NON_INTERACTIVE: "true"
INTERACTIVE: "true"
GITHUB_TOKEN: ${{ secrets.UBIQUITY_OS_CONFIGURATION_AGENT_PAT }}
73 changes: 73 additions & 0 deletions src/sync-configs/apply-changes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import path from "path";
import simpleGit, { SimpleGit } from "simple-git";
import { createPullRequest } from "./create-pull-request";
import { getDefaultBranch } from "./get-default-branch";
import { Repo, REPOS_DIR } from "./sync-configs";
import * as fs from "fs";

export async function applyChanges({
repo,
filePath,
modifiedContent,
instruction,
isInteractive,
forceBranch,
}: {
repo: Repo;
filePath: string;
modifiedContent: string;
instruction: string;
isInteractive: boolean;
forceBranch?: string;
}) {
const git: SimpleGit = simpleGit({
baseDir: path.join(__dirname, REPOS_DIR, repo.localDir),
binary: "git",
maxConcurrentProcesses: 6,
trimmed: false,
});

git.outputHandler((command, stdout, stderr) => {
stdout.pipe(process.stdout);
stderr.pipe(process.stderr);
});

const defaultBranch = forceBranch || (await getDefaultBranch(repo.url));
console.log(`Default branch for ${repo.url} is ${defaultBranch}`);

// Checkout and pull the default branch
await git.checkout(defaultBranch);
await git.pull("origin", defaultBranch);

// Create and checkout a new branch
const branchName = `sync-configs-${Date.now()}`;
await git.checkoutLocalBranch(branchName);

// Now apply the changes
fs.writeFileSync(filePath, modifiedContent, "utf8");

await git.add(repo.filePath);

// const status = await git.status();
// console.log(`Git status before commit:`, status);

await git.commit(
`chore: update using UbiquityOS Configurations Agent
${instruction}
`
);

try {
if (isInteractive) {
await git.push("origin", defaultBranch);
console.log(`Changes pushed to ${repo.url} in branch ${defaultBranch}`);
} else {
await git.push("origin", branchName, ["--set-upstream"]);
await createPullRequest({ repo, branchName, defaultBranch, instruction });
console.log(`Pull request created for ${repo.url} from branch ${branchName} to ${defaultBranch}`);
}
} catch (error) {
console.error(`Error applying changes to ${repo.url}:`, error);
}
}
11 changes: 11 additions & 0 deletions src/sync-configs/confirm-changes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import inquirer from "inquirer";
export async function confirmChanges(repoUrl: string): Promise<boolean> {
const response = await inquirer.prompt([
{
type: "confirm",
name: "confirm",
message: `Do you want to apply these changes to ${repoUrl}?`,
},
]);
return response.confirm;
}
17 changes: 15 additions & 2 deletions src/sync-configs/create-pull-request.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { Octokit } from "@octokit/rest";
import { Repo } from "./sync-configs";

export async function createPullRequest(repo: Repo, branchName: string, defaultBranch: string, instruction: string) {
export async function createPullRequest({
repo,
branchName,
defaultBranch,
instruction,
}: {
repo: Repo;
branchName: string;
defaultBranch: string;
instruction: string;
}) {
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const [owner, repoName] = repo.url.split("/").slice(-2);

Expand All @@ -14,7 +24,10 @@ export async function createPullRequest(repo: Repo, branchName: string, defaultB
title: `Sync configs: ${instruction}`,
head: branchName,
base: defaultBranch,
body: `This pull request was automatically created by the sync-configs tool.\n\nInstruction: ${instruction}`,
body: `> [!NOTE]
> This pull request was automatically created by the @UbiquityOS Sync Configurations Agent.
>
> ${instruction}`,
});

console.log(`Pull request created: ${pullRequest.html_url}`);
Expand Down
27 changes: 27 additions & 0 deletions src/sync-configs/process-repositories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import path from "path";
import { processRepository } from "./process-repository";
import { repositories } from "./repositories";
import { REPOS_DIR } from "./sync-configs";
import * as fs from "fs";

export async function processRepositories(instruction: string, isInteractive: boolean) {
const parserRepoIndex = repositories.findIndex((repo) => repo.type === "parser");
if (parserRepoIndex === -1) {
console.error("Parser repository not found. Unable to proceed.");
return;
}
const [parserRepo] = repositories.splice(parserRepoIndex, 1);

const parserFilePath = path.join(__dirname, REPOS_DIR, parserRepo.localDir, parserRepo.filePath);
if (!fs.existsSync(parserFilePath)) {
console.error(`Parser file ${parserFilePath} does not exist. Unable to proceed.`);
return;
}
const parserCode = fs.readFileSync(parserFilePath, "utf8");

for (const repo of repositories) {
if (repo.type !== "parser") {
await processRepository(repo, instruction, parserCode, isInteractive);
}
}
}
35 changes: 35 additions & 0 deletions src/sync-configs/process-repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import path from "path";
import { applyChanges } from "./apply-changes";
import { confirmChanges } from "./confirm-changes";
import { getDiff } from "./get-diff";
import { getModifiedContent } from "./get-modified-content";
import { Repo, REPOS_DIR } from "./sync-configs";
import * as fs from "fs";

export async function processRepository(repo: Repo, instruction: string, parserCode: string, isInteractive: boolean) {
const filePath = path.join(__dirname, REPOS_DIR, repo.localDir, repo.filePath);
if (!fs.existsSync(filePath)) {
console.log(`Skipping ${repo.url} as the file ${repo.filePath} does not exist.`);
return;
}
const fileContent = fs.readFileSync(filePath, "utf8");

const modifiedContent = await getModifiedContent(fileContent, instruction, parserCode);

const tempFilePath = `${filePath}.modified`;
fs.writeFileSync(tempFilePath, modifiedContent, "utf8");

console.log(`\nDifferences for ${filePath}:`);
const diff = await getDiff(filePath, tempFilePath);
console.log(diff);

const isConfirmed = !isInteractive || (await confirmChanges(repo.url));

if (isConfirmed) {
await applyChanges({ repo, filePath, modifiedContent, instruction, isInteractive });
} else {
console.log(`Changes to ${repo.url} discarded.`);
}

// fs.unlinkSync(tempFilePath);
}
31 changes: 31 additions & 0 deletions src/sync-configs/push-modified-contents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from "path";
import { applyChanges } from "./apply-changes";
import { getDefaultBranch } from "./get-default-branch";
import { repositories } from "./repositories";
import { REPOS_DIR } from "./sync-configs";

export async function pushModifiedContents() {
for (const repo of repositories) {
if (repo.type === "parser") {
console.log(`Skipping parser repository ${repo.url}`);
continue;
}
const filePath = path.join(__dirname, REPOS_DIR, repo.localDir, repo.filePath);
const modifiedFilePath = `${filePath}.modified`;

if (fs.existsSync(modifiedFilePath)) {
const modifiedContent = fs.readFileSync(modifiedFilePath, "utf8");
const defaultBranch = await getDefaultBranch(repo.url);
await applyChanges({
repo,
filePath,
modifiedContent,
instruction: "Rerunning using `--push` flag. Original prompt has not been retained.",
isInteractive: false,
forceBranch: defaultBranch,
});
} else {
console.log(`No modified file found for ${repo.url}. Skipping.`);
}
}
}
13 changes: 13 additions & 0 deletions src/sync-configs/sync-configs-interactive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import inquirer from "inquirer";
import { processRepositories } from "./process-repositories";

export async function syncConfigsInteractive() {
const response = await inquirer.prompt([
{
type: "input",
name: "instruction",
message: "Enter the changes you want to make (in plain English):",
},
]);
await processRepositories(response.instruction, false);
}
12 changes: 12 additions & 0 deletions src/sync-configs/sync-configs-non-interactive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { processRepositories } from "./sync-configs";

export async function syncConfigsNonInteractive() {
const args = process.argv.slice(2);
const instruction = args.join(" ") || process.env.INPUT_STRING;
if (!instruction) {
throw new Error(
"No instruction provided. You need to pass in an instruction either as command-line arguments or through the INPUT_STRING environment variable."
);
}
await processRepositories(instruction, true);
}
Loading

0 comments on commit 4528b3e

Please sign in to comment.