From vibesubin
Scaffolds test + deploy CI/CD pipelines for GitHub Actions, GitLab CI, Jenkins, and targets like Vercel, Netlify, Docker after assessing user's git host and deploy setup. Teaches basics to beginners.
npx claudepluginhub subinium/vibesubin --plugin vibesubinThis skill is limited to using the following tools:
CI/CD is one of the hardest topics for non-developers because it sits at the intersection of git, servers, authentication, and secrets management. Most tutorials jump straight to YAML. This skill starts earlier.
Generates complete CI/CD pipelines for Node.js, Python, Go, Rust projects using GitHub Actions, auto-detecting project type and recommending platforms like Vercel or Netlify with lint, test, build, deploy stages.
Guides GitLab CI/CD pipeline creation, debugging, and configuration including runners, jobs, stages, artifacts, caches, environments, and deployment automation.
Generates CI/CD pipeline configs adapted to project stack and platform, for GitHub Actions, GitLab CI, Jenkins, etc. Automates lint, tests, build, security, and deploy stages.
Share bugs, ideas, or general feedback.
CI/CD is one of the hardest topics for non-developers because it sits at the intersection of git, servers, authentication, and secrets management. Most tutorials jump straight to YAML. This skill starts earlier.
Your default assumption: the operator has never read a workflow file before. Don't patronize them, but don't skip concepts either.
Before generating any YAML, ask the operator two questions, one at a time. Don't ask all at once.
Question 1: "What happens when you push code today? Do you deploy manually, or is something already automated?"
Their answer tells you:
git pull" → They have a server and a manual deploy. You're replacing the manual step.Question 2: "Which git host are you on? GitHub, GitLab, Bitbucket, self-hosted?"
Their answer tells you which CI system you're writing for:
.gitlab-ci.yml)bitbucket-pipelines.yml)Do not generate YAML until both questions are answered. The #1 failure mode here is producing a GitHub Actions workflow for someone who's actually on GitLab.
If the operator says "just pick whatever's easiest," pick: GitHub + GitHub Actions + their current deploy target. Tell them explicitly that you picked that and why.
CI/CD is modular. Not every project needs every component. Use this tree to decide what to scaffold for a given repo.
CI Pipeline
│
├── REQUIRED (always scaffold)
│ ├── Checkout # git clone into the runner
│ ├── Runtime install # the language (Python/Node/Rust/Go/...)
│ ├── Dependency install # pip/npm/cargo/go mod
│ ├── Test execution # whatever test command the project has
│ └── Status reporting # pass/fail to the PR or commit
│
├── RECOMMENDED (scaffold unless operator declines)
│ ├── Lint # ruff/eslint/clippy/golangci-lint
│ ├── Typecheck # mypy/tsc --noEmit/cargo check/go vet
│ ├── Dependency caching # skip re-downloading node_modules every run
│ ├── Concurrency group # cancel old runs when a new commit lands
│ └── Branch / PR filter # only run on main + PRs, not every branch
│
├── OPTIONAL — auto deploy (only if operator asked)
│ ├── Deploy trigger # workflow_run on success, or direct push
│ ├── Deploy step # SSH / Vercel / Fly / Cloud Run / Docker push
│ ├── Post-deploy health check # curl -f /health, fail loudly
│ ├── Rollback path # revert to previous SHA on health fail
│ └── Notification # Slack/Telegram/email on success or fail
│
├── NICE TO HAVE (suggest, don't auto-add)
│ ├── Coverage report # pytest-cov, c8, tarpaulin
│ ├── Security scan # pip-audit, npm audit, cargo audit (see audit-security)
│ ├── Container build + push # if the deploy is container-based
│ ├── Integration tests # separate from unit, usually against a real DB
│ ├── Matrix builds # multiple OSes or language versions
│ ├── Scheduled runs # nightly cron for dependency updates or flake detection
│ └── Release automation # semantic-release, changesets, goreleaser
│
└── EXPENSIVE — offer only if operator asks
├── E2E browser tests # Playwright, Cypress (slow, flaky)
├── Visual regression # screenshot diffing
├── Load / stress tests # k6, Locust
├── Mutation testing # Stryker, PIT
└── Fuzzing # per-language fuzzer
How to use this tree with the operator:
Every added component costs something (runner minutes, maintenance, false-positive noise). Bias toward the minimal working pipeline. It's easier to add later than to remove.
If the operator said "what's a deploy?" or "what is CI?", pause and explain. Short, concrete, concrete, concrete. One analogy per concept.
CI (Continuous Integration) — "Every time you push code, a computer somewhere else runs your tests and tells you if anything broke. If the tests break, you find out in a minute instead of when a user hits the bug."
CD (Continuous Delivery / Deployment) — "If the tests pass, that same computer also deploys your code to production automatically. No more SSH."
Runner — "The computer that does the work. It's not your laptop and it's not your production server. Think of it as a rented robot that runs for 30 seconds and then disappears."
Workflow — "The recipe you give the runner. It's a YAML file that says: install these dependencies, run these tests, if they pass, deploy to this place."
Trigger — "The event that wakes the runner up. Usually 'someone pushed code to the main branch.' Can also be 'someone opened a pull request' or 'every Monday at 9am.'"
Secrets — "Passwords and API keys that the runner needs but that cannot be visible in the YAML (because YAML is in git and git is public). They live in a separate encrypted store on the CI platform and are injected into the runner at runtime."
Artifact — "The thing you built. A zip, a container image, a directory of static HTML. CI produces it; CD ships it."
Environment — "Where the artifact ends up. 'staging' is the pre-production test site; 'production' is what real users see."
After this one-page explanation, ask: "Does that make sense? Should I keep going, or do you want to pause and ask anything?"
The host you generate for depends on:
| Git host | CI file |
|---|---|
| GitHub | .github/workflows/*.yml |
| GitLab | .gitlab-ci.yml at repo root |
| Bitbucket | bitbucket-pipelines.yml at repo root |
| Gitea / Forgejo | .gitea/workflows/*.yml (uses GitHub Actions syntax) |
| CircleCI (add-on) | .circleci/config.yml |
| Travis (add-on) | .travis.yml |
Skill scaffolds for GitHub Actions by default. For others, state clearly: "I'll write this as GitHub Actions first, then point out the pieces that change for ." The core logic is portable even if the YAML syntax differs.
Generate two workflows at minimum:
test.yml — runs on every push and PRContents:
Commented inline for the non-developer reader. Every step has a comment explaining what it does.
deploy.yml — runs on success of test.ymlTriggered by workflow_run (GitHub Actions) or equivalent. Only fires if test.yml passed.
Contents depend on the deploy target (see Step 5). The invariant: deploy the exact revision that passed in test.yml, not whatever main happens to point to when the deploy job starts.
Built-in safety (every workflow this skill scaffolds enforces all of these):
permissions: contents: read — start from zero and only grant what the job actually needs. Default-broad token permissions are the #1 GitHub Actions supply-chain risk. Elevate per-job (e.g., id-token: write for OIDC) only where required.uses: line looks like uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2.workflow_run, use the successful run's head_sha and deploy that exact commit. Never git pull origin main blindly on the server — that is how commit A's passing tests deploy commit B by accident.DEPLOY_SSH_KEY — there is no OIDC equivalent for arbitrary SSH.production environment with required reviewers for any job that deploys to production. environment: name: production in the job turns on the approval gate. Pair with branch protection.CODEOWNERS covers .github/workflows/ so a random contributor can't silently change a workflow. Add /.github/workflows/ @maintainer at minimum.echo $SECRET still risks leaking through errors, stack traces, or timing. Never echo a secret. If a command's output might contain one, pipe through a redaction filter.concurrency group so two deploys don't race each other.timeout-minutes so a hung deploy eventually fails.always() step.curl -f <url>/health or equivalent. If the health check fails, the deploy job fails loudly.Working templates in this skill's templates/ directory:
templates/github-actions-test.yml — language-aware test workflow, permissions-hardened, SHA-pinnedtemplates/github-actions-deploy-ssh.yml — deploy to a VM over SSH, with post-deploy health check and cleanupTemplates for Vercel, Fly.io, Cloud Run, and Docker registries follow the same pattern — the skill can emit them on demand, but the canonical reference implementations are the two above.
Do not emit generic YAML just because it is the easiest thing to write. Before scaffolding, inspect the repo and tailor the workflow to the actual stack:
pnpm-lock.yaml → use pnpm, not npmyarn.lock → use yarnbun.lockb → use bunuv.lock → use uv runpoetry.lock → use poetry runCargo.toml → cargo check / cargo testgo.mod → go test ./...Gemfile → bundle exec ...composer.json → composer / phpunitmix.exs → mix testFramework markers matter too:
The operator should feel like the workflow was written for their repo, not copied from a blog post.
Needs:
DEPLOY_SSH_KEY)DEPLOY_HOST)DEPLOY_USER)sudo commands the deploy needs have NOPASSWD rules set up (sudoers.d)Common failure: sudo prompts for a password and the CI job hangs. Always verify NOPASSWD is set up or use a user that doesn't need sudo.
Reproduce locally first. If the operator has never done a remote deploy, tell them: "Before we automate this, we should do it manually from your laptop once to make sure it works. Can you SSH in and run the deploy commands by hand?" Automating a broken manual process leads to hours of debugging.
Most managed platforms already auto-deploy on push. CI's job here is only testing before deploy, not deploying itself. The skill should:
test.yml that runs on push and PRdeploy.yml unless the operator wants a staging/production gateThese typically use an image push + a deploy command:
docker build or flyctl deploy)Needs the platform's API token as a Secret (FLY_API_TOKEN, GCP_CREDENTIALS, etc.).
If the operator doesn't have somewhere to deploy, don't try to set up a full pipeline in one go. Suggest the simplest-possible target for their project:
fly.toml, or a VMAfter they pick, come back and run Step 4 / Step 5.
Every workflow that uses secrets needs a checklist handed to the operator. The skill produces this as a comment block in the generated YAML and also as a separate message:
## Secrets this workflow needs
Set these in your GitHub repo: Settings → Secrets and variables → Actions → New repository secret
- [ ] `DEPLOY_SSH_KEY` — contents of your SSH private key (e.g., `cat ~/.ssh/my_key`)
- [ ] `DEPLOY_HOST` — IP or hostname of your server (e.g., `192.0.2.1`)
- [ ] `DEPLOY_USER` — username on the server (e.g., `ubuntu`)
After you set all three, re-run the workflow. First run will usually fail on the SSH step if any secret is wrong — the log will tell you which one.
Never print the secret values themselves, and never store them in YAML.
Always recommend that the first run of a deploy workflow be manual, via workflow_dispatch. Reasons:
Tell the operator: "After I generate the files, go to Actions → Deploy → Run workflow. Watch the output. If it passes, you're set up. If it fails, paste me the error and I'll fix it."
Manual dispatch is for a reviewed re-deploy or first-run proof. Make the generated comments explicit about this. In normal operation, workflow_run should be the path that moves tested code to production.
DEPLOY_HOST in the YAML, the same name has to be in the checklistactions/checkout and actions/setup-* are fine; random actions from marketplace are a supply-chain risk. If you reference one, pin to a commit SHAworkflow_dispatch manually for the first run, then switch to workflow_run for subsequent automated runsThings to watch for in your own output:
git pull is enough — if the project has migrations, native dependencies, cache warming, or a restart step, git pull alone will silently produce a broken deployment. Enumerate every stepecho $DEPLOY_KEY in a step leaks the key to the public log. Never echo secretsWhen invoked from /vibesubin (the umbrella skill's parallel sweep), this skill runs in read-only audit mode. Do not scaffold workflows, do not write .github/workflows/*.yml, do not touch any files.
Instead, produce a findings-only report:
.github/workflows/, .gitlab-ci.yml, etc.) — list files with one-line purposes.permissions: blocks, overly-broad GITHUB_TOKEN scopes)./setup-ci directly will scaffold the missing pieces.The operator reviews the sweep report and, if they want the fixes applied, invokes /setup-ci directly — which then runs the full scaffolding procedure.
How to tell: the task context from the umbrella will include a sweep=read-only marker or an explicit instruction like "produce findings only, do not edit". If that's present, never write. If the operator invokes this skill by name (/setup-ci), the full procedure applies and editing is expected.
When the task context contains the tone=harsh marker (usually set by the /vibesubin harsh umbrella invocation, but can also come from direct requests like "don't sugarcoat" / "brutal review" / "매운 맛" / "厳しめ"), switch output rules on the CI audit report:
GITHUB_TOKEN has write-all on every workflow in this repo", "no pinned action SHAs, every uses: line is a moving target", ".github/workflows/deploy.yml echoes $DEPLOY_KEY in a run step — rotate that key and fix the workflow". No preamble.permissions: block". Harsh mode says "every job in this workflow gets a write-scoped GITHUB_TOKEN by default — this is the #1 supply-chain risk on GitHub Actions. Add permissions: contents: read now."workflow_dispatch for the first run, and says so in one sentence.Harsh mode does not invent findings, exaggerate CVE severity, or become rude. Every harsh statement must cite the same workflow file, job name, or secret reference the balanced version would cite. The change is framing, not substance.
.env or secrets → manage-secrets-env for the .env pattern and lifecycleproject-conventionsaudit-security immediatelyrefactor-verify for the fixCanonical working templates live in templates/:
templates/github-actions-test.yml — test workflow with permissions hardening and SHA-pinned actionstemplates/github-actions-deploy-ssh.yml — deploy to a VM over SSH with post-deploy health check and secret cleanupThe CI/CD concept explainer (runners, triggers, environments, OIDC, secrets, concurrency) is embedded in the "Step 2 — Concepts" section of this SKILL.md rather than split into a reference file. Per-platform deploy gotchas live in the "Step 5 — Deploy target specifics" section.