Claude-skill-registry Component Creator
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.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/component-creator" ~/.claude/skills/majiayu000-claude-skill-registry-component-creator && rm -rf "$T"
skills/data/component-creator/SKILL.mdto-be-continuous Component Creation Guide
Guide users through creating production-ready to-be-continuous components that follow ecosystem conventions, architectural principles, and best practices.
Overview
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:
- Single-responsibility principle per component
- Component-based architecture with
spec.inputs - Variant patterns for different authentication methods
- Base job inheritance for extensibility
- Convention over configuration
- Adaptive pipeline strategy
Core Philosophy
Single Responsibility & Modularity
Each component handles ONE specific pipeline stage (build, test, package, deploy, analyze). Components cooperate gracefully through:
- Shared artifact formats (Maven artifacts → Docker builds)
- Standardized dotenv variable exports
- Common stage naming conventions
- Reusable tool outputs (SonarQube reusing test reports)
Adaptive Pipeline Strategy
"Prioritize speed in early development stages, gradually introduce Quality & Security tasks as you get closer to production."
Implementation:
- Development branches: Manual quality checks, allowed to fail
- Draft MRs: Auto-run quality checks, allowed to fail
- Ready MRs: Auto-run quality checks, must succeed
- Production/integration branches: All checks required
Composability Over Integration
Components integrate through:
- Standardized stage sequence (11 stages)
- Dotenv artifact propagation
- Common variable naming patterns
- Shared authentication mechanisms
Component Directory Structure
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:
- templates/ directory: MUST contain all component YAML files
- Standard variant: MUST exist (gitlab-ci-component.yml)
- Variant suffixes: Use established patterns (-vault, -oidc, -gcp, -aws, -eks, -ecr)
- README.md: MUST document inputs, examples, variants
- CHANGELOG.md: MUST track version changes
Component YAML Structure
Required Sections
Every component YAML file MUST contain:
- spec: Input/output specification
- Base job: Hidden job (
) extended by all jobs.component-base - Jobs: Concrete jobs that execute in pipeline stages
- Scripts: Reusable bash functions (via YAML anchors)
Standard Template Structure
# 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]
Input Specification Best Practices
Dual Syntax Support
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 ]]
Naming Conventions
Inputs (kebab-case):
,build-tool
,snapshot-imageregistry-mirror- Use hyphens to separate words
- All lowercase
Variables (SCREAMING_SNAKE_CASE):
,COMPONENT_BUILD_TOOL
,COMPONENT_SNAPSHOT_IMAGECOMPONENT_REGISTRY_MIRROR- Use
prefixCOMPONENT_ - All uppercase with underscores
Input Types
spec: 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 vs Optional Inputs
Required inputs (no default):
- Critical for component functionality
- Component fails if not provided
- Example: deployment target, required credentials
Optional inputs (with default):
- Customization and tuning
- Sensible defaults for common use cases
- Example: image versions, feature flags, timeouts
Best practice: Minimize required inputs. Provide defaults whenever possible.
Base Job Patterns
Hidden Base Job
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"
Tool-Specific Base Jobs
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
Job Naming Conventions
Format
[component]-[action] or [component]-[tool]-[action]
Examples:
,docker-build
,docker-publishdocker-trivy
,maven-compile
,maven-testmaven-deploy
,k8s-review
,k8s-stagingk8s-production
Action Verbs
Use consistent verbs:
- build: Compile, assemble artifacts
- test: Unit tests, integration tests
- scan: Security scanning, vulnerability analysis
- lint: Code linting, static analysis
- package: Create distributable format
- publish: Upload to registry
- deploy: Deploy to environment
- cleanup: Remove resources
Environment Jobs
For deployment components:
(ephemeral review environments)component-review
(integration testing environment)component-integration
(pre-production environment)component-staging
(production environment)component-production
Pipeline Stages
Standard 11-Stage Sequence
stages: - .pre - build - test - package-build - package-test - infra - deploy - acceptance - publish - infra-prod - production - .post
Stage assignments:
- build: Compile code, run unit tests
- test: Additional testing (integration, contract)
- package-build: Build containers, packages
- package-test: Test packages (security scans, healthchecks)
- infra: Provision non-prod infrastructure
- deploy: Deploy to non-prod environments
- acceptance: Functional, performance, security tests
- publish: Promote artifacts to release registries
- infra-prod: Provision production infrastructure
- production: Deploy to production
Custom stages: Can be inserted (e.g.,
code-analysis between test and package-build)
Variant Patterns
Common Variants
| Variant | Suffix | Authentication | Use Case | Components |
|---|---|---|---|---|
| Standard | (none) | CI/CD variables | Simple deployments | All (62) |
| Vault | | HashiCorp Vault JWT/AppRole | Enterprise secrets management | ~20 |
| OIDC | | OpenID Connect | Temporary cloud credentials | AWS, Azure, GCloud |
| GCP | | Workload Identity Federation | GKE deployments, Artifact Registry | Docker, K8s, Helm, S3, Terraform |
| AWS/EKS | / | OIDC with IAM roles | EKS deployments, ECR registry | K8s, Docker |
| ECR | | OIDC with IAM | ECR-specific registry auth | Docker |
Consult
../template-discovery/references/variantes.md for complete catalog (70+ variants documented).
When to Create a Variant
Create a variant when:
- Authentication method differs: Vault vs static credentials
- Platform integration required: GCP Workload Identity, AWS OIDC
- Security requirements change: OIDC temporary credentials vs long-lived tokens
- Deployment strategy differs: Different cloud provider SDKs
Don't create variant for:
- Configuration differences (use inputs/variables)
- Optional features (use boolean inputs)
- Minor behavior changes (use conditional logic)
Variant Implementation Pattern
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
Variable Conventions
Variable Scoping
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"
Secret Handling
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" }
Artifact Export Patterns
DotEnv Artifacts
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}"
Standard Output Variables
Naming convention:
component_attribute
Examples:
,docker_image
,docker_tagdocker_digest
,maven_artifactmaven_version
,k8s_namespacek8s_service_url
Benefits:
- Declarative deployment pipelines
- Version propagation across stages
- Artifact traceability
Rules and Conditions
Standard Rule References
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-back-merge: Prevent pipelines on automated back-merges
- prefer-mr-pipeline: Use MR pipelines over branch pipelines when both exist
- extended-skip-ci: Support
,[skip ci on tag]
, etc.[skip ci on mr]
Adaptive Pipeline Policies
Test jobs (quality/security):
component-test: rules: - !reference [.test-policy, rules]
Behavior:
- Tag/protected branches: Auto-run, must succeed
- Dev branch (no MR): Manual, allowed to fail
- Draft MR: Auto-run, allowed to fail
- Ready MR: Auto-run, must succeed
Delivery jobs (publish/production):
component-publish: rules: - !reference [.delivery-policy, rules]
Behavior:
- Execute on release tags (SemVer)
- Execute on production/integration branches
- Skip elsewhere
Custom Rules
component-manual-job: rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' when: never - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' when: manual - when: never
Script Best Practices
Logging Functions
.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 $*"; }
Tool Installation Helpers
maybe_install_tool() { if ! command -v tool &> /dev/null; then log_info "Installing tool..." # Installation logic fi }
Multi-Distro Compatibility
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 }
Error Handling
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" }
Component Naming
Component Names
- kebab-case:
,docker
,semantic-release
,kubernetescloud-native-buildpacks - Descriptive: Clearly indicate technology/purpose
- Match technology:
for Maven,maven
for Terraformterraform - No abbreviations:
notkubernetes
(exception: widely known likek8s
)s3
Template Files
Pattern:
gitlab-ci-[component][-variant].yml
Examples:
(standard)gitlab-ci-docker.yml
(Vault variant)gitlab-ci-docker-vault.yml
(GCP variant)gitlab-ci-docker-gcp.yml
(AWS variant)gitlab-ci-kubernetes-aws.yml
Documentation Requirements
README.md Structure
# 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
CHANGELOG.md
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
Versioning Strategy
Semantic Versioning
Components MUST follow SemVer:
- MAJOR: Breaking changes (incompatible inputs, removed jobs)
- MINOR: New features (new inputs, new jobs, backward compatible)
- PATCH: Bug fixes (no new functionality)
Version Tags
Create Git tags for releases:
git tag -a v1.2.3 -m "Release version 1.2.3" git push origin v1.2.3
Version Aliases
GitLab automatically creates aliases:
→ latest 1.x.x1
→ latest 1.2.x1.2
→ exact version1.2.3
Users can pin:
# Always get latest patches component: .../component@1.2 # Pin exact version component: .../component@1.2.3
Testing Components
Sample Project
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
Validation Checklist
Before releasing component:
- All variants tested
- README documentation complete
- CHANGELOG updated
- Input specifications validated
- Sample project created
- Semantic versioning applied
- Security scan passed
- Component CI/CD passes
Reference Files
For detailed component patterns and examples:
: 62 existing components to study../template-discovery/references/catalog.md
: 70+ variant implementations across components../template-discovery/references/variantes.md
: Component syntax, scoped variables, secrets management../template-discovery/references/usage-guide.md
: Architectural patterns (Review Apps, GitOps, repo structure)../template-discovery/references/best-practices.md
Common Patterns
Minimal Component
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 ]]"
Multi-Tool Component
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
Environment Deployment Component
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]
Contributing Components
Workflow
- Discuss on Discord: Post message with topic
New template: component-name - Core team creates project: From template skeleton repository
- Fork and branch: Work from
branchinitial-component - Implement component: Follow patterns in this guide
- Create MR: Mark as Draft until ready
- Review: At least 2 core team approvals required
- Merge: Automatic release on merge
Commit Standards
- Atomic commits: One logical change per commit
- Semantic commits: Follow Conventional Commits
- Signed-off: Include
line (DCO)Signed-off-by:
Examples:
feat: add OIDC authentication variant fix: correct environment variable mapping docs: update README with new inputs
Review Criteria
- Follows naming conventions
- Includes all required files
- Documentation complete
- Sample project provided
- All variants tested
- Follows to-be-continuous philosophy
Summary: Key Behaviors
STRUCTURED:
- Follow standard directory layout
- Use established naming conventions
- Include all required files (README, CHANGELOG)
COMPATIBLE:
- Support dual syntax (inputs + variables)
- Use standard workflow rules
- Export dotenv artifacts for downstream jobs
- Follow 11-stage pipeline sequence
MODULAR:
- Single responsibility per component
- Hidden base job for extensibility
- Variant pattern for authentication methods
- Composable with other components
DOCUMENTED:
- Clear input specifications
- Usage examples in README
- Variant documentation
- Version changelog
TESTED:
- Sample project demonstrating usage
- All variants validated
- Component CI/CD passing
- Security scanning enabled
Remember: Study existing components in catalog.md and variantes.md for proven patterns. When in doubt, reference similar existing components for guidance.