mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-03 09:17:09 +08:00
Broad drift audit against origin/main (b52b63396).
Reference pages (most user-visible drift):
- slash-commands: add /busy, /curator, /footer, /indicator, /redraw, /steer
that were missing; drop non-existent /terminal-setup; fix /q footnote
(resolves to /queue, not /quit); extend CLI-only list with all 24
CLI-only commands in the registry
- cli-commands: add dedicated sections for hermes curator / fallback /
hooks (new subcommands not previously documented); remove stale
hermes honcho standalone section (the plugin registers dynamically
via hermes memory); list curator/fallback/hooks in top-level table;
fix completion to include fish
- toolsets-reference: document the real 52-toolset count; split browser
vs browser-cdp; add discord / discord_admin / spotify / yuanbao;
correct hermes-cli tool count from 36 to 38; fix misleading claim
that hermes-homeassistant adds tools (it's identical to hermes-cli)
- tools-reference: bump tool count 55 -> 68; add 7 Spotify, 5 Yuanbao,
2 Discord toolsets; move browser_cdp/browser_dialog to their own
browser-cdp toolset section
- environment-variables: add 40+ user-facing HERMES_* vars that were
undocumented (--yolo, --accept-hooks, --ignore-*, inference model
override, agent/stream/checkpoint timeouts, OAuth trace, per-platform
batch tuning for Telegram/Discord/Matrix/Feishu/WeCom, cron knobs,
gateway restart/connect timeouts); dedupe the Cron Scheduler section;
replace stale QQ_SANDBOX with QQ_PORTAL_HOST
User-guide (top level):
- cli.md: compression preserves last 20 turns, not 4 (protect_last_n: 20)
- configuration.md: display.platforms is the canonical per-platform
override key; tool_progress_overrides is deprecated and auto-migrated
- profiles.md: model.default is the config key, not model.model
- sessions.md: CLI/TUI session IDs use 6-char hex, gateway uses 8
- checkpoints-and-rollback.md: destructive-command list now matches
_DESTRUCTIVE_PATTERNS (adds rmdir, cp, install, dd)
- docker.md: the container runs as non-root hermes (UID 10000) via
gosu; fix install command (uv pip); add missing --insecure on the
dashboard compose example (required for non-loopback bind)
- security.md: systemctl danger pattern also matches 'restart'
- index.md: built-in tool count 47 -> 68
- integrations/index.md: 6 STT providers, 8 memory providers
- integrations/providers.md: drop fictional dashscope/qwen aliases
Features:
- overview.md: 9 image models (not 8), 9 TTS providers (not 5),
8 memory providers (Supermemory was missing)
- tool-gateway.md: 9 image models
- tools.md: extend common-toolsets list with search / messaging /
spotify / discord / debugging / safe
- fallback-providers.md: add 6 real providers from PROVIDER_REGISTRY
(lmstudio, kimi-coding-cn, stepfun, alibaba-coding-plan,
tencent-tokenhub, azure-foundry)
- plugins.md: Available Hooks table now includes on_session_finalize,
on_session_reset, subagent_stop
- built-in-plugins.md: add the 7 bundled plugins the page didn't
mention (spotify, google_meet, three image_gen providers, two
dashboard examples)
- web-dashboard.md: add --insecure and --tui flags
- cron.md: hermes cron create takes positional schedule/prompt, not
flags
Messaging:
- telegram.md: TELEGRAM_WEBHOOK_SECRET is now REQUIRED when
TELEGRAM_WEBHOOK_URL is set (gateway refuses to start without it
per GHSA-3vpc-7q5r-276h). Biggest user-visible drift in the batch.
- discord.md: HERMES_DISCORD_TEXT_BATCH_SPLIT_DELAY_SECONDS default
is 2.0, not 0.1
- dingtalk.md: document DINGTALK_REQUIRE_MENTION /
FREE_RESPONSE_CHATS / MENTION_PATTERNS / HOME_CHANNEL /
ALLOW_ALL_USERS that the adapter supports
- bluebubbles.md: drop fictional BLUEBUBBLES_SEND_READ_RECEIPTS env
var; the setting lives in platforms.bluebubbles.extra only
- qqbot.md: drop dead QQ_SANDBOX; add real QQ_PORTAL_HOST and
QQ_GROUP_ALLOWED_USERS
- wecom-callback.md: replace 'hermes gateway start' (service-only)
with 'hermes gateway' for first-time setup
Developer-guide:
- architecture.md: refresh tool/toolset counts (61/52), terminal
backend count (7), line counts for run_agent.py (~13.7k), cli.py
(~11.5k), main.py (~10.4k), setup.py (~3.5k), gateway/run.py
(~12.2k), mcp_tool.py (~3.1k); add yuanbao adapter, bump platform
adapter count 18 -> 20
- agent-loop.md: run_agent.py line count 10.7k -> 13.7k
- tools-runtime.md: add vercel_sandbox backend
- adding-tools.md: remove stale 'Discovery import added to
model_tools.py' checklist item (registry auto-discovery)
- adding-platform-adapters.md: mark send_typing / get_chat_info as
concrete base methods; only connect/disconnect/send are abstract
- acp-internals.md: ACP sessions now persist to SessionDB
(~/.hermes/state.db); acp.run_agent call uses
use_unstable_protocol=True
- cron-internals.md: gateway runs scheduler in a dedicated background
thread via _start_cron_ticker, not on a maintenance cycle; locking
is cross-process via fcntl.flock (Unix) / msvcrt.locking (Windows)
- gateway-internals.md: gateway/run.py ~12k lines
- provider-runtime.md: cron DOES support fallback (run_job reads
fallback_providers from config)
- session-storage.md: SCHEMA_VERSION = 11 (not 9); add migrations
10 and 11 (trigram FTS, inline-mode FTS5 re-index); add
api_call_count column to Sessions DDL; document messages_fts_trigram
and state_meta in the architecture tree
- context-compression-and-caching.md: remove the obsolete 'context
pressure warnings' section (warnings were removed for causing
models to give up early)
- context-engine-plugin.md: compress() signature now includes
focus_topic param
- extending-the-cli.md: _build_tui_layout_children signature now
includes model_picker_widget; add to default layout
Also fixed three pre-existing broken links/anchors the build warned
about (docker.md -> api-server.md, yuanbao.md -> cron-jobs.md and
tips#background-tasks, nix-setup.md -> #container-aware-cli).
Regenerated per-skill pages via website/scripts/generate-skill-docs.py
so catalog tables and sidebar are consistent with current SKILL.md
frontmatter.
docusaurus build: clean, no broken links or anchors.
534 lines
14 KiB
Markdown
534 lines
14 KiB
Markdown
---
|
|
title: "Github Repo Management — Clone/create/fork repos; manage remotes, releases"
|
|
sidebar_label: "Github Repo Management"
|
|
description: "Clone/create/fork repos; manage remotes, releases"
|
|
---
|
|
|
|
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
|
|
|
# Github Repo Management
|
|
|
|
Clone/create/fork repos; manage remotes, releases.
|
|
|
|
## Skill metadata
|
|
|
|
| | |
|
|
|---|---|
|
|
| Source | Bundled (installed by default) |
|
|
| Path | `skills/github/github-repo-management` |
|
|
| Version | `1.1.0` |
|
|
| Author | Hermes Agent |
|
|
| License | MIT |
|
|
| Tags | `GitHub`, `Repositories`, `Git`, `Releases`, `Secrets`, `Configuration` |
|
|
| Related skills | [`github-auth`](/docs/user-guide/skills/bundled/github/github-github-auth), [`github-pr-workflow`](/docs/user-guide/skills/bundled/github/github-github-pr-workflow), [`github-issues`](/docs/user-guide/skills/bundled/github/github-github-issues) |
|
|
|
|
## Reference: full SKILL.md
|
|
|
|
:::info
|
|
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
|
:::
|
|
|
|
# GitHub Repository Management
|
|
|
|
Create, clone, fork, configure, and manage GitHub repositories. Each section shows `gh` first, then the `git` + `curl` fallback.
|
|
|
|
## Prerequisites
|
|
|
|
- Authenticated with GitHub (see `github-auth` skill)
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
if command -v gh &>/dev/null && gh auth status &>/dev/null; then
|
|
AUTH="gh"
|
|
else
|
|
AUTH="git"
|
|
if [ -z "$GITHUB_TOKEN" ]; then
|
|
if [ -f ~/.hermes/.env ] && grep -q "^GITHUB_TOKEN=" ~/.hermes/.env; then
|
|
GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" ~/.hermes/.env | head -1 | cut -d= -f2 | tr -d '\n\r')
|
|
elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then
|
|
GITHUB_TOKEN=$(grep "github.com" ~/.git-credentials 2>/dev/null | head -1 | sed 's|https://[^:]*:\([^@]*\)@.*|\1|')
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Get your GitHub username (needed for several operations)
|
|
if [ "$AUTH" = "gh" ]; then
|
|
GH_USER=$(gh api user --jq '.login')
|
|
else
|
|
GH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user | python3 -c "import sys,json; print(json.load(sys.stdin)['login'])")
|
|
fi
|
|
```
|
|
|
|
If you're inside a repo already:
|
|
|
|
```bash
|
|
REMOTE_URL=$(git remote get-url origin)
|
|
OWNER_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')
|
|
OWNER=$(echo "$OWNER_REPO" | cut -d/ -f1)
|
|
REPO=$(echo "$OWNER_REPO" | cut -d/ -f2)
|
|
```
|
|
|
|
---
|
|
|
|
## 1. Cloning Repositories
|
|
|
|
Cloning is pure `git` — works identically either way:
|
|
|
|
```bash
|
|
# Clone via HTTPS (works with credential helper or token-embedded URL)
|
|
git clone https://github.com/owner/repo-name.git
|
|
|
|
# Clone into a specific directory
|
|
git clone https://github.com/owner/repo-name.git ./my-local-dir
|
|
|
|
# Shallow clone (faster for large repos)
|
|
git clone --depth 1 https://github.com/owner/repo-name.git
|
|
|
|
# Clone a specific branch
|
|
git clone --branch develop https://github.com/owner/repo-name.git
|
|
|
|
# Clone via SSH (if SSH is configured)
|
|
git clone git@github.com:owner/repo-name.git
|
|
```
|
|
|
|
**With gh (shorthand):**
|
|
|
|
```bash
|
|
gh repo clone owner/repo-name
|
|
gh repo clone owner/repo-name -- --depth 1
|
|
```
|
|
|
|
## 2. Creating Repositories
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
# Create a public repo and clone it
|
|
gh repo create my-new-project --public --clone
|
|
|
|
# Private, with description and license
|
|
gh repo create my-new-project --private --description "A useful tool" --license MIT --clone
|
|
|
|
# Under an organization
|
|
gh repo create my-org/my-new-project --public --clone
|
|
|
|
# From existing local directory
|
|
cd /path/to/existing/project
|
|
gh repo create my-project --source . --public --push
|
|
```
|
|
|
|
**With git + curl:**
|
|
|
|
```bash
|
|
# Create the remote repo via API
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/user/repos \
|
|
-d '{
|
|
"name": "my-new-project",
|
|
"description": "A useful tool",
|
|
"private": false,
|
|
"auto_init": true,
|
|
"license_template": "mit"
|
|
}'
|
|
|
|
# Clone it
|
|
git clone https://github.com/$GH_USER/my-new-project.git
|
|
cd my-new-project
|
|
|
|
# -- OR -- push an existing local directory to the new repo
|
|
cd /path/to/existing/project
|
|
git init
|
|
git add .
|
|
git commit -m "Initial commit"
|
|
git remote add origin https://github.com/$GH_USER/my-new-project.git
|
|
git push -u origin main
|
|
```
|
|
|
|
To create under an organization:
|
|
|
|
```bash
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/orgs/my-org/repos \
|
|
-d '{"name": "my-new-project", "private": false}'
|
|
```
|
|
|
|
### From a Template
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh repo create my-new-app --template owner/template-repo --public --clone
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/owner/template-repo/generate \
|
|
-d '{"owner": "'"$GH_USER"'", "name": "my-new-app", "private": false}'
|
|
```
|
|
|
|
## 3. Forking Repositories
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh repo fork owner/repo-name --clone
|
|
```
|
|
|
|
**With git + curl:**
|
|
|
|
```bash
|
|
# Create the fork via API
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/owner/repo-name/forks
|
|
|
|
# Wait a moment for GitHub to create it, then clone
|
|
sleep 3
|
|
git clone https://github.com/$GH_USER/repo-name.git
|
|
cd repo-name
|
|
|
|
# Add the original repo as "upstream" remote
|
|
git remote add upstream https://github.com/owner/repo-name.git
|
|
```
|
|
|
|
### Keeping a Fork in Sync
|
|
|
|
```bash
|
|
# Pure git — works everywhere
|
|
git fetch upstream
|
|
git checkout main
|
|
git merge upstream/main
|
|
git push origin main
|
|
```
|
|
|
|
**With gh (shortcut):**
|
|
|
|
```bash
|
|
gh repo sync $GH_USER/repo-name
|
|
```
|
|
|
|
## 4. Repository Information
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh repo view owner/repo-name
|
|
gh repo list --limit 20
|
|
gh search repos "machine learning" --language python --sort stars
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
# View repo details
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO \
|
|
| python3 -c "
|
|
import sys, json
|
|
r = json.load(sys.stdin)
|
|
print(f\"Name: {r['full_name']}\")
|
|
print(f\"Description: {r['description']}\")
|
|
print(f\"Stars: {r['stargazers_count']} Forks: {r['forks_count']}\")
|
|
print(f\"Default branch: {r['default_branch']}\")
|
|
print(f\"Language: {r['language']}\")"
|
|
|
|
# List your repos
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
"https://api.github.com/user/repos?per_page=20&sort=updated" \
|
|
| python3 -c "
|
|
import sys, json
|
|
for r in json.load(sys.stdin):
|
|
vis = 'private' if r['private'] else 'public'
|
|
print(f\" {r['full_name']:40} {vis:8} {r.get('language', ''):10} ★{r['stargazers_count']}\")"
|
|
|
|
# Search repos
|
|
curl -s \
|
|
"https://api.github.com/search/repositories?q=machine+learning+language:python&sort=stars&per_page=10" \
|
|
| python3 -c "
|
|
import sys, json
|
|
for r in json.load(sys.stdin)['items']:
|
|
print(f\" {r['full_name']:40} ★{r['stargazers_count']:6} {r['description'][:60] if r['description'] else ''}\")"
|
|
```
|
|
|
|
## 5. Repository Settings
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh repo edit --description "Updated description" --visibility public
|
|
gh repo edit --enable-wiki=false --enable-issues=true
|
|
gh repo edit --default-branch main
|
|
gh repo edit --add-topic "machine-learning,python"
|
|
gh repo edit --enable-auto-merge
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
curl -s -X PATCH \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO \
|
|
-d '{
|
|
"description": "Updated description",
|
|
"has_wiki": false,
|
|
"has_issues": true,
|
|
"allow_auto_merge": true
|
|
}'
|
|
|
|
# Update topics
|
|
curl -s -X PUT \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
-H "Accept: application/vnd.github.mercy-preview+json" \
|
|
https://api.github.com/repos/$OWNER/$REPO/topics \
|
|
-d '{"names": ["machine-learning", "python", "automation"]}'
|
|
```
|
|
|
|
## 6. Branch Protection
|
|
|
|
```bash
|
|
# View current protection
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/branches/main/protection
|
|
|
|
# Set up branch protection
|
|
curl -s -X PUT \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/branches/main/protection \
|
|
-d '{
|
|
"required_status_checks": {
|
|
"strict": true,
|
|
"contexts": ["ci/test", "ci/lint"]
|
|
},
|
|
"enforce_admins": false,
|
|
"required_pull_request_reviews": {
|
|
"required_approving_review_count": 1
|
|
},
|
|
"restrictions": null
|
|
}'
|
|
```
|
|
|
|
## 7. Secrets Management (GitHub Actions)
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh secret set API_KEY --body "your-secret-value"
|
|
gh secret set SSH_KEY < ~/.ssh/id_rsa
|
|
gh secret list
|
|
gh secret delete API_KEY
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
Secrets require encryption with the repo's public key — more involved via API:
|
|
|
|
```bash
|
|
# Get the repo's public key for encrypting secrets
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/secrets/public-key
|
|
|
|
# Encrypt and set (requires Python with PyNaCl)
|
|
python3 -c "
|
|
from base64 import b64encode
|
|
from nacl import encoding, public
|
|
import json, sys
|
|
|
|
# Get the public key
|
|
key_id = '<key_id_from_above>'
|
|
public_key = '<base64_key_from_above>'
|
|
|
|
# Encrypt
|
|
sealed = public.SealedBox(
|
|
public.PublicKey(public_key.encode('utf-8'), encoding.Base64Encoder)
|
|
).encrypt('your-secret-value'.encode('utf-8'))
|
|
print(json.dumps({
|
|
'encrypted_value': b64encode(sealed).decode('utf-8'),
|
|
'key_id': key_id
|
|
}))"
|
|
|
|
# Then PUT the encrypted secret
|
|
curl -s -X PUT \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/secrets/API_KEY \
|
|
-d '<output from python script above>'
|
|
|
|
# List secrets (names only, values hidden)
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/secrets \
|
|
| python3 -c "
|
|
import sys, json
|
|
for s in json.load(sys.stdin)['secrets']:
|
|
print(f\" {s['name']:30} updated: {s['updated_at']}\")"
|
|
```
|
|
|
|
Note: For secrets, `gh secret set` is dramatically simpler. If setting secrets is needed and `gh` isn't available, recommend installing it for just that operation.
|
|
|
|
## 8. Releases
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh release create v1.0.0 --title "v1.0.0" --generate-notes
|
|
gh release create v2.0.0-rc1 --draft --prerelease --generate-notes
|
|
gh release create v1.0.0 ./dist/binary --title "v1.0.0" --notes "Release notes"
|
|
gh release list
|
|
gh release download v1.0.0 --dir ./downloads
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
# Create a release
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/releases \
|
|
-d '{
|
|
"tag_name": "v1.0.0",
|
|
"name": "v1.0.0",
|
|
"body": "## Changelog\n- Feature A\n- Bug fix B",
|
|
"draft": false,
|
|
"prerelease": false,
|
|
"generate_release_notes": true
|
|
}'
|
|
|
|
# List releases
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/releases \
|
|
| python3 -c "
|
|
import sys, json
|
|
for r in json.load(sys.stdin):
|
|
tag = r.get('tag_name', 'no tag')
|
|
print(f\" {tag:15} {r['name']:30} {'draft' if r['draft'] else 'published'}\")"
|
|
|
|
# Upload a release asset (binary file)
|
|
RELEASE_ID=<id_from_create_response>
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
-H "Content-Type: application/octet-stream" \
|
|
"https://uploads.github.com/repos/$OWNER/$REPO/releases/$RELEASE_ID/assets?name=binary-amd64" \
|
|
--data-binary @./dist/binary-amd64
|
|
```
|
|
|
|
## 9. GitHub Actions Workflows
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh workflow list
|
|
gh run list --limit 10
|
|
gh run view <RUN_ID>
|
|
gh run view <RUN_ID> --log-failed
|
|
gh run rerun <RUN_ID>
|
|
gh run rerun <RUN_ID> --failed
|
|
gh workflow run ci.yml --ref main
|
|
gh workflow run deploy.yml -f environment=staging
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
# List workflows
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/workflows \
|
|
| python3 -c "
|
|
import sys, json
|
|
for w in json.load(sys.stdin)['workflows']:
|
|
print(f\" {w['id']:10} {w['name']:30} {w['state']}\")"
|
|
|
|
# List recent runs
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
"https://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=10" \
|
|
| python3 -c "
|
|
import sys, json
|
|
for r in json.load(sys.stdin)['workflow_runs']:
|
|
print(f\" Run {r['id']} {r['name']:30} {r['conclusion'] or r['status']}\")"
|
|
|
|
# Download failed run logs
|
|
RUN_ID=<run_id>
|
|
curl -s -L \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/logs \
|
|
-o /tmp/ci-logs.zip
|
|
cd /tmp && unzip -o ci-logs.zip -d ci-logs
|
|
|
|
# Re-run a failed workflow
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/rerun
|
|
|
|
# Re-run only failed jobs
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/runs/$RUN_ID/rerun-failed-jobs
|
|
|
|
# Trigger a workflow manually (workflow_dispatch)
|
|
WORKFLOW_ID=<workflow_id_or_filename>
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/repos/$OWNER/$REPO/actions/workflows/$WORKFLOW_ID/dispatches \
|
|
-d '{"ref": "main", "inputs": {"environment": "staging"}}'
|
|
```
|
|
|
|
## 10. Gists
|
|
|
|
**With gh:**
|
|
|
|
```bash
|
|
gh gist create script.py --public --desc "Useful script"
|
|
gh gist list
|
|
```
|
|
|
|
**With curl:**
|
|
|
|
```bash
|
|
# Create a gist
|
|
curl -s -X POST \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/gists \
|
|
-d '{
|
|
"description": "Useful script",
|
|
"public": true,
|
|
"files": {
|
|
"script.py": {"content": "print(\"hello\")"}
|
|
}
|
|
}'
|
|
|
|
# List your gists
|
|
curl -s \
|
|
-H "Authorization: token $GITHUB_TOKEN" \
|
|
https://api.github.com/gists \
|
|
| python3 -c "
|
|
import sys, json
|
|
for g in json.load(sys.stdin):
|
|
files = ', '.join(g['files'].keys())
|
|
print(f\" {g['id']} {g['description'] or '(no desc)':40} {files}\")"
|
|
```
|
|
|
|
## Quick Reference Table
|
|
|
|
| Action | gh | git + curl |
|
|
|--------|-----|-----------|
|
|
| Clone | `gh repo clone o/r` | `git clone https://github.com/o/r.git` |
|
|
| Create repo | `gh repo create name --public` | `curl POST /user/repos` |
|
|
| Fork | `gh repo fork o/r --clone` | `curl POST /repos/o/r/forks` + `git clone` |
|
|
| Repo info | `gh repo view o/r` | `curl GET /repos/o/r` |
|
|
| Edit settings | `gh repo edit --...` | `curl PATCH /repos/o/r` |
|
|
| Create release | `gh release create v1.0` | `curl POST /repos/o/r/releases` |
|
|
| List workflows | `gh workflow list` | `curl GET /repos/o/r/actions/workflows` |
|
|
| Rerun CI | `gh run rerun ID` | `curl POST /repos/o/r/actions/runs/ID/rerun` |
|
|
| Set secret | `gh secret set KEY` | `curl PUT /repos/o/r/actions/secrets/KEY` (+ encryption) |
|