Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ dev.db
dev.db-journal

# Prisma
prisma/migrations/
*.db
*.db-journal

Expand Down
18 changes: 18 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ API_SECRET="your-secret-key-here"
# Create at: https://github.com/settings/tokens (no scopes needed for public user info)
GITHUB_TOKEN=

# GitHub AI review (optional)
# Fine-grained PAT for the reviewer account. Grant Contents: read,
# Pull requests: read/write, and Issues: read/write on the review repository.
CODEX_REVIEW_ENABLED=false
GITHUB_REVIEW_REPOSITORY=vicinaehq/extensions
GITHUB_REVIEW_MAINTAINER=aurelleb
GITHUB_PAT=
# Secret configured on the repository webhook pointing to /webhooks/github.
GITHUB_WEBHOOK_SECRET=
# Persistent directory containing the subscription login created by `codex login`.
CODEX_REVIEW_HOME=/app/data/codex
# Optional; leave unset to use the subscription's default model.
CODEX_REVIEW_MODEL=
# Defaults to high. Use medium for faster reviews with the same policy context.
CODEX_REVIEW_REASONING_EFFORT=high
# Maximum duration of one Codex turn. Defaults to 15 minutes.
CODEX_REVIEW_TIMEOUT_MS=900000

# Upload Configuration
MAX_UPLOAD_SIZE=10485760 # 10MB in bytes

Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ jobs:
- name: Generate Prisma Client
run: bun prisma generate

- name: Validate database migrations
run: bun prisma migrate deploy

- name: Type check
run: bun run type-check

- name: Lint
run: bun run lint || echo "No lint script found, skipping..."
continue-on-error: true
- name: Check formatting and lint
run: bun run check

- name: Test
run: bun test || echo "No tests found, skipping..."
continue-on-error: true
run: bun test
10 changes: 7 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
deploy:
name: Deploy to Server
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
environment:
name: production
url: https://${{ vars.DOMAIN }}
Expand Down Expand Up @@ -43,13 +43,17 @@ jobs:
# Run migrations
bun run prisma-deploy

# Keep the deployed systemd unit in sync with the repository.
sudo install -m 0644 extra/vicinae.service /etc/systemd/system/vicinae.service
sudo systemctl daemon-reload
sudo systemctl restart vicinae

# Wait for service to be healthy
echo "Waiting for service to start..."
sleep 5

# Verify service is running
sudo systemctl is-active --quiet vicinae && echo "✅ Service is running" || echo "❌ Service failed to start"
# Verify both the process and HTTP server.
sudo systemctl is-active --quiet vicinae
curl --fail --silent --show-error http://127.0.0.1:3000/ >/dev/null

echo "Deployment completed successfully!"
11 changes: 4 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,23 @@ COPY package.json bun.lock* ./
RUN bun install --frozen-lockfile

COPY . .
COPY --from=deps /app/node_modules ./node_modules

# Generate Prisma client
RUN bun prisma generate
# Generate Prisma client (generation validates the configured datasource but does
# not create or access this temporary database).
RUN DATABASE_URL=file:/tmp/build.db bun prisma generate

# Production stage - minimal runtime image
FROM oven/bun:1-alpine AS production
WORKDIR /app

# Install sqlite3 for runtime
RUN apk add --no-cache sqlite

# Copy dependencies and built artifacts
COPY --from=deps /app/node_modules ./node_modules
COPY --from=build /app/src ./src
COPY --from=build /app/prisma ./prisma
COPY --from=build /app/package.json ./package.json

# Create storage and analytics data directories
RUN mkdir -p /app/storage /app/data
RUN mkdir -p /app/storage /app/data/codex
ENV ANALYTICS_DB_PATH=/app/data/analytics.duckdb

# Expose port
Expand Down
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,54 @@ bun prisma migrate dev
```sh
bun run dev
```

## AI-assisted pull request reviews

The backend welcomes extension contributors and automatically runs a Codex review when a non-draft pull request is opened, marked ready, reopened, or updated. Blocking findings produce `REQUEST_CHANGES`; a clean review produces `APPROVE` and marks the PR `human-reviewable`. An organization member or repository collaborator can retry by mentioning the reviewer account with a comment containing only `@<reviewer> review`.

The intended repository rule requires two approvals: the reviewer's automated extension-policy approval and a final Code Owner approval from a Vicinae maintainer. Enable stale-approval dismissal so every new commit must pass both reviewers again.

### GitHub reviewer account

Create a fine-grained personal access token for the dedicated reviewer account, limited to `vicinaehq/extensions`, with:

- Contents: read
- Pull requests: read and write
- Issues: read and write
- Metadata: read (automatically granted)

Add a repository webhook for Pull request and Issue comment events pointing to `https://store.vicinae.dev/webhooks/github`. Configure the same secret as `GITHUB_WEBHOOK_SECRET`.

Set `GITHUB_PAT`, `GITHUB_WEBHOOK_SECRET`, `GITHUB_REVIEW_REPOSITORY`, and `GITHUB_REVIEW_MAINTAINER`. The backend discovers the reviewer login from the PAT, verifies every webhook delivery, and accepts the strict `@<reviewer> review` command only from an organization member or repository collaborator.

The reviewer maintains one welcome/status comment and the following labels:

- `ai-reviewing`
- `ai-changes-requested`
- `human-reviewable`
- `ai-review-failed`

It mentions `GITHUB_REVIEW_MAINTAINER` once per commit when the automated review transitions to approved.

### Codex subscription

Keep a dedicated, persistent Codex home and authenticate it with the Codex for OSS account:

```sh
CODEX_HOME=/app/data/codex bun node_modules/@openai/codex/bin/codex.js login --device-auth
```

In Docker, run that command inside the backend container and persist `/app/data`. Then deploy the database migration and enable the worker:

```sh
bun prisma migrate deploy
```

```env
CODEX_REVIEW_ENABLED=true
CODEX_REVIEW_HOME=/app/data/codex
CODEX_REVIEW_REASONING_EFFORT=high
CODEX_REVIEW_TIMEOUT_MS=900000
```

Each job uses an ephemeral directory containing only the trusted extension-reviewer skill, PR diff, changed extension files, and the pinned `@vicinae/api` TypeScript declarations. Package runtime code is not exposed or executed. The reviewer verifies API recommendations against those declarations, recommends compatible upgrades, and can attach one-click GitHub suggested changes for small exact replacements. The Codex SDK receives a sanitized environment and a least-privilege permission profile: model-generated commands can read only minimal runtime paths and the ephemeral review workspace, with no filesystem writes, approvals, command network access, or web search. The private Codex state directory remains outside that profile. The Docker image includes Bubblewrap for Linux enforcement.
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.6/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
Loading
Loading