CtrlK
BlogDocsLog inGet started
Tessl Logo

ci-pipeline-synthesizer

Generates CI pipeline configs by analyzing a repo's structure, language, and build needs — GitHub Actions, GitLab CI, or other platforms. Use when bootstrapping CI for a new repo, when porting from one CI to another, when the user asks for a pipeline that builds and tests their project, or when wiring in security gates.

Install with Tessl CLI

npx tessl i github:santosomar/general-secure-coding-agent-skills --skill ci-pipeline-synthesizer
What are skills?

100

Quality

100%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SKILL.md
Review
Evals

CI Pipeline Synthesizer

Generate a CI config that actually runs, by reading the repo rather than asking the user twenty questions.

Step 1 — Detect the build

Read the repo, not the user's description. Signals:

File presentEcosystemBuild commandTest command
package.jsonNode/JSnpm ci then npm run buildnpm test
pyproject.toml / setup.pyPythonpip install -e . or uv syncpytest / python -m pytest
Cargo.tomlRustcargo build --releasecargo test
go.modGogo build ./...go test ./...
pom.xmlJava/Mavenmvn -B packagemvn -B test
build.gradle / build.gradle.ktsJava/Gradle./gradlew build./gradlew test
Makefile (and nothing else)Makemakemake test (if target exists)
Dockerfile (and no build system)Container-onlydocker build .— (look for test stage)

Read the actual file. package.json might not have a build script. Makefile might not have a test target. Adapt.

Step 2 — Choose the platform target

SignalEmit
.github/ dir existsGitHub Actions
.gitlab-ci.yml referenced in docs, or remote is gitlab.*GitLab CI
User specifiesWhatever they said
No signalGitHub Actions (default — largest install base)

Step 3 — Assemble the pipeline

Every CI pipeline has the same skeleton. Fill the slots:

[trigger]          — push to main + PRs. Nothing fancier unless asked.
  [checkout]       — always
  [setup runtime]  — language-specific setup action, version pinned to whatever the repo uses
  [cache deps]     — keyed on lockfile hash
  [install deps]   — from Step 1
  [lint]           — only if a lint config exists (.eslintrc, ruff.toml, .golangci.yml)
  [build]          — from Step 1 (skip for interpreted langs with no build step)
  [test]           — from Step 1
  [security]       — optional, see below

Pin versions. actions/checkout@v4 not @main. python-version: '3.11' not '3.x'. Floating versions are reproducibility bugs waiting to happen.

Security gates

Ask or infer whether to include (opt-in — they add runtime and noise):

  • Dependency audit (npm audit, pip-audit, cargo audit) — cheap, include by default as a non-blocking step
  • SAST — only if the repo already has a config for one (.semgrep.yml, CodeQL workflow); otherwise suggest but don't inject
  • Secret scanning — usually a platform feature, not a pipeline step — mention, don't add

Worked example

Repo contents: pyproject.toml (uses hatchling), uv.lock, tests/, .github/ exists but is empty.

Output (.github/workflows/ci.yml):

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - uses: astral-sh/setup-uv@v3
      - run: uv sync --frozen
      - run: uv run pytest

Six steps. No matrix (not asked for). No coverage upload (not asked for). --frozen because uv.lock exists — fail if lockfile is stale. Python 3.12 because pyproject.toml said requires-python = ">=3.12".

Edge cases

  • Monorepo with multiple languages: Emit one job per language, with paths: filters so they only run when their subtree changes. Don't run the Python tests because someone touched the Go service.
  • No tests exist: Still emit a build-and-lint pipeline. Add a commented-out # TODO: add test step when tests exist — don't silently skip it.
  • Build needs a service (DB, Redis): Add a services: block. Detect from test fixtures or docker-compose files.
  • The repo already has a CI config: Do NOT overwrite. Read it, report what's missing, offer a diff.

Do not

  • Do not emit a 200-line pipeline for a 10-file repo. Match complexity to the project.
  • Do not add matrix builds (multiple OS/versions) unless the project is a library that claims compatibility with a range. Applications run on one thing.
  • Do not add steps for tools the repo doesn't use. No eslint step if there's no .eslintrc.
  • Do not cargo-cult continue-on-error: true. If a step can fail, decide: is it blocking or not? If not blocking, why is it there?
  • Do not inline secrets. ${{ secrets.X }} only, and list which secrets need to be configured.

Output format

## Detected
Language: <lang>  Build: <cmd>  Test: <cmd>  Platform: <ci>

## Pipeline
<file path>
<code block with full pipeline>

## Secrets to configure
- <name>: <what it's for>

## Optional next steps
- <matrix build / coverage / security gate — only what's relevant>
Repository
santosomar/general-secure-coding-agent-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.