website

#astro#js#html#css

git clone https://git.pyrossh.dev/website

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


a3ff3a4pyrossh 2026-08-09T15:39:12+05:30
add hurl tests and update tools
README.md CHANGED
@@ -36,8 +36,10 @@ than the working directory so uncommitted local changes don't leak into the gene
36
36
 
37
37
  ## Commands
38
38
 
39
- | Command | Action |
39
+ | Command | Action |
40
- | :-------------- | :----------------------------------------- |
40
+ | :------------------- | :---------------------------------------------------------------- |
41
- | `npm install` | Install dependencies |
41
+ | `npm install` | Install dependencies |
42
- | `npm run dev` | Start the Eleventy dev server with reload |
42
+ | `npm run dev` | Start the Eleventy dev server with reload |
43
- | `npm run build` | Build the static site to `./dist/` |
43
+ | `npm run build` | Build the static site to `./dist/` |
44
+ | `npm test` | Build, then run the Playwright page tests |
45
+ | `npm run test:hurl` | Run [hurl](https://hurl.dev) checks against the live git dumb-http endpoint (`git.pyrossh.dev`); requires the `hurl` CLI |
assets/logos/bruno.png DELETED
Binary file
assets/logos/hurl.png ADDED
Binary file
assets/logos/iterm.png DELETED
Binary file
assets/logos/pika.png DELETED
Binary file
assets/logos/rust.png DELETED
Binary file
assets/logos/void.png DELETED
Binary file
package.json CHANGED
@@ -7,6 +7,7 @@
7
7
  "pretest": "npm run build",
8
8
  "test": "node --test tests/**/*.test.js",
9
9
  "test:install-browsers": "playwright install --with-deps chromium",
10
+ "test:hurl": "hurl --test --variable base_url=https://git.pyrossh.dev tests/hurl/*.hurl",
10
11
  "archive:submit": "node scripts/submit-to-archives.js",
11
12
  "tf:plan": "terraform -chdir=infra plan",
12
13
  "tf:apply": "terraform -chdir=infra apply"
src/_data/site.js CHANGED
@@ -76,13 +76,12 @@ const REPOS = [
76
76
 
77
77
  const TOOLS = [
78
78
  { name: "Stats", link: "https://github.com/exelban/stats", image: "/assets/logos/stats.png" },
79
- { name: "Void", link: "https://github.com/voideditor/void", image: "/assets/logos/void.png" },
80
- { name: "Helix", link: "https://github.com/helix-editor/helix", image: "/assets/logos/helix.png" },
81
- { name: "Nushell", link: "https://github.com/nushell/nushell", image: "/assets/logos/nu.png" },
82
79
  { name: "Ghostty", link: "https://github.com/ghostty-org/ghostty", image: "/assets/logos/ghostty.png" },
80
+ { name: "Nushell", link: "https://github.com/nushell/nushell", image: "/assets/logos/nu.png" },
83
81
  { name: "Zellij", link: "https://zellij.dev/", image: "/assets/logos/zellij.png" },
82
+ { name: "Helix", link: "https://github.com/helix-editor/helix", image: "/assets/logos/helix.png" },
84
83
  { name: "Helium", link: "https://github.com/imputnet/helium", image: "/assets/logos/helium.png" },
85
- { name: "Bruno", link: "https://github.com/usebruno/bruno", image: "/assets/logos/bruno.png" },
84
+ { name: "Hurl", link: "https://github.com/Orange-OpenSource/hurl", image: "/assets/logos/hurl.png" },
86
85
  ];
87
86
 
88
87
  // Eleventy only unwraps a JS data file's `default` export when it's the module's
tests/hurl/git-dumb-protocol.hurl ADDED
@@ -0,0 +1,82 @@
1
+ # Sanity checks for the git dumb-HTTP protocol served straight out of the
2
+ # "git" R2 bucket (git.pyrossh.dev) — there's no server-side git process behind
3
+ # it, just static file serving, so these checks make sure the bucket layout
4
+ # still looks like a valid dumb-protocol repo: HEAD/info/refs/objects in the
5
+ # shapes `git clone`'s dumb-http client expects, range requests (used to
6
+ # resume fetches), and 404s for repos/objects that don't exist.
7
+ #
8
+ # Run with: npm run test:hurl
9
+ # Override the target with: hurl --test --variable base_url=http://localhost:PORT tests/hurl/*.hurl
10
+
11
+ GET {{base_url}}/website/HEAD
12
+ HTTP 200
13
+ [Asserts]
14
+ header "Content-Type" == "application/octet-stream"
15
+ header "Accept-Ranges" == "bytes"
16
+ body matches "^ref: refs/heads/[^\n]+\n$"
17
+ [Captures]
18
+ head_ref: regex "ref: (refs/heads/\\S+)"
19
+
20
+
21
+ # info/refs lists every ref as "<40-hex-sha>\t<ref name>", one per line — the
22
+ # format `git clone`'s dumb-http client parses to discover what it can fetch.
23
+ GET {{base_url}}/website/info/refs
24
+ HTTP 200
25
+ [Asserts]
26
+ header "Content-Type" == "application/octet-stream"
27
+ body matches "(?m)^[0-9a-f]{40}\\t{{head_ref}}$"
28
+
29
+
30
+ # A smart-http server would respond to `?service=git-upload-pack` with a
31
+ # pkt-line "# service=git-upload-pack" advertisement and a different content
32
+ # type. R2 has no server logic to do that, so the query string is just
33
+ # ignored and the plain dumb-protocol refs list comes back unchanged — this
34
+ # is what makes it a dumb (not smart) git server.
35
+ GET {{base_url}}/website/info/refs?service=git-upload-pack
36
+ HTTP 200
37
+ [Asserts]
38
+ header "Content-Type" == "application/octet-stream"
39
+ body matches "(?m)^[0-9a-f]{40}\\trefs/heads/"
40
+
41
+
42
+ # objects/info/packs lists available packfiles as "P <pack name>" — dumb
43
+ # clients read this to know which packs to download instead of walking
44
+ # loose objects one by one.
45
+ GET {{base_url}}/website/objects/info/packs
46
+ HTTP 200
47
+ [Asserts]
48
+ body matches "^P pack-[0-9a-f]{40}\\.pack\\n"
49
+ [Captures]
50
+ pack_sha: regex "P pack-([0-9a-f]{40})\\.pack"
51
+
52
+
53
+ GET {{base_url}}/website/objects/pack/pack-{{pack_sha}}.idx
54
+ HTTP 200
55
+ [Asserts]
56
+ header "Content-Type" == "application/octet-stream"
57
+ bytes count > 0
58
+
59
+
60
+ GET {{base_url}}/website/objects/pack/pack-{{pack_sha}}.pack
61
+ HTTP 200
62
+ [Asserts]
63
+ header "Accept-Ranges" == "bytes"
64
+ bytes count > 0
65
+
66
+
67
+ # Dumb-http clients fetch packfiles with Range requests so an interrupted
68
+ # clone can resume instead of restarting — this only works if R2 honors them.
69
+ GET {{base_url}}/website/objects/pack/pack-{{pack_sha}}.pack
70
+ Range: bytes=0-99
71
+ HTTP 206
72
+ [Asserts]
73
+ header "Content-Range" matches "^bytes 0-99/\\d+$"
74
+ bytes count == 100
75
+
76
+
77
+ GET {{base_url}}/this-repo-does-not-exist-xyz/HEAD
78
+ HTTP 404
79
+
80
+
81
+ GET {{base_url}}/website/objects/00/0000000000000000000000000000000000
82
+ HTTP 404