|
| 1 | +# 10 - Publishing a Library to mcpp-index |
| 2 | + |
| 3 | +**English** | [简体中文](zh/10-publishing-a-library.md) |
| 4 | + |
| 5 | +How a library becomes something `[dependencies]` can name. This is the |
| 6 | +*library author's* chain; [09 - Releasing mcpp](09-release.md) is about |
| 7 | +releasing mcpp itself, and [02 - Packaging & Release](02-pack-and-release.md) |
| 8 | +is about `mcpp pack` bundling an application. |
| 9 | + |
| 10 | +## The chain, in the only order that works |
| 11 | + |
| 12 | +``` |
| 13 | +your repo merge → git tag → GitHub auto-generates the tag tarball |
| 14 | + ↓ |
| 15 | +gitcode mirror a byte-identical copy, for the CN region |
| 16 | + ↓ |
| 17 | +mcpplibs/mcpp-index pkgs/<x>/<name>.lua — GLOBAL + CN URLs + sha256 |
| 18 | + ↓ publish-artifact.yml pushes a content-hash artifact |
| 19 | + ↓ |
| 20 | +consumers bump the version in their mcpp.toml |
| 21 | +``` |
| 22 | + |
| 23 | +Each arrow is a gate. Skipping one does not fail loudly — it fails as |
| 24 | +"dependency not found" or a 404 in someone else's build, hours later. |
| 25 | + |
| 26 | +## 1. Tag the release |
| 27 | + |
| 28 | +The version in `mcpp.toml` and the tag must agree. GitHub generates |
| 29 | +`archive/refs/tags/<tag>.tar.gz` automatically; that tarball **is** the |
| 30 | +artifact — nothing needs uploading. |
| 31 | + |
| 32 | +```bash |
| 33 | +git tag 0.0.48 && git push origin 0.0.48 |
| 34 | +curl -fsSL -o pkg-0.0.48.tar.gz \ |
| 35 | + https://github.com/<owner>/<repo>/archive/refs/tags/0.0.48.tar.gz |
| 36 | +sha256sum pkg-0.0.48.tar.gz # ← the digest the index will carry |
| 37 | +``` |
| 38 | + |
| 39 | +The tarball extracts to `<repo>-<tag>/`, and mcpp looks for `mcpp.toml` inside |
| 40 | +that wrapper directory. A repo that ships its own `mcpp.toml` needs no `mcpp` |
| 41 | +field in the index entry. |
| 42 | + |
| 43 | +## 2. Mirror to gitcode |
| 44 | + |
| 45 | +The CN entry must be a **byte-identical copy** of the GitHub tarball, only |
| 46 | +renamed. Anything else and the two regions disagree about what a pinned |
| 47 | +`sha256` means. |
| 48 | + |
| 49 | +```bash |
| 50 | +gtc release publish mcpp-res/<name> --tag 0.0.48 --asset pkg-0.0.48.tar.gz |
| 51 | +``` |
| 52 | + |
| 53 | +Then verify it, because the upload reporting success is not the same as the |
| 54 | +asset being fetchable: |
| 55 | + |
| 56 | +```bash |
| 57 | +# GET, never HEAD — gitcode answers HEAD with 401 and GET with 302 → CDN 200 |
| 58 | +curl -fsSL -o cn.tar.gz \ |
| 59 | + https://gitcode.com/mcpp-res/<name>/releases/download/0.0.48/pkg-0.0.48.tar.gz |
| 60 | +cmp cn.tar.gz pkg-0.0.48.tar.gz # must be identical, not merely present |
| 61 | +``` |
| 62 | + |
| 63 | +## 3. Add the index entry |
| 64 | + |
| 65 | +In `mcpplibs/mcpp-index`, `pkgs/<first-letter>/<name>.lua`: |
| 66 | + |
| 67 | +```lua |
| 68 | +["0.0.48"] = { |
| 69 | + url = { |
| 70 | + GLOBAL = "https://github.com/<owner>/<repo>/archive/refs/tags/0.0.48.tar.gz", |
| 71 | + CN = "https://gitcode.com/mcpp-res/<name>/releases/download/0.0.48/pkg-0.0.48.tar.gz", |
| 72 | + }, |
| 73 | + sha256 = "<the digest from step 1>", |
| 74 | +}, |
| 75 | +``` |
| 76 | + |
| 77 | +**In all three platform blocks** — `linux`, `macosx`, `windows`. A source |
| 78 | +tarball is the same bytes on every platform, and an entry present in only one |
| 79 | +of them fails on the others as "no such version", which reads like a typo in |
| 80 | +the consumer's manifest. |
| 81 | + |
| 82 | +## 4. Wait for the artifact |
| 83 | + |
| 84 | +**The index is an artifact, not a git clone.** Merging to `main` is not |
| 85 | +enough: `publish-artifact.yml` has to run and push a content-hash artifact, |
| 86 | +and clients hold a refresh TTL on top of that. Editing a cached `pkgs/**` by |
| 87 | +hand does nothing. |
| 88 | + |
| 89 | +```bash |
| 90 | +gh run list --repo mcpplibs/mcpp-index --workflow publish-artifact.yml --limit 1 |
| 91 | +rm -rf ~/.mcpp/registry/data/<namespace> # force a client refresh |
| 92 | +``` |
| 93 | + |
| 94 | +## 5. Verify from a cold resolve, then bump consumers |
| 95 | + |
| 96 | +The point of this step is that a local checkout of the library will mask every |
| 97 | +mistake above. Resolve it the way a stranger would: |
| 98 | + |
| 99 | +```bash |
| 100 | +rm -rf ~/.mcpp/registry/data/xpkgs/<ns>-x-<name>/0.0.48 |
| 101 | +mcpp build # must download and compile 0.0.48 |
| 102 | +``` |
| 103 | + |
| 104 | +Only then bump `[dependencies]` in the consumers. |
| 105 | + |
| 106 | +> Do **not** try to force a refresh with |
| 107 | +> `find ~/.mcpp/registry -mindepth 1 -maxdepth 1 ! -name data -exec rm -rf {} +` |
| 108 | +> alone. `data/xpkgs` sits at depth 2 and is not named `data`, so a careless |
| 109 | +> second pass deletes the whole payload store (~800 MB of toolchains). |
| 110 | +> Recovery is `mcpp self doctor`, which re-provisions, then `mcpp update`. |
| 111 | +
|
| 112 | +## Testing against an unreleased version |
| 113 | + |
| 114 | +While the chain above is still in flight, seed the registry by hand so |
| 115 | +consumers can compile against the library before it is published: |
| 116 | + |
| 117 | +```bash |
| 118 | +REG=~/.mcpp/registry/data/xpkgs/<ns>-x-<name>/0.0.48 |
| 119 | +mkdir -p "$REG" |
| 120 | +git -C /path/to/library archive --format=tar --prefix=<repo>-0.0.48/ HEAD \ |
| 121 | + | tar -x -C "$REG" |
| 122 | +touch "$REG/.mcpp_ok" # the marker that says "resolved" |
| 123 | +cp ../0.0.47/.xpkg.lua "$REG/.xpkg.lua" # add a 0.0.48 entry to it |
| 124 | +``` |
| 125 | + |
| 126 | +mcpp's build sandbox is network-isolated, so `file://` and |
| 127 | +`http://127.0.0.1` index URLs cannot be fetched — seeding the cache is the way. |
| 128 | + |
| 129 | +**Remove the seeded copy before believing the real thing works.** A seeded |
| 130 | +0.0.48 and a published 0.0.48 are indistinguishable to the build, and the |
| 131 | +seeded one is the copy that will still be there when the publish silently |
| 132 | +failed. |
| 133 | + |
| 134 | +## Checklist |
| 135 | + |
| 136 | +- [ ] `mcpp.toml` version == git tag |
| 137 | +- [ ] tag pushed; tarball downloads and its sha256 recorded |
| 138 | +- [ ] gitcode asset verified with **GET**, byte-identical to GitHub's |
| 139 | +- [ ] index entry in **all three** platform blocks |
| 140 | +- [ ] `publish-artifact.yml` succeeded |
| 141 | +- [ ] cold resolve (seeded copy deleted) downloads and compiles it |
| 142 | +- [ ] consumers bumped |
0 commit comments