This skill should be used when the user wants to "create to-be-continuous component", "build TBC template", "extend existing component", "create variant", "contribute to to-be-continuous", "component structure", "how to create gitlab ci component", or needs guidance on component architecture, naming conventions, GitLab CI component syntax, input specifications, base job patterns, or to-be-continuous best practices and philosophy.
/plugin marketplace add rafaelcalleja/claude-market-place/plugin install gitlab-tbc@claude-market-placeThis skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdexamples/full-component.ymlexamples/minimal-component.ymlexamples/variant-example.ymlGuide users through creating production-ready to-be-continuous components that follow ecosystem conventions, architectural principles, and best practices.
to-be-continuous components follow standardized patterns enabling composability, reusability, and maintainability across projects. Understanding component structure, naming conventions, and design principles is essential for creating components compatible with the ecosystem.
Key concepts:
spec.inputsEach component handles ONE specific pipeline stage (build, test, package, deploy, analyze). Components cooperate gracefully through:
"Prioritize speed in early development stages, gradually introduce Quality & Security tasks as you get closer to production."
Implementation:
Components integrate through:
Every to-be-continuous component follows this organizational pattern:
component-name/
├── templates/
│ ├── gitlab-ci-component.yml # Standard variant (required)
│ ├── gitlab-ci-component-vault.yml # Vault variant (optional)
│ ├── gitlab-ci-component-oidc.yml # OIDC variant (optional)
│ ├── gitlab-ci-component-gcp.yml # GCP variant (optional)
│ ├── gitlab-ci-component-aws.yml # AWS/EKS variant (optional)
│ └── gitlab-ci-component-ecr.yml # ECR variant (optional)
├── README.md # Component documentation (required)
├── CHANGELOG.md # Version history (required)
├── .gitlab-ci.yml # Component's own CI/CD (required)
└── LICENSE # MIT license (recommended)
Critical rules:
Every component YAML file MUST contain:
.component-base) extended by all jobs# Component: component-name
# Version: X.Y.Z
# Description: [What this component does]
# Documentation: https://to-be-continuous.gitlab.io/doc/ref/component-name
spec:
inputs:
# Required inputs (no default)
required-input:
description: "Description of required input"
type: string
# Optional inputs (with defaults)
optional-input:
description: "Description of optional input"
type: string
default: "default-value"
# Boolean inputs
feature-enabled:
description: "Enable specific feature"
type: boolean
default: false
# Enumerated inputs
build-tool:
description: "Tool to use for building"
type: string
options:
- tool1
- tool2
- default
default: "default"
# Reusable script library
.scripts: &component-scripts
- |
# Logging functions
log_info() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
log_warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
log_error() { echo -e "\033[1;31m[ERROR]\033[0m $*"; }
# Component-specific functions
component_function() {
# Function implementation
}
# Hidden base job - extended by all component jobs
.component-base:
image: appropriate/image:tag
variables:
# Map inputs to variables for backward compatibility
COMPONENT_VAR: $[[ inputs.required-input ]]
COMPONENT_FEATURE: $[[ inputs.feature-enabled ]]
before_script:
- *component-scripts
rules:
- !reference [.tbc-workflow-rules, skip-back-merge]
- !reference [.tbc-workflow-rules, prefer-mr-pipeline]
- !reference [.tbc-workflow-rules, extended-skip-ci]
# Concrete jobs
component-build:
stage: build
extends: .component-base
script:
- log_info "Building with $COMPONENT_VAR"
- component_function
artifacts:
reports:
dotenv: component.env
rules:
- when: on_success
component-test:
stage: test
extends: .component-base
script:
- log_info "Testing component"
needs:
- component-build
rules:
- !reference [.test-policy, rules]
component-publish:
stage: publish
extends: .component-base
script:
- log_info "Publishing component"
needs:
- component-build
- component-test
rules:
- !reference [.delivery-policy, rules]
Components MUST support BOTH input syntaxes for backward compatibility:
Modern (Component Inputs):
include:
- component: $CI_SERVER_FQDN/to-be-continuous/component/gitlab-ci-component@1.0.0
inputs:
build-tool: "maven"
enable-tests: true
Legacy (Variables):
include:
- project: 'to-be-continuous/component'
ref: '1.0.0'
file: '/templates/gitlab-ci-component.yml'
variables:
COMPONENT_BUILD_TOOL: "maven"
COMPONENT_ENABLE_TESTS: "true"
Implementation pattern:
spec:
inputs:
build-tool:
type: string
default: "default"
.component-base:
variables:
# Input maps to variable
COMPONENT_BUILD_TOOL: $[[ inputs.build-tool ]]
Inputs (kebab-case):
build-tool, snapshot-image, registry-mirrorVariables (SCREAMING_SNAKE_CASE):
COMPONENT_BUILD_TOOL, COMPONENT_SNAPSHOT_IMAGE, COMPONENT_REGISTRY_MIRRORCOMPONENT_ prefixspec:
inputs:
# String input
string-input:
type: string
description: "Single value input"
default: "default-value"
# Number input
number-input:
type: number
description: "Numeric value"
default: 3
# Boolean input
boolean-input:
type: boolean
description: "True/false flag"
default: false
# Enumerated input
choice-input:
type: string
description: "Select from options"
options:
- option1
- option2
- option3
default: "option1"
Required inputs (no default):
Optional inputs (with default):
Best practice: Minimize required inputs. Provide defaults whenever possible.
Purpose: Centralize configuration affecting all component jobs
Pattern:
.component-base:
image: $[[ inputs.image ]]
tags:
- docker
variables:
VAR1: $[[ inputs.var1 ]]
VAR2: "default-value"
before_script:
- *component-scripts
- setup_function
rules:
- !reference [.tbc-workflow-rules, skip-back-merge]
- !reference [.tbc-workflow-rules, prefer-mr-pipeline]
- !reference [.tbc-workflow-rules, extended-skip-ci]
Users can override:
.component-base:
tags:
- kubernetes
variables:
http_proxy: "http://proxy:8080"
For components supporting multiple tools:
.component-base:
# Common configuration
.component-tool1-base:
extends: .component-base
image: tool1/image:latest
variables:
TOOL: "tool1"
.component-tool2-base:
extends: .component-base
image: tool2/image:latest
variables:
TOOL: "tool2"
component-build-tool1:
extends: .component-tool1-base
script:
- tool1 build
component-build-tool2:
extends: .component-tool2-base
script:
- tool2 build
[component]-[action] or [component]-[tool]-[action]
Examples:
docker-build, docker-publish, docker-trivymaven-compile, maven-test, maven-deployk8s-review, k8s-staging, k8s-productionUse consistent verbs:
For deployment components:
component-review (ephemeral review environments)component-integration (integration testing environment)component-staging (pre-production environment)component-production (production environment)stages:
- .pre
- build
- test
- package-build
- package-test
- infra
- deploy
- acceptance
- publish
- infra-prod
- production
- .post
Stage assignments:
Custom stages: Can be inserted (e.g., code-analysis between test and package-build)
| Variant | Suffix | Authentication | Use Case | Components |
|---|---|---|---|---|
| Standard | (none) | CI/CD variables | Simple deployments | All (62) |
| Vault | -vault | HashiCorp Vault JWT/AppRole | Enterprise secrets management | ~20 |
| OIDC | -oidc | OpenID Connect | Temporary cloud credentials | AWS, Azure, GCloud |
| GCP | -gcp | Workload Identity Federation | GKE deployments, Artifact Registry | Docker, K8s, Helm, S3, Terraform |
| AWS/EKS | -aws/-eks | OIDC with IAM roles | EKS deployments, ECR registry | K8s, Docker |
| ECR | -ecr | OIDC with IAM | ECR-specific registry auth | Docker |
Consult ../template-discovery/references/variantes.md for complete catalog (70+ variants documented).
Create a variant when:
Don't create variant for:
Step 1: Copy standard variant
cp gitlab-ci-component.yml gitlab-ci-component-vault.yml
Step 2: Modify authentication mechanism
# Standard variant uses CI/CD variables
variables:
REGISTRY_TOKEN: $[[ inputs.registry-token ]]
# Vault variant fetches from Vault
variables:
REGISTRY_TOKEN: '@url@http://vault-secrets-provider/api/secrets/registry?field=token'
Step 3: Add variant-specific inputs
spec:
inputs:
vault-addr:
description: "Vault server address"
type: string
vault-role:
description: "Vault role for authentication"
type: string
default: "gitlab-ci"
Step 4: Update README with variant documentation
Step 5: Add to variantes.md catalog
Three levels of variables:
1. Global Component Variables
variables:
COMPONENT_VERSION: "1.0.0"
COMPONENT_DEFAULT_IMAGE: "alpine:latest"
2. Job-Level Variables
.component-base:
variables:
BASE_VAR: "value"
component-build:
variables:
BUILD_SPECIFIC_VAR: "value"
3. Scoped Variables (conditional)
variables:
S3_BUCKET: "nonprod-bucket"
scoped__S3_BUCKET__if__CI_ENVIRONMENT_NAME__equals__production: "prod-bucket"
Standard secrets (CI/CD variables):
variables:
SECRET_VAR: $SECRET_FROM_CICD_VARS
Unmaskable secrets (Base64 encoding):
variables:
SECRET_WITH_SPECIAL_CHARS: '@b64@eyJvcGVuIjoiJOKCrDVAbWUifQ=='
External secrets (Vault, URL):
variables:
VAULT_SECRET: '@url@http://vault-secrets-provider/api/secrets/path?field=name'
Secret evaluation (in scripts):
eval_secret() {
local var_name="$1"
local var_value="${!var_name}"
# Decode @b64@ prefix
if [[ "$var_value" =~ ^@b64@(.+)$ ]]; then
echo "${BASH_REMATCH[1]}" | base64 -d
return
fi
# Fetch @url@ prefix
if [[ "$var_value" =~ ^@url@(.+)$ ]]; then
curl -sSf "${BASH_REMATCH[1]}"
return
fi
# Return as-is
echo "$var_value"
}
Export variables for downstream jobs:
component-build:
script:
- build_command
- |
{
echo "component_version=${VERSION}"
echo "component_artifact=${ARTIFACT_PATH}"
echo "component_digest=$(sha256sum artifact | cut -d' ' -f1)"
} > component.env
artifacts:
reports:
dotenv: component.env
Downstream consumption:
component-deploy:
needs:
- component-build
script:
- echo "Deploying version ${component_version}"
- echo "Artifact digest: ${component_digest}"
Naming convention: component_attribute
Examples:
docker_image, docker_tag, docker_digestmaven_artifact, maven_versionk8s_namespace, k8s_service_urlBenefits:
Components MUST include standard workflow rules:
.component-base:
rules:
- !reference [.tbc-workflow-rules, skip-back-merge]
- !reference [.tbc-workflow-rules, prefer-mr-pipeline]
- !reference [.tbc-workflow-rules, extended-skip-ci]
Explanation:
[skip ci on tag], [skip ci on mr], etc.Test jobs (quality/security):
component-test:
rules:
- !reference [.test-policy, rules]
Behavior:
Delivery jobs (publish/production):
component-publish:
rules:
- !reference [.delivery-policy, rules]
Behavior:
component-manual-job:
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
- when: never
.scripts: &component-scripts
- |
# ANSI color codes
log_info() { echo -e "\033[1;34m[INFO]\033[0m $*"; }
log_warn() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
log_error() { echo -e "\033[1;31m[ERROR]\033[0m $*"; }
log_success() { echo -e "\033[1;32m[SUCCESS]\033[0m $*"; }
maybe_install_tool() {
if ! command -v tool &> /dev/null; then
log_info "Installing tool..."
# Installation logic
fi
}
detect_package_manager() {
if command -v apt-get &> /dev/null; then
echo "apt-get"
elif command -v yum &> /dev/null; then
echo "yum"
elif command -v apk &> /dev/null; then
echo "apk"
else
log_error "No supported package manager found"
return 1
fi
}
set -euo pipefail # Exit on error, undefined vars, pipe failures
# Function with error handling
safe_operation() {
if ! risky_command; then
log_error "Command failed"
return 1
fi
log_success "Command succeeded"
}
docker, semantic-release, kubernetes, cloud-native-buildpacksmaven for Maven, terraform for Terraformkubernetes not k8s (exception: widely known like s3)Pattern: gitlab-ci-[component][-variant].yml
Examples:
gitlab-ci-docker.yml (standard)gitlab-ci-docker-vault.yml (Vault variant)gitlab-ci-docker-gcp.yml (GCP variant)gitlab-ci-kubernetes-aws.yml (AWS variant)# Component Name
Brief description of what component does.
## Inputs
| Input | Type | Default | Description |
|-------|------|---------|-------------|
| `input-name` | string | `default` | Description |
## Variants
- **Standard**: Description
- **Vault**: Description
- **OIDC**: Description
## Example
\`\`\`yaml
include:
- component: $CI_SERVER_FQDN/to-be-continuous/component/gitlab-ci-component@1.0.0
inputs:
example-input: "value"
\`\`\`
## Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `COMPONENT_VAR` | Description | `value` |
## Jobs
- **component-build**: Description
- **component-test**: Description
## Integration
How component integrates with other components.
## License
MIT
Follow Keep a Changelog:
# Changelog
## [1.1.0] - 2024-01-15
### Added
- New input for feature X
- Support for variant Y
### Changed
- Updated default image to v2.0
### Fixed
- Bug in authentication flow
## [1.0.0] - 2023-12-01
### Added
- Initial release
Components MUST follow SemVer:
Create Git tags for releases:
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3
GitLab automatically creates aliases:
1 → latest 1.x.x1.2 → latest 1.2.x1.2.3 → exact versionUsers can pin:
# Always get latest patches
component: .../component@1.2
# Pin exact version
component: .../component@1.2.3
Create sample project demonstrating component usage:
samples/component-sample/
├── .gitlab-ci.yml # Uses component
├── README.md # Explains sample
├── src/ # Sample source code
└── tests/ # Sample tests
Sample .gitlab-ci.yml:
include:
- component: $CI_SERVER_FQDN/to-be-continuous/component/gitlab-ci-component@1.0.0
inputs:
build-tool: "maven"
enable-tests: true
Before releasing component:
For detailed component patterns and examples:
../template-discovery/references/catalog.md: 62 existing components to study../template-discovery/references/variantes.md: 70+ variant implementations across components../template-discovery/references/usage-guide.md: Component syntax, scoped variables, secrets management../template-discovery/references/best-practices.md: Architectural patterns (Review Apps, GitOps, repo structure)Single job, single stage:
spec:
inputs:
target:
type: string
.component-base:
image: alpine:latest
rules:
- !reference [.tbc-workflow-rules, skip-back-merge]
- !reference [.tbc-workflow-rules, prefer-mr-pipeline]
component-job:
stage: deploy
extends: .component-base
script:
- echo "Deploying to $[[ inputs.target ]]"
Support multiple build tools:
spec:
inputs:
build-tool:
type: string
options: [tool1, tool2, default]
default: "default"
.component-base:
variables:
TOOL: $[[ inputs.build-tool ]]
component-build-tool1:
extends: .component-base
rules:
- if: '$TOOL == "tool1"'
script:
- tool1 build
component-build-tool2:
extends: .component-base
rules:
- if: '$TOOL == "tool2"'
script:
- tool2 build
Deploy to multiple environments:
.component-base:
image: kubectl:latest
script:
- kubectl apply -f manifests/
component-review:
extends: .component-base
stage: deploy
environment:
name: review/$CI_COMMIT_REF_SLUG
on_stop: component-review-cleanup
component-staging:
extends: .component-base
stage: deploy
environment:
name: staging
component-production:
extends: .component-base
stage: production
environment:
name: production
rules:
- !reference [.delivery-policy, rules]
New template: component-nameinitial-component branchSigned-off-by: line (DCO)Examples:
feat: add OIDC authentication variant
fix: correct environment variable mapping
docs: update README with new inputs
STRUCTURED:
COMPATIBLE:
MODULAR:
DOCUMENTED:
TESTED:
Remember: Study existing components in catalog.md and variantes.md for proven patterns. When in doubt, reference similar existing components for guidance.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.