Skip to content

Commit 8b7ea4e

Browse files
droyadclaude
andauthored
Add Hyponome PR review microsite at /pr-review (browser-only, GH Pages) (#1684)
* Add Hyponome PR review microsite at /pr-review Browser-only successor to the OctopusDeploy/Hyponome ASP.NET Core app. Lives at /pr-review as a standalone Vite + React 18 + TypeScript SPA, deployed to GitHub Pages via .github/workflows/pr-review-deploy.yml. Existing /app, /server, gulpfile.babel.js pipeline is untouched. Why browser-only: the original Hyponome runs an ASP.NET Core server purely so Octokit (and a server-side PAT) can fetch PR data. The Library repo is public, so all the GitHub calls work unauthenticated, which means the entire tool can be a static bundle on GitHub Pages with no server, no PAT storage, and no infra to maintain. Feature parity with Hyponome plus a tabbed redesign: - Lists open PRs on OctopusDeploy/Library. - Per file: tabbed Monaco DiffEditor showing real side-by-side diffs of the full file (before/after fetched from raw.githubusercontent.com, which does not count against the GitHub API rate limit) plus one tab per embedded script that actually changed in the PR. - Script extraction covers Octopus.Action.Script.ScriptBody (language from Octopus.Action.Script.Syntax), Octopus.Action.Terraform.Template, Octopus.Action.Terraform.VariableValues, and any Octopus.Action.CustomScripts.{phase}.{ext} entries (language inferred from the extension). Unchanged scripts do not get a tab. Other notes: - Hash routing (no GH Pages 404 trick required). - Hyponome branding restored: hyponome.png in the header, favicon.png, page title "Hyponome - Octopus Library PR Review". - Hardcoded to OctopusDeploy/Library; a fork edits one constant. - Full-width layout so the diff viewer uses the whole viewport. Deployment: one-time, set Settings > Pages > Source to "GitHub Actions" in the repo. Site URL: https://octopusdeploy.github.io/Library/pr-review/ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Document Hyponome PR review tool in root README Adds /pr-review to the Organization list and a "Hyponome (recommended)" subsection at the top of "Reviewing PRs" that links to the deployed GH Pages URL and explains what the tool surfaces per file. The existing _diff.ps1 instructions are kept as a "Reviewing script changes locally" fallback for offline work or rate-limit scenarios. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Update Hyponome PR comment to link to the web tool The Hyponome workflow has been posting docker-container instructions on every step-template PR. With the browser-only successor deployed to GitHub Pages, the comment is now a single clickable link to the PR view in the new tool — no local setup required. Addresses review feedback on #1684 from @hnrkndrssn. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7df2479 commit 8b7ea4e

26 files changed

Lines changed: 3626 additions & 9 deletions

.github/workflows/Hyponome.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Link to hyponome
2-
on:
2+
on:
33
pull_request_target:
44
types: [opened]
55
paths:
@@ -15,10 +15,5 @@ jobs:
1515
issue_number: context.issue.number,
1616
owner: context.repo.owner,
1717
repo: context.repo.repo,
18-
body: `Start Hyponome locally
19-
20-
docker pull ghcr.io/hnrkndrssn/hyponome:main
21-
docker run --rm -p 8000:8080 -it ghcr.io/hnrkndrssn/hyponome:main
22-
23-
[Review in Hyponome](http://localhost:8000/pulls/${context.issue.number})`
18+
body: `Review this PR in [Hyponome](https://octopusdeploy.github.io/Library/pr-review/#/pulls/${context.issue.number}) for a side-by-side diff of the step-template JSON and any embedded scripts.`
2419
})
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: Deploy PR review microsite
2+
3+
# Builds /pr-review and publishes it to GitHub Pages.
4+
# After this workflow runs once, set Pages source to "GitHub Actions" in the
5+
# repo settings: Settings > Pages > Build and deployment > Source.
6+
#
7+
# Resulting URL: https://octopusdeploy.github.io/Library/pr-review/
8+
9+
on:
10+
push:
11+
branches: [master, main]
12+
paths:
13+
- "pr-review/**"
14+
- ".github/workflows/pr-review-deploy.yml"
15+
workflow_dispatch:
16+
17+
permissions:
18+
contents: read
19+
pages: write
20+
id-token: write
21+
22+
concurrency:
23+
group: pages-pr-review
24+
cancel-in-progress: true
25+
26+
jobs:
27+
build:
28+
runs-on: ubuntu-latest
29+
defaults:
30+
run:
31+
working-directory: pr-review
32+
steps:
33+
- uses: actions/checkout@v4
34+
35+
- uses: actions/setup-node@v4
36+
with:
37+
node-version: "20"
38+
cache: "npm"
39+
cache-dependency-path: pr-review/package-lock.json
40+
41+
- name: Install
42+
run: npm ci
43+
44+
- name: Typecheck
45+
run: npm run typecheck
46+
47+
- name: Build
48+
run: npm run build
49+
50+
# Publish the built site under /pr-review/ inside the Pages artifact so
51+
# it lands at https://octopusdeploy.github.io/Library/pr-review/
52+
- name: Stage artifact
53+
run: |
54+
mkdir -p ../_site/pr-review
55+
cp -r dist/* ../_site/pr-review/
56+
57+
- uses: actions/upload-pages-artifact@v3
58+
with:
59+
path: _site
60+
61+
deploy:
62+
needs: build
63+
runs-on: ubuntu-latest
64+
environment:
65+
name: github-pages
66+
url: ${{ steps.deployment.outputs.page_url }}
67+
steps:
68+
- id: deployment
69+
uses: actions/deploy-pages@v4

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Organization
99
* *Step templates* are checked into `/step-templates` as raw JSON exports direct from Octopus Deploy
1010
* The *library website* is largely under `/app`, with build artifacts at the root of the repository
1111
* The `/tools` folder contains utilities to help with editing step templates
12+
* The `/pr-review` folder contains a browser-only PR review tool ([Hyponome](https://octopusdeploy.github.io/Library/pr-review/)) deployed to GitHub Pages
1213

1314
Contributing step templates or to the website
1415
---------------------------------------------
@@ -18,9 +19,19 @@ Read our [contributing guidelines](https://github.com/OctopusDeploy/Library/blob
1819
Reviewing PRs
1920
-------------
2021

21-
### Reviewing script changes
22+
### Hyponome (recommended)
2223

23-
Step template JSON files embed scripts as single-line escaped strings, making diffs hard to read. Use the `_diff.ps1` tool to extract old and new scripts into separate files you can compare in your diff tool:
24+
The easiest way to review a PR is in the browser using **Hyponome**, our PR review microsite:
25+
26+
**[https://octopusdeploy.github.io/Library/pr-review/](https://octopusdeploy.github.io/Library/pr-review/)**
27+
28+
Hyponome lists open pull requests on this repository and, for each changed file, shows a true side-by-side diff in a Monaco editor. For step-template JSONs it surfaces a separate tab per embedded script that actually changed in the PR — `Octopus.Action.Script.ScriptBody`, `Octopus.Action.Terraform.Template`, custom `PreDeploy`/`Deploy`/`PostDeploy` scripts, and so on — each with syntax highlighting matching the script's language. This makes script changes readable without having to mentally unescape the JSON.
29+
30+
It runs entirely in your browser against the public GitHub API (no sign-in, no setup). Source lives in [`/pr-review`](./pr-review/README.md); changes there auto-deploy via GitHub Pages.
31+
32+
### Reviewing script changes locally
33+
34+
If you'd rather review offline, or you're hitting the unauthenticated GitHub rate limit, the `_diff.ps1` tool extracts old and new scripts into separate files you can compare in your local diff tool:
2435

2536
```powershell
2637
# Compare ScriptBody against previous commit

pr-review/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
dist
3+
*.tsbuildinfo
4+
.DS_Store
5+
.vite

pr-review/README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# PR Review
2+
3+
A browser-only PR review tool for [OctopusDeploy/Library](https://github.com/OctopusDeploy/Library).
4+
Successor to [Hyponome](https://github.com/hnrkndrssn/hyponome): same feature set, no server,
5+
deployed as a static site to GitHub Pages.
6+
7+
Live at <https://octopusdeploy.github.io/Library/pr-review/>.
8+
9+
## What it does
10+
11+
- Lists open pull requests on `OctopusDeploy/Library`.
12+
- For each changed file, shows the **before/after side-by-side** in Monaco's
13+
`DiffEditor`. The before/after contents are fetched directly from
14+
`raw.githubusercontent.com` (a static CDN that does not count against the
15+
GitHub API rate limit), not reconstructed from the unified-diff patch.
16+
- For step-template JSONs, surfaces one **tab per embedded script** that
17+
changed in the PR, each with its own side-by-side syntax-highlighted diff.
18+
Supported properties:
19+
- `Octopus.Action.Script.ScriptBody` (syntax from `Octopus.Action.Script.Syntax`)
20+
- `Octopus.Action.Terraform.Template`
21+
- `Octopus.Action.Terraform.VariableValues`
22+
- `Octopus.Action.CustomScripts.{PreDeploy,Deploy,PostDeploy}.{ps1,sh,csx,fsx,…}`
23+
language inferred from the extension.
24+
25+
Scripts that exist in both before and after but didn't actually change in
26+
this PR don't get a tab (no point looking at an unchanged diff).
27+
28+
## How it differs from Hyponome
29+
30+
| | Hyponome | PR Review |
31+
|---|---|---|
32+
| Runtime | ASP.NET Core (server) | Static SPA (browser only) |
33+
| GitHub access | Octokit, server-side PAT | `fetch` to `api.github.com`, unauthenticated |
34+
| Hosting | Docker container | GitHub Pages |
35+
| Diff viewer | Ace + ace-diff | Monaco `DiffEditor` |
36+
| UI | Bootstrap 3 + jQuery | React 18 + plain CSS |
37+
38+
## Authentication
39+
40+
None. The site uses the GitHub REST API unauthenticated, which is rate-limited to
41+
**60 requests per hour per IP address**. Each PR detail view consumes roughly 3
42+
requests (PR + files + occasionally the raw diff for files with omitted patches),
43+
so casual browsing of ~15 PRs per hour fits comfortably.
44+
45+
When the limit is hit, the site renders an explanatory error state with the
46+
reset time. There is no PAT prompt and no token storage — keeping the deployment
47+
truly static and avoiding any browser-stored secrets.
48+
49+
## Local development
50+
51+
```sh
52+
cd pr-review
53+
npm install
54+
npm run dev
55+
```
56+
57+
Opens at `http://localhost:5173/Library/pr-review/`. Hot reload works as
58+
expected via Vite.
59+
60+
Useful scripts:
61+
62+
| Script | Purpose |
63+
|---|---|
64+
| `npm run dev` | Vite dev server with HMR |
65+
| `npm run build` | Type-check, then build a production bundle into `dist/` |
66+
| `npm run typecheck` | TS only, no emit |
67+
| `npm run preview` | Serve the production build locally |
68+
69+
## Deployment
70+
71+
Pushes to `master`/`main` that touch `pr-review/**` or the workflow file run
72+
`.github/workflows/pr-review-deploy.yml`, which builds the site and publishes
73+
it to GitHub Pages.
74+
75+
**One-time setup** (only needed the first time):
76+
77+
1. In repo *Settings → Pages*, set **Source** to **GitHub Actions**.
78+
2. Run the workflow once (push or *Run workflow* in the Actions tab).
79+
80+
The site lands at `https://octopusdeploy.github.io/Library/pr-review/`. If
81+
you change the deployment path, also update `base` in `vite.config.ts` and
82+
the `_site/pr-review` path in the workflow.
83+
84+
## Code layout
85+
86+
```
87+
src/
88+
├── main.tsx Entry — mounts <App/>.
89+
├── App.tsx HashRouter + header + footer.
90+
├── styles.css All app styling (CSS custom properties, dark mode).
91+
├── routes/
92+
│ ├── PullRequestList.tsx Open PRs list.
93+
│ └── PullRequestDetail.tsx PR header + file panels.
94+
├── api/
95+
│ ├── github.ts fetch-based client. Lists PRs/files via api.github.com,
96+
│ │ reads file contents from raw.githubusercontent.com.
97+
│ └── types.ts Hand-trimmed shapes for the endpoints we use.
98+
├── lib/
99+
│ ├── extractScript.ts Pull every changed Octopus script out of a step-template
100+
│ │ JSON (ScriptBody, Terraform, custom scripts).
101+
│ └── languageDetect.ts Filename → Monaco language id; binary detection.
102+
└── components/
103+
├── PullRequestHeader.tsx Title / branches / author.
104+
├── FilePanel.tsx Tabbed per-file panel (File diff + one tab per script).
105+
├── ErrorState.tsx Generic + rate-limit-aware error rendering.
106+
└── TimeAgo.tsx Relative timestamps.
107+
```
108+
109+
The repo target (`OctopusDeploy/Library`) is hardcoded in `src/api/github.ts`.
110+
A fork that wants to point this at a different repo edits one constant.
111+
112+
## Why hash routing?
113+
114+
GitHub Pages is static hosting — any deep link like `/pulls/123` would 404 on
115+
refresh. `HashRouter` keeps the route entirely in the URL fragment
116+
(`#/pulls/123`), which the server never sees. Two-route SPA, internal tool,
117+
zero extra deployment complexity.
118+
119+
## Known harmless console warning
120+
121+
Navigating from one PR to another sometimes logs:
122+
123+
> `Uncaught Error: TextModel got disposed before DiffEditorWidget model got reset`
124+
125+
This is a known race inside `@monaco-editor/react` where Monaco's lazy CDN
126+
load completes after React has already unmounted the previous `DiffEditor`.
127+
It's thrown asynchronously during teardown, doesn't affect any rendered UI,
128+
and can be ignored. Each `DiffEditor` already gets a stable `key` per
129+
`file.sha`/`file.filename` to force a clean remount, which suppresses the
130+
worst of it; the remaining warning is upstream.
131+

pr-review/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<meta name="color-scheme" content="light dark" />
7+
<link rel="icon" type="image/png" href="./favicon.png" />
8+
<title>Hyponome &middot; Octopus Library PR Review</title>
9+
</head>
10+
<body>
11+
<div id="root"></div>
12+
<script type="module" src="/src/main.tsx"></script>
13+
</body>
14+
</html>

0 commit comments

Comments
 (0)