Skip to content

Commit

Permalink
Merge pull request #8 from ralphschuler/devel
Browse files Browse the repository at this point in the history
feat(ci): add opencommit
  • Loading branch information
ralphschuler authored Nov 26, 2023
2 parents fdf08dc + ea78681 commit 4cdb3aa
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 1,308 deletions.
32 changes: 32 additions & 0 deletions .autopr/triggers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
triggers:
- branch_name: main
run:
workflow: generate_readme_summaries
parameters:
FILE_SUMMARY_PROMPT: "Write an executive summary of this file, intended for someone seeing it for the first time. Write 3-6 bullet points, prefixed with emojis."
FILE_SUMMARY_INSTRUCTIONS: "Respond in 3-6 bullet points, using plenty of emojis."
FOLDER_SUMMARY_PROMPT: "Write an executive summary of this folder, intended for someone seeing it for the first time. Respond in 3-5 sentences."
FOLDER_SUMMARY_INSTRUCTIONS: "Respond in simple sentences, using plenty of emojis."
IGNORE_FILES:
- docs
EMPTY_FILE_SUMMARY: "This file is empty."

- branch_name: main
run:
workflow: publish_todo_issues
parameters:
ISSUE_LABEL_CHOICES:
- "easy"
- "medium"
- "hard"
ISSUE_LABEL_PROMPT: |
How hard is this task?
ISSUE_DESCRIPTION_PROMPT: |
What tips can you give to someone that's resolving this TODO?
ISSUE_DESCRIPTION_INSTRUCTIONS: |
Respond in 1-3 sentences.
- type: label
label_substring: summarize
on_pull_request: true
workflow: summarize_pr
45 changes: 45 additions & 0 deletions .github/workflows/auto-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
on:
push:
branches:
- main
issues:
types: [labeled]
issue_comment:
types: [created]
pull_request_target:
types: [labeled]

permissions:
contents: write
issues: write
pull-requests: write

jobs:
autopr:
runs-on: ubuntu-latest
steps:
- name: Install jq
run: sudo apt-get install jq
- name: Check if label was added by a collaborator
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
is_collaborator=$(curl -s -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/collaborators/${{ github.event.sender.login }}" | jq -r '.message')
if [ "$is_collaborator" == "Not Found" ]; then
echo "Label not added by a collaborator. Skipping action."
exit 78
fi
- name: Checkout
uses: actions/checkout@v2
with:
ref: main
fetch-depth: 1
- name: AutoPR
uses: irgolic/AutoPR@main
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
base_branch: main
36 changes: 36 additions & 0 deletions .github/workflows/opencommit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: 'OpenCommit Action'

on:
push:
branches:
- main

jobs:
opencommit:
timeout-minutes: 10
name: OpenCommit
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: Setup Node.js Environment
uses: actions/setup-node@v2
with:
node-version: '16'
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: di-sukharev/[email protected]
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

env:
OCO_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}

# customization
OCO_OPENAI_MAX_TOKENS: 500
OCO_OPENAI_BASE_PATH: ''
OCO_DESCRIPTION: true
OCO_EMOJI: true
OCO_MODEL: gpt-3.5-turbo-16k
OCO_LANGUAGE: en
OCO_PROMPT_MODULE: conventional-commit
4 changes: 0 additions & 4 deletions .husky/commit-msg

This file was deleted.

8 changes: 0 additions & 8 deletions commitlint.config.js

This file was deleted.

6 changes: 0 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
],
"scripts": {
"publish": "yarn workspaces foreach -Apt run publish",
"husky:install": "husky install",
"prepare": "yarn husky:install && yarn workspaces foreach -Apt run prepare",
"build": "yarn workspaces foreach -Apt run build",
"test": "yarn workspaces foreach -Apt run test",
Expand All @@ -20,10 +19,5 @@
"packageManager": "[email protected]",
"dependencies": {
"tsx": "^4.1.4"
},
"devDependencies": {
"@commitlint/cli": "^18.4.3",
"@commitlint/config-conventional": "^18.4.3",
"husky": "^8.0.3"
}
}
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"start": "tsx src/index.ts"
},
"dependencies": {
"@ralphschuler/ts-error": "workspace:^",
"tsx": "^4.1.4"
}
}
3 changes: 3 additions & 0 deletions packages/cli/src/Cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class Cli {

}
30 changes: 30 additions & 0 deletions packages/cli/src/commands/HelloWorld.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export class HelloWorldCommand extends Command {
public static name = "hello-world";
public static description = "A simple hello world command";

public static arguments: IArgument<any>[] = [
{
name: "name",
description: "Your name",
type: "string",
required: true,
},
];

public static flags: IFlag<any>[] = [
{
name: "times",
description: "Number of times to say hello",
type: "number",
default: 1,
},
];

public async run(context: IContext) {
const { args, flags } = context;

for (let i = 0; i < flags.times; i++) {
console.log(`Hello ${args.name}!`);
}
}
}
184 changes: 171 additions & 13 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,189 @@
import { noThrow, isError } from "@ralphschuler/ts-error";

