Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ac92f14
feat: add support for custom domain and managed certificate in deploy…
webmaxru Apr 1, 2026
98cc3b9
feat: add user-assigned managed identity for ACR pull and update role…
webmaxru Apr 1, 2026
8620d10
feat: add favicon assets and generation script
webmaxru Apr 1, 2026
bd2e967
Refactor code structure for improved readability and maintainability
webmaxru Apr 1, 2026
a77e8fe
feat: add support for custom domain configuration and ACR admin crede…
webmaxru Apr 1, 2026
f267f90
feat: update Open Graph and Twitter Card meta tags to support dynamic…
webmaxru Apr 1, 2026
26d42fe
feat: enhance custom domain handling with validation and dynamic site…
webmaxru Apr 1, 2026
c756d33
fix: correct frontend directory path in Dockerfile
webmaxru Apr 1, 2026
b6fb117
Update webapp/backend/src/server.js
webmaxru Apr 1, 2026
4dc269c
Update infra/webapp/main.bicep
webmaxru Apr 1, 2026
2390cab
Update webapp/backend/src/server.js
webmaxru Apr 1, 2026
9bad285
test: add progress spinner tests and fix CSS hidden attribute override
webmaxru Apr 1, 2026
6bd5b21
Update webapp/backend/src/server.js
webmaxru Apr 1, 2026
b5a497e
Update webapp/backend/tests/routes.test.js
webmaxru Apr 1, 2026
c6b755f
fix: update custom domain condition to check for DNS verification rea…
webmaxru Apr 1, 2026
c865eef
fix: handle comma-separated host headers in createApp function
webmaxru Apr 1, 2026
7f6b6ca
fix: align runtime.port with actual ephemeral port for correct URL re…
webmaxru Apr 1, 2026
c5b3158
Update webapp/backend/src/server.js
webmaxru Apr 1, 2026
032d1a3
fix: enable cross-origin access to static assets for social media cra…
webmaxru Apr 1, 2026
633ff6f
Merge branch 'webapp-custom-domain' of https://github.com/webmaxru/ag…
webmaxru Apr 1, 2026
3a7e63c
Update webapp/.env.example
webmaxru Apr 1, 2026
8a3be6b
fix: update root route to serve index.html and prevent direct serving…
webmaxru Apr 1, 2026
f464041
Merge branch 'webapp-custom-domain' of https://github.com/webmaxru/ag…
webmaxru Apr 1, 2026
0f8f160
fix: update Open Graph image for improved social media sharing
webmaxru Apr 1, 2026
9dd8e1b
Update webapp/backend/src/server.js
webmaxru Apr 1, 2026
3956c9a
Update infra/webapp/main.bicep
webmaxru Apr 2, 2026
629cebb
feat: add deployment instructions for webapp and update test environm…
webmaxru Apr 2, 2026
a2b6a0d
docs: update local webapp setup instructions for clarity and synchron…
webmaxru Apr 2, 2026
4b5e233
chore: remove .github instruction files to unblock fork PR eval
webmaxru Apr 2, 2026
ca78797
Update .github/workflows/webapp-cd.yml
webmaxru Apr 2, 2026
bccaf10
refactor: improve server closure handling in API route tests
webmaxru Apr 3, 2026
e95975d
Merge branch 'webapp-custom-domain' of https://github.com/webmaxru/ag…
webmaxru Apr 3, 2026
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
26 changes: 26 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
description: "Global rules for the agentrc project."
---

# Global Copilot Instructions

## Webapp Deployment Instructions — Auto-Update Rule

Whenever you modify any file matching the patterns below, review `.github/instructions/webapp-deploy.instructions.md` and update it if the change affects deployment behavior:

- `webapp/**` — frontend or backend code, dependencies, config
- `Dockerfile.webapp` — container build instructions
- `infra/webapp/**` — Bicep infrastructure templates
- `packages/core/src/**` — shared library bundled into the backend

Changes that require updating the deployment instructions include:

- New environment variables or secrets added to the container app
- New files or directories that the Dockerfile copies
- Changes to the esbuild config or build pipeline
- New Azure resources in the Bicep template
- Changes to the ACR registry name, container app name, or resource group
- Changes to dependency structure (new `package.json` files copied in Docker build)
- New probes, scaling rules, or ingress configuration

