Module 8: walk through GitHub PAT setup, link SSH as optional (#106) (#107)
Sync course wiki / sync-wiki (push) Successful in 4s
CI / check (push) Successful in 7s

Co-authored-by: Justin Paul <justin@jpaul.me>
Co-committed-by: Justin Paul <justin@jpaul.me>
This commit was merged in pull request #107.
This commit is contained in:
2026-06-23 20:32:04 -04:00
committed by Claude (agent)
parent 95e5911957
commit 58f54ce745
+87
View File
@@ -323,6 +323,88 @@ WSL, or Git Bash on Windows. Continues the `tasks-app` repo from Module 2.
*direct the agent* to do the git work (add the remote, push, clone, fetch, pull) and you verify *direct the agent* to do the git work (add the remote, push, clone, fetch, pull) and you verify
each result yourself. You don't type the git commands by hand. each result yourself. You don't type the git commands by hand.
### Set up GitHub authentication (do this first)
This is the one part you do by hand in the web UI, and it's failure mode #1 above: the single most
common first-push wall. Set it up *before* Part A so the push just works. You have two paths; do
**one**. This lab walks the **PAT / HTTPS** path step by step on GitHub as the worked example,
because it's all in the browser and needs no command-line setup. SSH is the optional alternative,
linked below.
> **Other host?** These are GitHub's exact menu paths as the worked example. On GitLab, Bitbucket,
> Codeberg, or your own Forgejo/Gitea the *shape* is identical (see the "Getting a credential" callout
> in the lesson) but the menu names drift; find your host's "access tokens" or "SSH keys" settings.
**Path 1: Personal access token (PAT) over HTTPS.** Generate a token in GitHub's web UI, then paste
it once when Git asks for a password.
1. On GitHub, go to your avatar (top right) → **Settings** → **Developer settings** (bottom of the
left sidebar) → **Personal access tokens**. GitHub offers two token types:
- **Fine-grained tokens** (recommended): scoped to a single repository, with explicit permissions.
This lab uses fine-grained.
- **Tokens (classic)**: older, broader; access is controlled by a coarse `repo` scope that grants
all your repos at once.
Pick **Fine-grained tokens** → **Generate new token**.
2. Fill in the token:
- **Token name:** anything memorable, e.g. `tasks-app-push`.
- **Expiration:** pick a real expiry (30 to 90 days is fine for the lab). Tokens expire by design;
that's a rotation cost you accept for the convenience.
- **Repository access:** choose **Only select repositories** and select your `tasks-app` repo. If
you haven't created the empty remote yet (Part A step 1), come back and select it after, or
create the repo first and then make the token. The token only needs to *reach* a repo that
exists.
- **Permissions → Repository permissions → Contents:** set it to **Read and write**. This is the
write scope, and it is *the* gotcha: a token without it authenticates fine and then `403`s on
push (failure mode #1's scope trap). GitHub auto-adds **Metadata: Read** when you do this; leave
it.
3. Click **Generate token** and **copy the value immediately.** GitHub shows it exactly once. If you
lose it, you generate a new one rather than recover the old.
4. At the first push (Part A step 2), Git prompts for a **username** and **password**:
- **Username:** your GitHub username.
- **Password:** paste the **token** (not your GitHub account password; password auth over HTTPS
was removed years ago). Most terminals show *nothing* while you paste a secret; that's normal,
not a hang. Press Enter.
A **credential helper** caches it after the first success (`git config --global credential.helper`,
set to `osxkeychain` on macOS, `manager` on Windows, or `store`/`cache` on Linux), so you paste the
token *once*, not on every push.
> **Verify-before-publish:** GitHub's menu wording, token-type names, and the **Contents: Read and
> write** permission label drift. Re-confirm the path **Settings → Developer settings → Personal
> access tokens → Fine-grained tokens** and the Contents scope before relying on these exact names.
**Path 2: SSH key (optional alternative).** A key you add to your account skips passwords entirely.
It's more upfront setup (generate a keypair, load the ssh-agent, paste the *public* key into GitHub),
but then there's no token to scope, expire, or cache. Follow GitHub's official docs, in order:
- [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)
- [Adding a new SSH key to your GitHub account](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account)
- [Testing your SSH connection](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection)
If you go SSH, use the **SSH** URL (`git@github.com:…`) when you create the remote in Part A, not the
HTTPS one.
**Which should you pick?**
| | **PAT / HTTPS** | **SSH key** |
|---|---|---|
| **Setup** | Fast, all in the web UI; nothing to install | More upfront: keygen, ssh-agent, add the public key |
| **After setup** | Credential helper caches the token; otherwise re-paste | No prompts ever; nothing to cache |
| **Network** | Port 443; sails through corporate proxies/firewalls | Port 22; sometimes blocked on locked-down networks |
| **Maintenance** | Expires; needs rotation; the write-scope `403` trap; shown once | No expiry by default; no scope to misconfigure |
| **Risk to manage** | A leaked token until it expires/is revoked | A private key + passphrase on your disk |
Short version: **PAT** is the faster start and the friendlier path behind a corporate firewall;
**SSH** is the lower-friction *long-term* setup once you're past the initial keygen. Either one
satisfies the lab. If you're unsure, do the PAT.
### Part A: Create the empty remote and push ### Part A: Create the empty remote and push
1. On your host's web UI, create a **new, empty** repository named `tasks-app`. Do **not** add a 1. On your host's web UI, create a **new, empty** repository named `tasks-app`. Do **not** add a
@@ -514,4 +596,9 @@ tables, and update the "as of" date when you do.
- [ ] **Credential/token UI**: the "Getting a credential" callout names menu paths and the - [ ] **Credential/token UI**: the "Getting a credential" callout names menu paths and the
write-scope label (`repo` / "read and write") generically; confirm the current wording and write-scope label (`repo` / "read and write") generically; confirm the current wording and
scope name on the default-example host before publishing. scope name on the default-example host before publishing.
- [ ] **GitHub PAT walkthrough** (lab "Set up GitHub authentication"): confirm the menu path
**Settings → Developer settings → Personal access tokens → Fine-grained tokens**, the two token
types (**fine-grained** vs **classic**/`repo`), and that the write scope is **Repository
permissions → Contents: Read and write** (with **Metadata: Read** auto-added). These are
volatile GitHub UI labels; also re-confirm the three linked SSH docs URLs still resolve.
- [ ] Update the comparison's **"as of" date** to the build date. - [ ] Update the comparison's **"as of" date** to the build date.