interface IParameter<T> {
name: string;
type: T;
description?: string;
help?: string;
type: T; // Changed to directly use the type
value: T;
validator?: (value: T) => boolean;
}

class MissingArgumentError extends Error {
constructor(argumentName: string) {
super(`Missing argument: ${argumentName}`);
}
}

class MissingFlagError extends Error {
constructor(flagName: string) {
super(`Missing flag: ${flagName}`);
}
}

interface IFlag<T> extends IParameter<T> {
class ValidationError extends Error {
constructor(message: string) {
super(message);
}
}

class ExecutionError extends Error {
constructor(message: string) {
super(message);
}
}

class CommandNotFoundError extends Error {
constructor(commandName: string) {
super(`Command not found: ${commandName}`);
}
}

class CommandAlreadyExistsError extends Error {
constructor(commandName: string) {
super(`Command already exists: ${commandName}`);
}
}

interface IFlag<T extends string | number | boolean> extends IParameter<T> {
alias?: string;
default?: T;
}

interface IArgument<T> extends IParameter<T> {
required?: boolean;
interface IArgument<T extends string | number | boolean> extends IParameter<T> {
required: boolean;
}

interface ICollection<T> {
[key: string]: T;
get: (name: string) => T | undefined; // Corrected return type
}

interface IFlagCollection extends ICollection<IFlag<any>> {}
interface IArgumentCollection extends ICollection<IArgument<any>> {}

interface IContext {
args: string[];
flags: Record<string, any>;
args: IArgumentCollection;
flags: IFlagCollection;
}

interface ICommand {
name: string;
description?: string;
arguments?: IArgument<any>[];
flags?: IFlag<any>[];
run: (context: IContext) => void;
type CommandFunction = (context: IContext) => Promise<void> | void;
type MiddlewareFunction = (context: IContext, next: CommandFunction) => void;

abstract class Command<T extends IArgument<any>, U extends IFlag<any>> {
abstract name: string;
abstract description: string;
abstract help: string;
abstract args?: T[];
abstract flags?: U[];
abstract run: CommandFunction;
}

interface ICommandHandler {
commands: ICommand[];
addCommand(command: ICommand): void;
removeCommand(command: ICommand): void;
run(input: string): Promise<void>;
}

class CommandHandler implements ICommandHandler {
commands: ICommand[] = [];
middlewares: MiddlewareFunction[] = [];

addCommand(command: ICommand): void {
if (this.commands.find((cmd) => cmd.name === command.name)) {
throw new CommandAlreadyExistsError(command.name);
}
this.commands.push(command);
}

removeCommand(command: ICommand): void {
if (!this.commands.find((cmd) => cmd.name === command.name)) {
throw new CommandNotFoundError(command.name);
}
this.commands = this.commands.filter((cmd) => cmd.name !== command.name);
}

use(middleware: MiddlewareFunction): void {
this.middlewares.push(middleware);
}

async run(input: string): Promise<void> {
const [commandName, ...params] = input.split(/\s+/);
const command = this.commands.find((cmd) => cmd.name === commandName);

if (!command) {
throw new CommandNotFoundError(commandName);
}

const context: IContext = {
args: {},
flags: {},
};

this.parseArgumentsAndFlags(params, command, context);

const runWithMiddlewares = async () => {
let index = -1;

const runner = async (i: number): Promise<void> => {
if (i <= index) {
throw new Error("next() called multiple times");
}

index = i;
const middleware = this.middlewares[i];
if (middleware) {
await middleware(context, () => runner(i + 1));
} else {
await command.run(context);
}
};

await runner(0);
};

await runWithMiddlewares();
}

private parseArgumentsAndFlags(
params: string[],
command: ICommand,
context: IContext,
): void {
let currentArgIndex = 0;

for (const param of params) {
if (param.startsWith("--")) {
const [flagName, flagValue] = param.substring(2).split('=');
const flag = command.flags?.find(
(f) => f.name === flagName || f.alias === flagName,
);
if (!flag) {
throw new MissingFlagError(flagName);
}
context.flags[flag.name] = flagValue ?? true; // Support for value flags
} else {
if (command.args && command.args.length > currentArgIndex) {
const arg = command.args[currentArgIndex];
context.args[arg.name] = param;
currentArgIndex++;
}
}
}

command.args?.forEach((arg) => {
if (arg.required && context.args[arg.name] === undefined) {
throw new MissingArgumentError(arg.name);
}
});

command.flags?.forEach((flag) => {
if (
context.flags[flag.name] === undefined &&
flag.default !== undefined
) {
context.flags[flag.name] = flag.default;
}
});
}
}
Loading

0 comments on commit 4cdb3aa

Please sign in to comment.