Do NOT update the deployment instructions for changes that are purely internal (test files, local dev config, code logic that doesn't affect the build/deploy pipeline).
138 changes: 138 additions & 0 deletions .github/instructions/webapp-deploy.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
description: "Webapp deployment guide. Determines the MINIMUM deployment steps needed based on which files changed. Covers infra (Bicep), Docker image (ACR build), and container app update."
applyTo: "webapp/**,Dockerfile.webapp,infra/webapp/**,packages/core/src/**"
---

# Webapp Deployment — Minimum Required Actions

When the user asks to deploy the webapp, determine the **minimum set of actions** needed based on which files changed. Do NOT run a full deployment every time. Use the decision tree below.

## Azure Resource Names

| Resource | Name / Value |
| ---------------- | ------------------------------- |
| Resource group | `agentrc-webapp` |
| Container App | `agentrc-webapp` |
| ACR registry | `agentrcwebapp` |
| Image repository | `agentrc-webapp` |
| Custom domain | `agentrc.isainative.dev` |
| Dockerfile | `Dockerfile.webapp` (repo root) |
| Bicep entrypoint | `infra/webapp/main.bicep` |
| Bicep params | `infra/webapp/main.bicepparam` |

## Decision Tree — What Changed → What to Do

### 1. Infrastructure changes (`infra/webapp/**`)

Files: `infra/webapp/main.bicep`, `infra/webapp/main.bicepparam`

These change Azure resources (Container Apps Environment, ACR, storage, networking, secrets, probes, scale rules, custom domain). **Full infra redeployment required.**

```sh
# Validate first
az bicep build --file infra/webapp/main.bicep

# Deploy infrastructure
az deployment group create \
--resource-group agentrc-webapp \
--template-file infra/webapp/main.bicep \
--parameters infra/webapp/main.bicepparam

# If container image also changed, follow steps 2+3 after.
# If only infra params changed (e.g. scaling, domain), this is sufficient.
```

### 2. Docker build required (image rebuild + push to ACR)

A new container image must be built when **any** of these files changed:

| Path pattern | Reason |
| ---------------------------------- | ------------------------------------------------- |
| `Dockerfile.webapp` | Build instructions themselves changed |
| `webapp/backend/src/**` | Backend application code (bundled by esbuild) |
| `webapp/backend/esbuild.config.js` | Build config for backend bundle |
| `webapp/backend/package.json` | Backend dependencies |
| `webapp/backend/package-lock.json` | Backend dependency lockfile |
| `webapp/frontend/**` | Static frontend files (copied into image as-is) |
| `packages/core/src/**` | Shared core library (aliased into backend bundle) |
| `package.json` (root) | Root workspace dependencies |
| `package-lock.json` (root) | Root workspace lockfile |

Build command — run from repo root:

```sh
az acr build \
--registry agentrcwebapp \
--image agentrc-webapp:<tag> \
--file Dockerfile.webapp .
```

Pick a descriptive `<tag>` for the change (e.g. `fix-og-meta`, `update-styles`), or use `latest`.

**After building, always proceed to step 3.**

### 3. Container App update (deploy new image)

After pushing a new image to ACR, update the running container:

```sh
az containerapp update \
--name agentrc-webapp \
--resource-group agentrc-webapp \
--image agentrcwebapp.azurecr.io/agentrc-webapp:<tag>
```

Use the same `<tag>` from step 2. This is the only step needed when the image tag changed but no infra changes occurred.

## Quick Reference — Change → Minimum Actions

| What changed | Actions needed |
| -------------------------------------------- | ------------------------------------- |
| `webapp/frontend/` only (HTML/CSS/JS/assets) | ACR build → App update |
| `webapp/backend/src/` only | ACR build → App update |
| `packages/core/src/` only | ACR build → App update |
| `Dockerfile.webapp` | ACR build → App update |
| `webapp/backend/package.json` (deps) | ACR build → App update |
| `infra/webapp/main.bicep` (resources) | Bicep deploy |
| `infra/webapp/main.bicepparam` (params) | Bicep deploy |
| Infra + app code together | Bicep deploy → ACR build → App update |
| `webapp/backend/tests/**` only | No deployment needed |
| `webapp/frontend/tests/**` only | No deployment needed |
| `webapp/backend/vitest.config.js` only | No deployment needed |
| `webapp/frontend/vitest.config.js` only | No deployment needed |
| `webapp/docker-compose.yml` only | No deployment needed (local dev only) |
| `webapp/.env` or `webapp/.env.example` | No deployment needed (local dev only) |

## Build Pipeline Details

The Docker build has three stages:

1. **deps** — `npm ci` for root workspace + backend (installs `@agentrc/core` from `packages/core/`)
2. **build** — `node esbuild.config.js` bundles `webapp/backend/src/server.js` → `dist/server.js`, resolving `@agentrc/core` via alias to `packages/core/src/`
3. **runtime** — Node 24 Alpine, copies `dist/`, `node_modules/`, and `webapp/frontend/` (served as static files by Express)

The frontend has no build step — files in `webapp/frontend/` are served directly by `express.static`.

## Pre-deploy Checklist

Before deploying, run backend tests to verify the change:

```sh
cd webapp/backend && npx vitest run
```

If frontend tests exist:

```sh
cd webapp/frontend && npx vitest run
```

## Container App Architecture

- **Hosting**: Azure Container Apps (Consumption, East US)
- **Ingress**: External, port 3000, HTTPS only
- **Identity**: User-assigned managed identity for ACR pull (no admin credentials)
- **Storage**: Azure Files mount at `/app/data` for shared reports
- **Monitoring**: Application Insights via connection string secret
- **Scaling**: 1–4 replicas, HTTP-based autoscaling
- **Health**: Liveness + Readiness probes on `/api/health`
24 changes: 14 additions & 10 deletions .github/prompts/align-cli-webapp-reports.prompt.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
---
description: Compare CLI visual readiness report with local webapp report for a given repo, identify differences in checks/rendering/scoring, and fix them
description: Compare CLI visual readiness report with local webapp report for a given repo, identify rendering/scoring differences, and fix them in the webapp only
---

You are debugging consistency between two readiness report outputs for the **AgentRC** project:

1. **CLI visual report** — generated by `npm run dev -- readiness --visual` from the repo root (produces an HTML file)
2. **Webapp report** — rendered by the local dev server at `http://localhost:3000/{owner}/{repo}`

Both should produce identical results for the same repository because they share the same core engine (`packages/core/src/services/readiness.ts`). In practice they can diverge due to rendering differences or scoring logic bugs.
Both should produce identical results for the same repository because they share the same core engine (`packages/core/src/services/readiness.ts`). In practice the webapp rendering can diverge from the CLI due to its independent rendering logic.

> **IMPORTANT CONSTRAINT**: The CLI report and `packages/core/` are the **source of truth**. All fixes MUST be made exclusively in the `webapp/` directory (frontend and/or backend). **Never modify files in `packages/core/` or `src/`** — if the webapp disagrees with the CLI, the webapp is wrong.

## Architecture Reference

### Shared Core (source of truth for checks)
### Shared Core (source of truth — DO NOT MODIFY)

- `packages/core/src/services/readiness.ts` — All criteria definitions, `countStatus()`, `buildCriteria()`, `buildExtras()`, pillar/level aggregation
- Criteria scopes: `repo` (always), `app` (per-application), `area` (only with `--per-area`)
- `countStatus()` **excludes** skipped checks from the denominator when computing pillar pass/total
- Extras (bonus checks) are **not scored** — they don't affect levels or totals

### CLI Rendering
### CLI Rendering (source of truth — DO NOT MODIFY)

- `packages/core/src/services/visualReport.ts` — Generates the standalone HTML report
- `calculateAiToolingData()` — Aggregates AI criteria across repos (counts all including skipped in the hero display)
- Total checks: `report.pillars.reduce((s, p) => s + p.total, 0)`
- Does **not** render bonus/extras section in HTML output

### Webapp Backend
### Webapp Backend (fix here if needed)

- `webapp/backend/src/services/scanner.js` — Clones repo, calls `runReadinessReport()` from `@agentrc/core`
- `webapp/backend/src/routes/scan.js` — `POST /api/scan` endpoint
- Returns the raw `ReadinessReport` JSON (same shape as CLI)
- Uses `@agentrc/core` as a `file:../../packages/core` dependency — always uses local source code

### Webapp Frontend
### Webapp Frontend (fix here if needed)

- `webapp/frontend/src/report.js` — Independent rendering implementation (NOT shared with CLI)
- `buildHero()` — Total from `report.pillars.reduce((s, p) => s + p.total, 0)`
Expand Down Expand Up @@ -122,12 +124,14 @@ Both should produce identical results for the same repository because they share

### Phase 4: Root Cause & Fix

> **Reminder**: The CLI and `packages/core/` are the source of truth. All fixes go in `webapp/` only.

10. For each difference found, classify as:
- **Rendering divergence** → Fix in either `visualReport.ts` (CLI) or `report.js` (webapp) to align
- **Scoring logic bug** → Fix in `readiness.ts` (core) which fixes both
- **Icon/label mapping gap** → Update the icon map in the affected renderer
- **Rendering divergence** → Fix in `webapp/frontend/src/report.js` to match CLI behavior
- **Scoring logic divergence** → Fix in `webapp/backend/` or `webapp/frontend/` to align with core's scoring
- **Icon/label mapping gap** → Update the icon/label map in `webapp/frontend/src/report.js`

11. Implement the fixes directly in the source files.
11. Implement the fixes directly in the `webapp/` source files. **Never edit** files in `packages/core/`, `src/`, or any other directory outside `webapp/`.

12. After fixing, restart the webapp dev server and re-run Phase 1-2 to verify alignment.

Expand Down
27 changes: 25 additions & 2 deletions .github/workflows/webapp-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ permissions:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/agentrc-webapp
RESOURCE_GROUP: agentrc-webapp-rg
RESOURCE_GROUP: agentrc-webapp
BICEP_FILE: infra/webapp/main.bicep

jobs:
Expand Down Expand Up @@ -133,14 +133,30 @@ jobs:
2>&1 || echo "Storage mount does not exist yet"
sleep 10

- name: Deploy infrastructure
- name: Deploy infrastructure (step 1 — app + domain registration)
uses: azure/arm-deploy@v2
with:
resourceGroupName: ${{ env.RESOURCE_GROUP }}
template: ${{ env.BICEP_FILE }}
parameters: >
containerImageTag=${{ needs.build-push.outputs.image-tag }}
ghTokenForScan=${{ secrets.GH_TOKEN_FOR_SCAN }}
useAcrAdminCredentials=${{ vars.USE_ACR_ADMIN_CREDENTIALS == 'true' }}
customDomain=${{ vars.CUSTOM_DOMAIN || '' }}
customDomainCertReady=false

Comment thread
webmaxru marked this conversation as resolved.
- name: Deploy infrastructure (step 2 — bind managed certificate)
if: vars.CUSTOM_DOMAIN != '' && vars.CUSTOM_DOMAIN_CERT_READY == 'true'
Comment thread
webmaxru marked this conversation as resolved.
Outdated
uses: azure/arm-deploy@v2
with:
resourceGroupName: ${{ env.RESOURCE_GROUP }}
template: ${{ env.BICEP_FILE }}
parameters: >
containerImageTag=${{ needs.build-push.outputs.image-tag }}
ghTokenForScan=${{ secrets.GH_TOKEN_FOR_SCAN }}
useAcrAdminCredentials=${{ vars.USE_ACR_ADMIN_CREDENTIALS == 'true' }}
customDomain=${{ vars.CUSTOM_DOMAIN || '' }}
customDomainCertReady=true

- name: Ensure image in ACR
run: |
Expand Down Expand Up @@ -176,3 +192,10 @@ jobs:
curl -sf "https://${APP_URL}/api/health" | grep -q '"ok"'
curl -sf "https://${APP_URL}/" | grep -q "AgentRC"
echo "Smoke tests passed!"

CUSTOM_DOMAIN="${{ vars.CUSTOM_DOMAIN }}"
if [ -n "$CUSTOM_DOMAIN" ] && [ "${{ vars.CUSTOM_DOMAIN_CERT_READY }}" = "true" ]; then
echo "Testing custom domain https://${CUSTOM_DOMAIN}"
curl -sf "https://${CUSTOM_DOMAIN}/api/health" | grep -q '"ok"'
echo "Custom domain smoke test passed!"
fi
2 changes: 1 addition & 1 deletion Dockerfile.webapp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ COPY webapp/backend/package.json ./package.json
COPY --from=deps /app/webapp/backend/node_modules ./node_modules
COPY --from=deps /app/node_modules /app/node_modules
COPY --from=build /app/webapp/backend/dist ./dist
COPY webapp/frontend/ /app/frontend/
COPY webapp/frontend/ /app/webapp/frontend/
ENV REPORTS_DIR=/app/data/reports
RUN mkdir -p /app/data \
&& chown -R node:node /app
Expand Down
Loading
Loading