From a24961a55ce3adb779bcf3547b695a194ae8dc4d Mon Sep 17 00:00:00 2001 From: ztimson Date: Sat, 27 Dec 2025 22:03:14 -0500 Subject: [PATCH] Use npx instead --- .editorconfig | 2 +- .github/workflows/build.yml | 70 +++++++++++++++++++----------------- .github/workflows/review.yml | 27 +++++++------- Dockerfile | 7 ---- README.md | 55 ++++++---------------------- package.json | 22 +++++++----- src/review.mjs | 16 +++++---- 7 files changed, 84 insertions(+), 115 deletions(-) delete mode 100644 Dockerfile diff --git a/.editorconfig b/.editorconfig index df2f981..3d9a482 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,4 +13,4 @@ quote_type = single [*.md] max_line_length = off -trim_trailing_whitespace = false \ No newline at end of file +trim_trailing_whitespace = false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da3ef4e..8bacd35 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,44 +1,48 @@ -name: Build and publish -run-name: Build and publish +name: Publish Library +run-name: Publish Library on: push: jobs: - container: - name: Build Container + build: + name: Build NPM Project runs-on: ubuntu-latest - container: docker + container: node:alpine steps: - - name: Build Container - run: | - git clone -b "${{github.ref_name}}" "$(echo ${{github.server_url}}/${{github.repository}}.git | sed s%://%://${{github.token}}@% )" . - DOCKER_HUB=$([ -n "${{secrets.DOCKER_HUB_USER}}" ] && [ -n "${{secrets.DOCKER_HUB_TOKEN}}" ] && [ -n "${{secrets.DOCKER_HUB_IMAGE}}" ] && echo "true" || echo "false") - REGISTRY="$(echo "${{github.server_url}}" | sed -E 's|https?://||')" - VERSION="$(cat package.json | grep version | grep -Eo '[0-9][[:alnum:]\.\/\-]+')" + - name: Clone Repository + uses: ztimson/actions/clone@develop - docker login -u "${{github.repository_owner}}" -p "${{secrets.DEPLOY_TOKEN}}" "$REGISTRY" - if [ "$DOCKER_HUB" = "true" ]; then docker login -u "${{secrets.DOCKER_HUB_USER}}" -p "${{secrets.DOCKER_HUB_TOKEN}}" docker.io; fi + - name: Install & Build + run: npm i && npm run build - docker build -t "$REGISTRY/${{github.repository}}:${{github.ref_name}}" . - docker push "$REGISTRY/${{github.repository}}:${{github.ref_name}}" - if [ "$DOCKER_HUB" = "true" ]; then - docker tag "$REGISTRY/${{github.repository}}:${{github.ref_name}}" "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:${{github.ref_name}}" - docker push "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:${{github.ref_name}}" - fi + - name: Publish Library + run: | + if [ "${{github.ref_name}}" = "master" ]; then + REGISTRY="${{github.server_url}}/api/packages/${{github.repository_owner}}/npm/" + npm set registry "$REGISTRY" + npm set $(echo $REGISTRY | sed s%http:%% | sed s%https:%% ):_authToken "${{secrets.DEPLOY_TOKEN}}" + npm publish || echo "Failed to publish" - if [ "${{github.ref_name}}" = "master" ]; then - docker tag "$REGISTRY/${{github.repository}}:${{github.ref_name}}" "$REGISTRY/${{github.repository}}:$VERSION" - docker push "$REGISTRY/${{github.repository}}:$VERSION" - if [ "$DOCKER_HUB" = "true" ]; then - docker tag "$REGISTRY/${{github.repository}}:${{github.ref_name}}" "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:$VERSION" - docker push "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:$VERSION" - fi + REGISTRY="https://registry.npmjs.org/" + npm set registry "$REGISTRY" + npm set $(echo $REGISTRY | sed s%http:%% | sed s%https:%% ):_authToken "${{secrets.NPM_TOKEN}}" + npm publish || echo "Failed to publish" + fi + tag: + name: Tag Version + needs: build + if: ${{github.ref_name}} == 'release' + runs-on: ubuntu-latest + container: node:alpine + steps: + - name: Clone Repository + uses: ztimson/actions/clone@develop - docker tag "$REGISTRY/${{github.repository}}:${{github.ref_name}}" "$REGISTRY/${{github.repository}}:latest" - docker push "$REGISTRY/${{github.repository}}:latest" - if [ "$DOCKER_HUB" = "true" ]; then - docker tag "$REGISTRY/${{github.repository}}:${{github.ref_name}}" "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:latest" - docker push "docker.io/${{secrets.DOCKER_HUB_IMAGE}}:latest" - fi - fi + - name: Get Version Number + run: echo "VERSION=$(cat package.json | grep version | grep -Eo ':.+' | grep -Eo '[[:alnum:]\.\/\-]+')" >> $GITHUB_ENV + + - name: Tag Version + uses: ztimson/actions/tag@develop + with: + tag: ${{env.VERSION}} diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index 210fe62..13550a3 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -6,7 +6,7 @@ on: jobs: review: runs-on: ubuntu-latest - container: docker + container: node:22 steps: - name: Fetch code run: | @@ -15,17 +15,14 @@ jobs: git fetch origin ${{ github.event.pull_request.base.ref }} - name: Run AI Review - run: | - echo $GITHUB_WORKSPACE - docker pull "git.zakscode.com/ztimson/ai-reviewer:test" - docker run --rm -v $GITHUB_WORKSPACE:/app \ - -e AI_HOST=anthropic \ - -e AI_MODEL=claude-sonnet-4-5 \ - -e AI_TOKEN="${{ secrets.ANTHROPIC_TOKEN }}" \ - -e GIT_HOST="${{ github.server_url }}" \ - -e GIT_OWNER="${{ github.repository_owner }}" \ - -e GIT_REPO="${{ github.event.repository.name }}" \ - -e GIT_TOKEN="${{ secrets.ASSISTANT_TOKEN }}" \ - -e GIT_BRANCH="origin/${{ github.event.pull_request.base.ref }}" \ - -e PULL_REQUEST="${{ github.event.pull_request.number }}" \ - "git.zakscode.com/ztimson/ai-reviewer:test" + run: npx -y @ztimson/ai-agents review + env: + AI_HOST: anthropic + AI_MODEL: claude-sonnet-4-5 + AI_TOKEN: ${{ secrets.ANTHROPIC_TOKEN }} + GIT_HOST: ${{ github.server_url }} + GIT_OWNER: ${{ github.repository_owner }} + GIT_REPO: ${{ github.event.repository.name }} + GIT_TOKEN: ${{ secrets.ASSISTANT_TOKEN }} + GIT_BRANCH: origin/${{ github.event.pull_request.base.ref }} + PULL_REQUEST: ${{ github.event.pull_request.number }} diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 0e56696..0000000 --- a/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -FROM node:22 - -COPY . /ai -RUN cd /ai && npm ci && mkdir -p /app - -WORKDIR /app -ENTRYPOINT ["node", "/ai/src/review.mjs", "/app"] diff --git a/README.md b/README.md index 8b9f029..5802b71 100644 --- a/README.md +++ b/README.md @@ -6,29 +6,29 @@ Logo -### AI Reviewer +### AI Agents -Automated AI-powered code review for pull requests 🤖 +Automated AI-powered agents for automated reviews and code assistance -[![Version](https://img.shields.io/badge/dynamic/json.svg?label=Version&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-reviewer/tags&query=$[0].name)](https://git.zakscode.com/ztimson/ai-reviewer/tags) -[![Pull Requests](https://img.shields.io/badge/dynamic/json.svg?label=Pull%20Requests&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-reviewer&query=open_pr_counter)](https://git.zakscode.com/ztimson/ai-reviewer/pulls) -[![Issues](https://img.shields.io/badge/dynamic/json.svg?label=Issues&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-reviewer&query=open_issues_count)](https://git.zakscode.com/ztimson/ai-reviewer/issues) +[![Version](https://img.shields.io/badge/dynamic/json.svg?label=Version&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents/tags&query=$[0].name)](https://git.zakscode.com/ztimson/ai-agents/tags) +[![Pull Requests](https://img.shields.io/badge/dynamic/json.svg?label=Pull%20Requests&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents&query=open_pr_counter)](https://git.zakscode.com/ztimson/ai-agents/pulls) +[![Issues](https://img.shields.io/badge/dynamic/json.svg?label=Issues&style=for-the-badge&url=https://git.zakscode.com/api/v1/repos/ztimson/ai-agents&query=open_issues_count)](https://git.zakscode.com/ztimson/ai-agents/issues) ---
- Release Notes - • Report a Bug - • Request a Feature + Release Notes + • Report a Bug + • Request a Feature
--- ## Table of Contents -- [AI Reviewer](#top) +- [AI Agents](#top) - [About](#about) - [Built With](#built-with) - [Setup](#setup) @@ -37,7 +37,7 @@ Automated AI-powered code review for pull requests 🤖 ## About -Automated code reviewer that uses AI to analyze git diffs and provide inline comments on pull requests. Supports Anthropic, OpenAI, and Ollama models with tool-based reviewing for precise feedback. +Automated code agents that uses AI to analyze git diffs and provide inline comments on pull requests. Supports Anthropic, OpenAI, and Ollama models with tool-based reviewing for precise feedback. ### Built With [![Docker](https://img.shields.io/badge/Docker-384d54?style=for-the-badge&logo=docker)](https://docker.com/) @@ -54,40 +54,7 @@ Automated code reviewer that uses AI to analyze git diffs and provide inline com #### Instructions -1. Add the following git action: -```yaml -name: Code review -on: - pull_request: - types: [opened, synchronize, reopened] - -jobs: - review: - runs-on: ubuntu-latest - container: docker - steps: - - name: Fetch code - run: | - git clone "$(echo ${{github.server_url}}/${{github.repository}}.git | sed s%://%://${{github.token}}@% )" . - git checkout ${{ github.event.pull_request.head.sha }} - git fetch origin ${{ github.event.pull_request.base.ref }} - - - name: Run AI Review - run: | - echo $GITHUB_WORKSPACE - docker pull "git.zakscode.com/ztimson/ai-reviewer:test" - docker run --rm -v $GITHUB_WORKSPACE:/app \ - -e AI_HOST=anthropic \ - -e AI_MODEL=claude-sonnet-4-5 \ - -e AI_TOKEN="${{ secrets.ANTHROPIC_TOKEN }}" \ - -e GIT_HOST="${{ github.server_url }}" \ - -e GIT_OWNER="${{ github.repository_owner }}" \ - -e GIT_REPO="${{ github.event.repository.name }}" \ - -e GIT_TOKEN="${{ secrets.ASSISTANT_TOKEN }}" \ - -e GIT_BRANCH="origin/${{ github.event.pull_request.base.ref }}" \ - -e PULL_REQUEST="${{ github.event.pull_request.number }}" \ - "git.zakscode.com/ztimson/ai-reviewer:test" -``` +1. Run using npx: `npx @ztimson/ai-agents review` diff --git a/package.json b/package.json index 696572e..9d29b97 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,21 @@ { - "name": "ai-reviewer", - "version": "0.0.0", - "scripts": { - "review": "node src/review.mjs" - }, - "keywords": [], - "author": "", + "name": "@ztimson/ai-agents", + "version": "0.0.3", + "description": "AI agents", + "keywords": ["ai", "review"], + "author": "ztimson", "license": "ISC", - "description": "", + "type": "module", + "bin": { + "review": "./src/review.mjs" + }, "dependencies": { "@ztimson/ai-utils": "^0.2.4", "@ztimson/node-utils": "^1.0.7", "@ztimson/utils": "^0.28.3", "dotenv": "^17.2.3" - } + }, + "files": [ + "src/" + ] } diff --git a/src/review.mjs b/src/review.mjs index 7405da0..502a94f 100644 --- a/src/review.mjs +++ b/src/review.mjs @@ -1,3 +1,5 @@ +#!/usr/bin/env node + import {Ai} from '@ztimson/ai-utils'; import {$} from '@ztimson/node-utils'; import * as os from 'node:os'; @@ -5,12 +7,14 @@ import * as path from 'node:path'; import * as fs from 'node:fs'; import * as dotenv from 'dotenv'; -dotenv.config({debug: false}); -dotenv.config({path: '.env.local', override: true, debug: false}); +dotenv.config({quiet: true, debug: false}); +dotenv.config({path: '.env.local', override: true, quiet: true, debug: false}); (async () => { - const root = process.argv[2] || process.cwd(), - branch = process.env['GIT_BRANCH'] || await $`cd ${root} && git symbolic-ref refs/remotes/origin/HEAD`, + let p = process.argv[process.argv.length - 1]; + if(p === 'review' || p.endsWith('review.mjs')) p = null; + + const root = p || process.cwd(), git = process.env['GIT_HOST'], owner = process.env['GIT_OWNER'], repo = process.env['GIT_REPO'], @@ -21,11 +25,11 @@ dotenv.config({path: '.env.local', override: true, debug: false}); token = process.env['AI_TOKEN']; console.log(`Reviewing: ${root}\n`); + const branch = process.env['GIT_BRANCH'] || await $`cd ${root} && git symbolic-ref refs/remotes/origin/HEAD`; const comments = []; const commit = await $`cd ${root} && git log -1 --pretty=format:%H`; const gitDiff = await $`cd ${root} && git diff ${branch}`; - let options = {ollama: {model, host}}; if(host === 'anthropic') options = {anthropic: {model, token}}; else if(host === 'openai') options = {openAi: {model, token}}; @@ -33,7 +37,7 @@ dotenv.config({path: '.env.local', override: true, debug: false}); ...options, model: [host, model], path: process.env['path'] || os.tmpdir(), - system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity. After making all recommendations, provide a brief bullet point summary in markdown.`, + system: `You are a code reviewer. Analyze the git diff and use the \`recommend\` tool for EACH issue you find. You must call \`recommend\` exactly once for every bug or improvement opportunity directly related to changes. Ignore formatting recommendations. After making all recommendations, provide one brief bullet-point summary.`, tools: [{ name: 'read_file', description: 'Read contents of a file',