Skip to content

Commit 9b1a32e

Browse files
authored
Merge pull request #5 from keturn/feat/assemble
2 parents f9baf1d + e3d0067 commit 9b1a32e

18 files changed

Lines changed: 618 additions & 26 deletions

File tree

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"cSpell.words": [
3+
"dearmor",
4+
"Tauri"
5+
]
6+
}

README.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Debian Repositories (apt support) for GitHub Releases
2+
3+
It's great when GitHub-hosted projects produce `.deb` packages in their release workflow[^1],
4+
but GitHub has never bothered to make a GitHub project something you can add to your system's `sources.list` to get ongoing updates.
5+
6+
Here we aim to make it easy and affordable to make an apt-compatible repository for your releases.
7+
8+
[^1]: Shoutout to [GoReleaser](https://goreleaser.com/) and [Tauri](https://v2.tauri.app/distribute/debian/) as a few tools I've seen enabling Debian packaging in the wild.
9+
10+
11+
## Requirements
12+
13+
```sh
14+
sudo apt-get install --no-recommends dpkg-dev sq xz-utils
15+
```
16+
17+
And [Node.js v24 (LTS)](https://nodejs.org/en/download) with pnpm.
18+
19+
20+
## Usage
21+
22+
### Importing a Release
23+
24+
Import packages from your latest release:
25+
26+
`gh-release-apt import owner/repo`
27+
28+
If you want your repository to retain multiple versions,
29+
do save the resulting `pool/**/Packages` files (to version control or a persistent filesystem) so this release's packages don't have to be downloaded again next time.
30+
31+
32+
### Building the Repository
33+
34+
With your signing key in the `SIGNING_KEY` environment variable, run:
35+
36+
`gh-release-apt assemble`
37+
38+
Then deploy to your server—_excluding_ the `.deb` files themselves.
39+
40+
41+
42+
## Design
43+
44+
The key feature we rely on is that apt will follow redirects.
45+
This means we *can* keep using standard GitHub Release asset hosting for the packages themselves—
46+
which is great, because we don't want the overhead of storing extra copies of them,
47+
GitHub keeps paying for the bandwidth,
48+
and the project's download analytics keep working.
49+
50+
[GitHub Pages doesn't offer a way to configure redirects](https://github.com/orgs/community/discussions/86095),
51+
but other hosts do offer this in their static web hosting features.[^2]
52+
There is, however, often a limit on the number of redirect rules.
53+
For that reason, we organize the repository's package pool so it's easy to map back to GitHub URLs with a single rule (instead of Debian's alphabetized structure).
54+
55+
[^2]: including [GitLab Pages](https://docs.gitlab.com/user/project/pages/redirects/),
56+
[CloudFlare Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/redirects/),
57+
[AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-page-redirect.html) or
58+
[AWS Amplify](https://docs.aws.amazon.com/amplify/latest/userguide/redirects.html),
59+
[NearlyFreeSpeech](https://faq.nearlyfreespeech.net/full/htaccess#htaccess),
60+
[Firebase](https://firebase.google.com/docs/hosting/full-config#redirects),
61+
[Netlify](https://docs.netlify.com/manage/routing/redirects/overview/),
62+
[Vercel](https://vercel.com/docs/redirects/configuration-redirects),
63+
[Digital Ocean](https://docs.digitalocean.com/products/app-platform/how-to/url-rewrites/#configure-a-redirect),
64+
[Render](https://render.com/docs/redirects-rewrites),
65+
[pico.sh](https://pico.sh/pgs#-redirects),
66+
[Codeberg](https://docs.codeberg.org/codeberg-pages/redirects/),
67+
etc.
68+
69+
70+
## Appendix: Creating a Signing Key
71+
72+
This is not the only way to create a signing key, but if you don't have one already,
73+
this creates a minimal key for signing only.
74+
75+
```sh
76+
sq key generate --without-password --can-sign --cannot-encrypt --cannot-authenticate --shared-key --no-userids
77+
sq cert export --cert $FINGERPRINT | sq packet dearmor --output archive-keyring.pgp
78+
sq key export --cert $FINGERPRINT | gh secret set SIGNING_KEY
79+
```
80+
81+
See [DebianRepository/UseThirdParty](https://wiki.debian.org/DebianRepository/UseThirdParty#OpenPGP_certificate_distribution)
82+
for recommendations on where to name and place the certificate.
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Debian Repository
2+
## deb package files are served by redirects
3+
*.deb
4+
## Packages in dist/ are generated (from those in pool/)
5+
/public/dist/**/Packages
6+
## Release files are auto-generated
7+
Release
8+
Release.gpg
9+
InRelease
10+
11+
12+
# Logs
13+
14+
logs
15+
_.log
16+
npm-debug.log_
17+
yarn-debug.log*
18+
yarn-error.log*
19+
lerna-debug.log*
20+
.pnpm-debug.log*
21+
22+
# Diagnostic reports (https://nodejs.org/api/report.html)
23+
24+
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
25+
26+
# Runtime data
27+
28+
pids
29+
_.pid
30+
_.seed
31+
\*.pid.lock
32+
33+
# Directory for instrumented libs generated by jscoverage/JSCover
34+
35+
lib-cov
36+
37+
# Coverage directory used by tools like istanbul
38+
39+
coverage
40+
\*.lcov
41+
42+
# nyc test coverage
43+
44+
.nyc_output
45+
46+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
47+
48+
.grunt
49+
50+
# Bower dependency directory (https://bower.io/)
51+
52+
bower_components
53+
54+
# node-waf configuration
55+
56+
.lock-wscript
57+
58+
# Compiled binary addons (https://nodejs.org/api/addons.html)
59+
60+
build/Release
61+
62+
# Dependency directories
63+
64+
node_modules/
65+
jspm_packages/
66+
67+
# Snowpack dependency directory (https://snowpack.dev/)
68+
69+
web_modules/
70+
71+
# TypeScript cache
72+
73+
\*.tsbuildinfo
74+
75+
# Optional npm cache directory
76+
77+
.npm
78+
79+
# Optional eslint cache
80+
81+
.eslintcache
82+
83+
# Optional stylelint cache
84+
85+
.stylelintcache
86+
87+
# Microbundle cache
88+
89+
.rpt2_cache/
90+
.rts2_cache_cjs/
91+
.rts2_cache_es/
92+
.rts2_cache_umd/
93+
94+
# Optional REPL history
95+
96+
.node_repl_history
97+
98+
# Output of 'npm pack'
99+
100+
\*.tgz
101+
102+
# Yarn Integrity file
103+
104+
.yarn-integrity
105+
106+
# parcel-bundler cache (https://parceljs.org/)
107+
108+
.cache
109+
.parcel-cache
110+
111+
# Next.js build output
112+
113+
.next
114+
out
115+
116+
# Nuxt.js build / generate output
117+
118+
.nuxt
119+
dist
120+
121+
# Gatsby files
122+
123+
.cache/
124+
125+
# Comment in the public line in if your project uses Gatsby and not Next.js
126+
127+
# https://nextjs.org/blog/next-9-1#public-directory-support
128+
129+
# public
130+
131+
# vuepress build output
132+
133+
.vuepress/dist
134+
135+
# vuepress v2.x temp and cache directory
136+
137+
.temp
138+
.cache
139+
140+
# Docusaurus cache and generated files
141+
142+
.docusaurus
143+
144+
# Serverless directories
145+
146+
.serverless/
147+
148+
# FuseBox cache
149+
150+
.fusebox/
151+
152+
# DynamoDB Local files
153+
154+
.dynamodb/
155+
156+
# TernJS port file
157+
158+
.tern-port
159+
160+
# Stores VSCode versions used for testing VSCode extensions
161+
162+
.vscode-test
163+
164+
# yarn v2
165+
166+
.yarn/cache
167+
.yarn/unplugged
168+
.yarn/build-state.yml
169+
.yarn/install-state.gz
170+
.pnp.\*
171+
172+
# wrangler project
173+
174+
.dev.vars*
175+
!.dev.vars.example
176+
.env*
177+
!.env.example
178+
.wrangler/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "<PACKAGE_NAME>",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "wrangler deploy",
7+
"dev": "wrangler dev",
8+
"start": "wrangler dev"
9+
},
10+
"devDependencies": {
11+
"wrangler": "^3.78.5"
12+
}
13+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# deb package files are served by redirects
2+
*.deb
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/pool/:owner/:repo/:tag/* https://www.github.com/:owner/:repo/releases/download/:tag/:splat
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Debian Package Repository</title>
6+
</head>
7+
<body>
8+
<p>FIXME: We should probably put something here about how to add this to your apt sources.list.</p>
9+
</body>
10+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "<WORKER_NAME>",
3+
"compatibility_date": "<COMPATIBILITY_DATE>",
4+
"assets": {
5+
// The path to the directory containing the `index.html` file to be served at `/`
6+
"directory": "./public"
7+
},
8+
"observability": {
9+
"enabled": true
10+
}
11+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"dependencies": {
2020
"@octokit/rest": "^21.0.2",
2121
"commander": "^12.1.0",
22+
"fdir": "^6.5.0",
2223
"fs-extra": "^11.2.0",
2324
"zx": "8.8.5-lite"
2425
},

pnpm-lock.yaml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)