Skip to content

shellcell/packages

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

packages

Static apt (.deb), dnf (.rpm) and apk (Alpine) repositories for the shellcell CLIs, served from GitHub Pages at https://packages.shellcell.dev. End-user install instructions live on that page (generated from templates/index.html; the base URL is set once as BASE_URL in the publish workflow).

How it works

This repository is stateless: no packages or indexes are committed. The source of truth is each project's latest GitHub release.

project release workflow ──repository_dispatch──▶ publish.yml
                                                     │
     for each project in projects.txt:               │
       download *.deb *.rpm *.apk from latest release│
     build + sign apt/rpm/apk indexes  ◀─────────────┘
     deploy site/ to GitHub Pages
  • scripts/build-site.sh — orchestrator; downloads assets, calls the three builders, exports public keys, renders index.html.
  • scripts/build-apt.sh — reprepro-built dists/ + pool/, Release signed with the GPG key (SignWith: yes = default imported key).
  • scripts/build-rpm.sh — per-arch dirs + createrepo_c, detached signature on repomd.xml (repo_gpgcheck=1).
  • scripts/build-apk.sh — per-arch dirs, APKINDEX.tar.gz generated and signed with the abuild RSA key inside an alpine container.

Every run rebuilds the whole site, so a burst of releases, a failed run, or a key rotation is fixed by re-running the workflow. Only the latest release of each project is served. Projects whose releases carry no package assets are skipped, so listing a project in projects.txt before its packaging exists is harmless.

Secrets

Secret Used by Contents
GPG_PRIVATE_KEY this repo armored GPG private key; signs apt Release and rpm repomd.xml
APK_PRIVATE_KEY this repo abuild RSA private key; signs APKINDEX.tar.gz
TAP_GITHUB_TOKEN project repos a PAT with access to this repo; authorizes the repository_dispatch that triggers publishing

Keep the canonical copy of every private key and token in a password manager — GitHub Actions secrets are write-only and cannot be recovered from GitHub. Public keys are not secret: the abuild public key is committed under keys/, and the GPG public key is exported from the private key on each run.

One-time setup

  1. Enable Pages: repo Settings → Pages → Source: GitHub Actions.

  2. Custom domain: add a DNS CNAME record packages.shellcell.dev → shellcell.github.io, set packages.shellcell.dev as the custom domain in Settings → Pages, and enable Enforce HTTPS once the certificate is issued.

  3. GPG key (signs apt + rpm metadata). Sign-only, no passphrase (CI signs unattended), no expiry (an expired repo key breaks installed users):

    export GNUPGHOME="$(mktemp -d)"
    gpg --batch --quick-gen-key "shellcell packages <packages@shellcell.dev>" ed25519 sign never
    gpg --export-secret-keys --armor > gpg-private.asc   # → password manager
    gpg --export --armor > gpg-public.asc                # → password manager
    gh secret set GPG_PRIVATE_KEY --org shellcell --visibility selected --repos packages < gpg-private.asc
    shred -u gpg-private.asc && rm -rf "$GNUPGHOME"
  4. abuild RSA key (signs the Alpine index; Alpine does not use GPG). The file name is load-bearing — see keys/README.md:

    openssl genrsa -out packages@shellcell.rsa 4096
    openssl rsa -in packages@shellcell.rsa -pubout -out packages@shellcell.rsa.pub
    # private key → password manager, then:
    gh secret set APK_PRIVATE_KEY --org shellcell --visibility selected --repos packages < packages@shellcell.rsa
    cp packages@shellcell.rsa.pub keys/   # commit this
    shred -u packages@shellcell.rsa
  5. Dispatch token: a fine-grained PAT whose repository access includes this repo (Contents: read/write is sufficient), stored as an org secret named TAP_GITHUB_TOKEN available to the project repos.

  6. Wire the projects: each project's release workflow sends a dispatch after its release assets are uploaded:

      publish-packages:
        needs: release
        runs-on: ubuntu-latest
        steps:
          - name: Trigger package repo publish
            env:
              GH_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
            run: |
              gh api repos/shellcell/packages/dispatches \
                -f event_type=publish-packages \
                -f "client_payload[project]=${GITHUB_REPOSITORY#*/}" \
                -f "client_payload[version]=${GITHUB_REF_NAME#v}"

    (Guard with if: startsWith(github.ref, 'refs/tags/') in workflows that also run on branch pushes.)

Operations

Publish manually: Actions → Publish → Run workflow. Safe to run any time; the site is rebuilt from scratch.

Local dry run (needs gh, reprepro, createrepo_c, gpg with the signing key imported, and docker):

export GH_TOKEN=$(gh auth token)
./scripts/build-site.sh
python3 -m http.server -d site   # point apt/dnf/apk at localhost to test

Add a project: add its name to projects.txt; make sure its release workflow uploads .deb/.rpm/.apk assets (nfpm) and sends the dispatch above.

Rotate a key: generate a new key as in setup, overwrite the org secret, re-run Publish. The site serves the new public key immediately; existing users must re-fetch it (one curl line from the install instructions), so announce the rotation in the projects' READMEs or releases.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors