feat: reorganise bash scripts and add comprehensive documentation (#6)
CI / dependency-pin-check-typescript (push) Successful in 5s
CI / dependency-pin-check-python (push) Successful in 4s
CI / python (push) Successful in 9m28s
CI / typescript (push) Successful in 9m42s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m39s

## Summary

This PR completes the bash script restructuring and adds comprehensive documentation across all script categories.

### Bash Restructuring

- Moved cohort shell scripts (`remove_github_members.sh`, `update_github_teams.sh`) from `python/cohort/` into a new `bash/cohort/` directory
- Moved existing bash utilities (`add-keys-to-git.sh`, `fix-yubikey-perms.sh`, `list-yubikey-ssh-keys.sh`) into a new `bash/yubikey/` subdirectory
- Updated `run.sh` to support **Bash** as a third language option alongside TypeScript and Python
  - Bash scripts are run directly (no 1Password secret injection needed)
  - Category discovery and script listing works the same as for TS/Python
  - Removed dead "Root Scripts" logic that was no longer needed

### Documentation

Added `README.md` files for all script categories that were missing them:

- `bash/cohort/README.md` — cohort GitHub team management scripts
- `bash/yubikey/README.md` — YubiKey SSH key and permission utilities
- `typescript/src/crowdin/README.md` — Crowdin translation management scripts
- `typescript/src/discord/README.md` — Discord bot utility scripts
- `typescript/src/discourse/README.md` — Discourse forum management scripts
- `typescript/src/gitea/README.md` — Gitea bulk repository operation scripts
- `typescript/src/github/README.md` — GitHub API interaction scripts
- `typescript/src/music/README.md` — Music file metadata tools
- `typescript/src/s3/README.md` — S3-compatible object storage scripts
- `typescript/src/security/README.md` — Security analysis and reporting scripts
- `python/cohort/README.md` — Updated to remove moved shell scripts, fix usage commands

Also updated project-level docs:

- **`README.md`** — Corrected project structure, fixed running instructions (removed references to non-existent `make run-ts`/`make run-py` targets), added Bash prerequisites
- **`CLAUDE.md`** — Updated project overview, structure, development standards, and script-adding guides to reflect the current state of the project

 This PR was created with help from Hikari~ 🌸

Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Reviewed-on: #6
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #6.
This commit is contained in:
2026-02-23 20:18:41 -08:00
committed by Naomi Carrigan
parent e481823e06
commit ec58c9c843
65 changed files with 4507 additions and 157 deletions
+75
View File
@@ -0,0 +1,75 @@
# Cohort Bash Scripts
Shell scripts for managing GitHub team membership during the NHCarrigan spring cohort programme. These scripts handle one-off team changes that are too complex or bulk-oriented to do manually through the GitHub web interface.
All scripts use the `gh` CLI for GitHub API calls. Run `gh auth login` before using them.
## Getting Started
Run scripts via the interactive runner from the project root:
```bash
make run
# Select: Bash → cohort → <script>
```
Or run directly:
```bash
bash bash/cohort/<script-name>.sh
```
## Table of Contents
- [remove\_github\_members.sh](#remove_github_memberssh)
- [update\_github\_teams.sh](#update_github_teamssh)
---
## remove_github_members.sh
Removes a hardcoded list of inactive members from their GitHub organisation teams in the `nhcarrigan-spring-2026-cohort` organisation. Covers both standard team membership and `-leaders` sub-team membership where applicable.
### Usage
```bash
bash bash/cohort/remove_github_members.sh
```
### Environment Variables
None. Uses `gh` CLI authentication — run `gh auth login` first.
### Data Files
None. Member usernames and team slugs are hardcoded in the script.
### Notes
- The member list and team assignments are specific to a point-in-time removal event. Update the script with the correct usernames before each use.
- Each removal command uses `|| true` so a single failure (e.g. member already removed) does not abort the entire script.
---
## update_github_teams.sh
Orchestrates a multi-step GitHub team restructure: removes all members from a dissolved team, clears its leaders sub-team, then adds each member to their new team. Also promotes a member to leader in their new team.
### Usage
```bash
bash bash/cohort/update_github_teams.sh
```
### Environment Variables
None. Uses `gh` CLI authentication — run `gh auth login` first.
### Data Files
None. All member usernames, team slugs, and role assignments are hardcoded in the script.
### Notes
- This script is specific to a one-off team restructure (Jade Jasmine dissolution). Update the member list and team assignments before each use.
- The script exits immediately on any error (`set -e`). If a step fails, check whether the member or team already exists in the target state.
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Script to remove inactive members from GitHub organization teams
# Date: 2026-02-12
ORG="nhcarrigan-spring-2026-cohort"
# Team 1 (Jade Jasmine) - Remove leader and participant
echo "Removing from Jade Jasmine..."
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine-leaders/memberships/Mista-Log" || true
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/A-normal-programmer" || true
# Team 2 (Crimson Dahlia) - Remove 2 participants
echo "Removing from Crimson Dahlia..."
gh api --method DELETE "/orgs/$ORG/teams/crimson-dahlia/memberships/1s-crypto" || true
gh api --method DELETE "/orgs/$ORG/teams/crimson-dahlia/memberships/emlanis" || true
# Team 3 (Rose Camellia) - Remove leader
echo "Removing from Rose Camellia..."
gh api --method DELETE "/orgs/$ORG/teams/rose-camellia-leaders/memberships/michaelboateng1" || true
# Team 4 (Amber Wisteria) - Remove leader and participant
echo "Removing from Amber Wisteria..."
gh api --method DELETE "/orgs/$ORG/teams/amber-wisteria-leaders/memberships/neonbit101" || true
gh api --method DELETE "/orgs/$ORG/teams/amber-wisteria/memberships/avanishchandra" || true
# Team 5 (Ivory Orchid) - Remove participant
echo "Removing from Ivory Orchid..."
gh api --method DELETE "/orgs/$ORG/teams/ivory-orchid/memberships/VuBui217" || true
# Team 7 (Peach Gardenia) - Remove participant
echo "Removing from Peach Gardenia..."
gh api --method DELETE "/orgs/$ORG/teams/peach-gardenia/memberships/TabsOO7" || true
# Team 8 (Violet Carnation) - Remove 2 participants
echo "Removing from Violet Carnation..."
gh api --method DELETE "/orgs/$ORG/teams/violet-carnation/memberships/masudulalam" || true
gh api --method DELETE "/orgs/$ORG/teams/violet-carnation/memberships/urmilbhatt" || true
# Team 10 (Coral Sunflower) - Remove leader and participant
echo "Removing from Coral Sunflower..."
gh api --method DELETE "/orgs/$ORG/teams/coral-sunflower-leaders/memberships/AjayTheWizard" || true
gh api --method DELETE "/orgs/$ORG/teams/coral-sunflower/memberships/Hritikhh" || true
# Team 11 (Indigo Tulip) - Remove participant
echo "Removing from Indigo Tulip..."
gh api --method DELETE "/orgs/$ORG/teams/indigo-tulip/memberships/SiAust" || true
# Team 13 (Mint Narcissus) - Remove participant
echo "Removing from Mint Narcissus..."
gh api --method DELETE "/orgs/$ORG/teams/mint-narcissus/memberships/SergioPardoSanchez" || true
echo "Done removing members from GitHub teams!"
+73
View File
@@ -0,0 +1,73 @@
#!/bin/bash
# Update GitHub teams for Jade Jasmine dissolution
set -e # Exit on error
ORG="nhcarrigan-spring-2026-cohort"
echo "=== Phase 2: GitHub Team Changes ==="
echo ""
# Step 1: Remove all members from jade-jasmine team
echo "Step 1: Removing members from jade-jasmine team..."
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/Nikil-D-Gr8" || echo " - Nikil-D-Gr8 already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/amandaw800" || echo " - amandaw800 already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/hayden-html" || echo " - hayden-html already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/hbar1st" || echo " - hbar1st already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/rosacabrerac" || echo " - rosacabrerac already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/ArbitraryPie" || echo " - ArbitraryPie already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/builtbykabir" || echo " - builtbykabir already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine/memberships/Mista-Log" || echo " - Mista-Log already removed or not found"
echo "✅ jade-jasmine team cleared"
echo ""
# Step 2: Remove leaders from jade-jasmine-leaders team
echo "Step 2: Removing leaders from jade-jasmine-leaders team..."
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine-leaders/memberships/hayden-html" || echo " - hayden-html already removed or not found"
gh api --method DELETE "/orgs/$ORG/teams/jade-jasmine-leaders/memberships/Mista-Log" || echo " - Mista-Log already removed or not found"
echo "✅ jade-jasmine-leaders team cleared"
echo ""
# Step 3: Add members to new teams
echo "Step 3: Adding members to new teams..."
echo " - Adding Nikil-D-Gr8 to crimson-dahlia..."
gh api --method PUT "/orgs/$ORG/teams/crimson-dahlia/memberships/Nikil-D-Gr8" -f role=member
echo " - Adding amandaw800 to violet-carnation..."
gh api --method PUT "/orgs/$ORG/teams/violet-carnation/memberships/amandaw800" -f role=member
echo " - Adding hayden-html to teal-iris..."
gh api --method PUT "/orgs/$ORG/teams/teal-iris/memberships/hayden-html" -f role=member
echo " - Adding hbar1st to indigo-tulip..."
gh api --method PUT "/orgs/$ORG/teams/indigo-tulip/memberships/hbar1st" -f role=member
echo " - Adding rosacabrerac to scarlet-hydrangea..."
gh api --method PUT "/orgs/$ORG/teams/scarlet-hydrangea/memberships/rosacabrerac" -f role=member
echo " - Adding ArbitraryPie to peach-gardenia..."
gh api --method PUT "/orgs/$ORG/teams/peach-gardenia/memberships/ArbitraryPie" -f role=member
echo " - Adding builtbykabir to azure-lotus..."
gh api --method PUT "/orgs/$ORG/teams/azure-lotus/memberships/builtbykabir" -f role=member
echo " - Adding Mista-Log to ivory-orchid..."
gh api --method PUT "/orgs/$ORG/teams/ivory-orchid/memberships/Mista-Log" -f role=member
echo "✅ All members added to new teams"
echo ""
# Step 4: Add Mista-Log to ivory-orchid-leaders
echo "Step 4: Adding Mista-Log to ivory-orchid-leaders..."
gh api --method PUT "/orgs/$ORG/teams/ivory-orchid-leaders/memberships/Mista-Log" -f role=member
echo "✅ Mista-Log promoted to leader in Ivory Orchid"
echo ""
echo "=== Phase 2 Complete! ==="
echo ""
echo "Summary:"
echo "- ✅ jade-jasmine team cleared (8 members removed)"
echo "- ✅ jade-jasmine-leaders team cleared (2 leaders removed)"
echo "- ✅ 8 members added to their new teams"
echo "- ✅ Mista-Log promoted to leader in ivory-orchid"
+109
View File
@@ -0,0 +1,109 @@
# YubiKey Scripts
Shell scripts for managing YubiKey hardware security keys on WSL (Windows Subsystem for Linux). Covers SSH key extraction, Git signing key configuration, and fixing USB permission issues that commonly arise in WSL environments.
All scripts require a YubiKey to be attached and forwarded to WSL via `usbipd`. The `ykman` and `yubico-piv-tool` packages must be installed.
## Getting Started
Run scripts via the interactive runner from the project root:
```bash
make run
# Select: Bash → yubikey → <script>
```
Or run directly:
```bash
bash bash/yubikey/<script-name>.sh
```
## Table of Contents
- [add-keys-to-git.sh](#add-keys-to-gitsh)
- [fix-yubikey-perms.sh](#fix-yubikey-permssh)
- [list-yubikey-ssh-keys.sh](#list-yubikey-ssh-keyssh)
---
## add-keys-to-git.sh
Extracts the SSH public keys from three YubiKey PIV slots and writes them as Git commit signing keys to the corresponding per-context Git config files. Run this after replacing or re-provisioning a YubiKey.
| Slot | Context | Config file |
|---|---|---|
| 9a | Personal | `~/.git-naomi` |
| 9c | Deepgram | `~/.git-dg` |
| 9e | FreeCodeCamp | `~/.git-fcc` |
### Usage
```bash
bash bash/yubikey/add-keys-to-git.sh
```
### Environment Variables
None.
### Data Files
None.
### Notes
- After running, you must upload the new public keys to GitHub (and any other services that verify commit signatures) manually.
- Requires `ykman` and `ssh-keygen` to be available in your PATH.
---
## fix-yubikey-perms.sh
Repairs YubiKey connectivity in WSL by fixing USB device permissions, restarting smart card services, and applying a polkit policy override that allows smart card access in WSL's "inactive" session context.
### Usage
```bash
bash bash/yubikey/fix-yubikey-perms.sh
```
### Environment Variables
None.
### Data Files
None.
### Notes
- Run this script when `ykman` or `yubico-piv-tool` fail with "Failed to connect" or similar errors after attaching the YubiKey via `usbipd`.
- The polkit fix modifies `/usr/share/polkit-1/actions/org.debian.pcsc-lite.policy` (a backup is created automatically on first run).
- Requires `sudo` access. Several steps use `sudo` to modify system files and restart services.
- Requires `lsusb`, `yubico-piv-tool`, `systemctl`, and `gpgconf` to be available.
---
## list-yubikey-ssh-keys.sh
Scans PIV slots 9a, 9c, 9d, and 9e on the connected YubiKey and prints any SSH public keys found, along with the certificate subject label if one is present.
### Usage
```bash
bash bash/yubikey/list-yubikey-ssh-keys.sh
```
### Environment Variables
None.
### Data Files
None.
### Notes
- Requires `ykman`, `ssh-keygen`, and `openssl` to be available.
- Writes a temporary file to `/tmp/yubi_tmp.pem` during execution; it is cleaned up automatically after each slot is processed.