**Table of Contents**
- [Gpack Development Guide](#gpack-development-guide)
- [Overview](#overview)
- [Getting Started](#getting-started)
- [Initialize New Gpack](#initialize-new-gpack)
- [Gpack Structure](#gpack-structure)
- [Gpack Manifest (`ggen.toml`)](#gpack-manifest-ggentoml)
- [Basic Manifest](#basic-manifest)
- [Manifest Fields](#manifest-fields)
- [Required Fields](#required-fields)
- [Optional Fields](#optional-fields)
- [Template Development](#template-development)
- [Template Structure](#template-structure)
- [Template Best Practices](#template-best-practices)
- [Macro Development](#macro-development)
- [Creating Macros](#creating-macros)
- [Using Macros](#using-macros)
- [RDF Graph Development](#rdf-graph-development)
- [Graph Structure](#graph-structure)
- [SPARQL Queries](#sparql-queries)
- [Testing](#testing)
- [Golden Tests](#golden-tests)
- [Test Configuration](#test-configuration)
- [Running Tests](#running-tests)
- [Linting and Validation](#linting-and-validation)
- [Lint Gpack](#lint-gpack)
- [Validation Checks](#validation-checks)
- [Publishing](#publishing)
- [Prepare for Publishing](#prepare-for-publishing)
- [Publish to Registry](#publish-to-registry)
- [Publishing Process](#publishing-process)
- [Versioning](#versioning)
- [Semantic Versioning](#semantic-versioning)
- [Version Guidelines](#version-guidelines)
- [Changelog](#changelog)
- [Dependencies](#dependencies)
- [Adding Dependencies](#adding-dependencies)
- [Dependency Types](#dependency-types)
- [Dependency Resolution](#dependency-resolution)
- [Best Practices](#best-practices)
- [Gpack Design](#gpack-design)
- [Template Quality](#template-quality)
- [Community Guidelines](#community-guidelines)
- [Troubleshooting](#troubleshooting)
- [Common Issues](#common-issues)
- [Template Not Found](#template-not-found)
- [Dependency Conflicts](#dependency-conflicts)
- [RDF Validation Errors](#rdf-validation-errors)
- [Test Failures](#test-failures)
- [Getting Help](#getting-help)
- [Advanced Topics](#advanced-topics)
- [Custom Filters](#custom-filters)
- [Plugin System](#plugin-system)
- [CI/CD Integration](#cicd-integration)
# Gpack Development Guide
This guide covers creating, testing, and publishing gpacks to the ggen marketplace.
## Overview
Gpacks are versioned template collections that can be shared across the ggen community. They include:
- **Templates**: `.tmpl` files with YAML frontmatter
- **Macros**: Reusable template fragments (`.tera` files)
- **RDF Graphs**: Semantic models and SPARQL queries
- **Tests**: Golden tests for validation
- **Dependencies**: Other gpacks this gpack depends on
## Getting Started
### Initialize New Gpack
```bash
# Create new gpack
ggen pack init
# This creates:
# ├── ggen.toml # Gpack manifest
# ├── templates/ # Template directory
# ├── macros/ # Macro directory
# ├── graphs/ # RDF graphs
# ├── tests/ # Test directory
# └── README.md # Documentation
```
### Gpack Structure
```
my-gpack/
├── ggen.toml # Gpack manifest
├── templates/ # Template files
│ └── cli/
│ └── subcommand/
│ ├── rust.tmpl
│ ├── graphs/ # Local RDF data
│ │ ├── cli.ttl
│ │ └── shapes/
│ │ └── cli.shacl.ttl
│ └── queries/ # Local SPARQL queries
│ └── commands.rq
├── macros/ # Reusable fragments
│ └── common.tera
├── tests/ # Golden tests
│ └── test_hello.rs
├── README.md # Documentation
└── .gitignore # Git ignore file
```
## Gpack Manifest (`ggen.toml`)
### Basic Manifest
```toml
[gpack]
id = "io.ggen.rust.cli-subcommand"
name = "Rust CLI subcommand"
version = "0.1.0"
description = "Generate clap subcommands"
license = "MIT"
authors = ["Your Name <your.email@example.com>"]
repository = "https://github.com/your-org/your-gpack"
homepage = "https://github.com/your-org/your-gpack"
keywords = ["rust", "cli", "clap"]
ggen_compat = ">=0.2 <0.4"
[dependencies]
"io.ggen.macros.std" = "^0.2"
[templates]
entrypoints = ["cli/subcommand/rust.tmpl"]
includes = ["macros/**/*.tera"]
[rdf]
base = "http://example.org/"
prefixes.ex = "http://example.org/"
files = ["templates/**/graphs/*.ttl"]
inline = ["@prefix ex: <http://example.org/> . ex:Foo a ex:Type ."]
```
### Manifest Fields
#### Required Fields
- `id`: Unique identifier (reverse domain notation)
- `name`: Human-readable name
- `version`: Semantic version
- `description`: Brief description
- `license`: License identifier
- `ggen_compat`: Required ggen version range
#### Optional Fields
- `authors`: List of authors
- `repository`: Source repository URL
- `homepage`: Project homepage
- `keywords`: Search keywords
- `readme`: Path to README file
- `changelog`: Path to changelog file
## Template Development
### Template Structure
```yaml
---
name: "example"
description: "Example command"
rdf:
inline:
- mediaType: text/turtle
text: |
@prefix cli: <urn:ggen:cli#> .
[] a cli:Command ;
cli:name "{{ name }}" ;
cli:description "{{ description }}" .
sparql:
vars:
- name: slug
query: |
PREFIX cli: <urn:ggen:cli#>
SELECT ?slug WHERE { ?c a cli:Command ; cli:name ?slug } LIMIT 1
determinism:
seed: "{{ name }}"
---
// Generated by gpack: {{ gpack.id }}
// Template: {{ template.path }}
use clap::Parser;
#[derive(Parser)]
#[arg(short, long)]
pub verbose: bool,
}
if args.verbose {
println!("Verbose mode enabled");
}
Ok(())
}
```
### Template Best Practices
1. **Use semantic variable names**: `name`, `description`, `version`
2. **Include RDF models**: Define semantic structure
3. **Add SPARQL queries**: Extract variables from graphs
4. **Include determinism**: Use seeds for reproducibility
5. **Add comments**: Document generated code
6. **Use filters**: Apply transformations (`| snake_case`, `| pascal`)
## Macro Development
### Creating Macros
```tera
{#- Common CLI argument structure #}
{% macro cli_args(name, description) %}
#[derive(Parser)]
#[arg(short, long)]
pub verbose: bool,
}
{% endmacro %}
{#- Common error handling #}
{% macro error_handling() %}
-> Result<(), Box<dyn std::error::Error>> {
// Error handling logic
Ok(())
}
{% endmacro %}
```
### Using Macros
```yaml
---
to: "src/cmds/{{ name }}.rs"
---
{% import "macros/common.tera" as common %}
{{ common::cli_args(name, description) }}
## RDF Graph Development
### Graph Structure
```turtle
@prefix cli: <urn:ggen:cli#> .
@prefix ex: <http://example.org/> .
@base <http://example.org/> .
ex:Command a cli:Command ;
cli:name "example" ;
cli:description "Example command" ;
cli:subcommands (
ex:StatusCommand
ex:ConfigCommand
) .
ex:StatusCommand a cli:Command ;
cli:name "status" ;
cli:description "Show status" .
ex:ConfigCommand a cli:Command ;
cli:name "config" ;
cli:description "Manage configuration" .
```
### SPARQL Queries
```sparql
PREFIX cli: <urn:ggen:cli#>
PREFIX ex: <http://example.org/>
# Extract command names
SELECT ?name WHERE {
?cmd a cli:Command ;
cli:name ?name .
}
# Extract subcommands
SELECT ?parent ?child WHERE {
?parent a cli:Command ;
cli:subcommands ?child .
?child a cli:Command .
}
```
## Testing
### Golden Tests
```rust
// tests/test_hello.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hello_command() {
// Test generated code compiles
let args = HelloArgs { verbose: false };
let result = hello(args);
assert!(result.is_ok());
}
}
```
### Test Configuration
```toml
# ggen.toml
[tests]
golden = ["tests/*.rs"]
variables = [
{ name = "test1", description = "Test command 1" },
{ name = "test2", description = "Test command 2" }
]
```
### Running Tests
```bash
# Run all tests
ggen pack test
# Run specific test
ggen pack test --test test_hello
# Run with verbose output
ggen pack test --verbose
```
## Linting and Validation
### Lint Gpack
```bash
# Lint gpack for publishing
ggen pack lint
# Lint specific template
ggen pack lint --template templates/cli/subcommand/rust.tmpl
# Lint with fixes
ggen pack lint --fix
```
### Validation Checks
The linter checks for:
- **Manifest validity**: Correct `ggen.toml` structure
- **Template syntax**: Valid YAML frontmatter
- **RDF validity**: Well-formed RDF graphs
- **SPARQL syntax**: Valid SPARQL queries
- **Dependencies**: Resolvable dependencies
- **Versioning**: Semantic versioning compliance
## Publishing
### Prepare for Publishing
```bash
# Update version
# Edit ggen.toml:
# version = "0.2.0"
# Run tests
ggen pack test
# Lint gpack
ggen pack lint
# Generate changelog
ggen pack changelog
```
### Publish to Registry
```bash
# Publish gpack
ggen pack publish
# Publish with specific version
ggen pack publish --version 0.2.0
# Publish with dry run
ggen pack publish --dry-run
```
### Publishing Process
1. **Validation**: Gpack is validated against schema
2. **Testing**: Golden tests are run
3. **Linting**: Code quality checks
4. **Registry Upload**: Gpack is uploaded to registry
5. **Index Update**: Registry index is updated
6. **Notification**: Community is notified
## Versioning
### Semantic Versioning
Follow semantic versioning (semver):
- **Major** (1.0.0 → 2.0.0): Breaking changes
- **Minor** (1.0.0 → 1.1.0): New features
- **Patch** (1.0.0 → 1.0.1): Bug fixes
### Version Guidelines
- **0.x.x**: Development versions
- **1.x.x**: Stable versions
- **Pre-release**: Use `-alpha`, `-beta`, `-rc` suffixes
### Changelog
```markdown
# Changelog
## [0.2.0] - 2024-01-15
### Added
- New CLI subcommand template
- Support for verbose flag
- Error handling macros
### Changed
- Updated RDF model structure
- Improved SPARQL queries
### Fixed
- Template variable resolution
- Macro import issues
## [0.1.0] - 2024-01-01
### Added
- Initial release
- Basic CLI subcommand template
```
## Dependencies
### Adding Dependencies
```toml
# ggen.toml
[dependencies]
"io.ggen.macros.std" = "^0.2"
"io.ggen.common.rdf" = "~0.1.0"
"io.ggen.rust.cli" = ">=0.1.0 <0.3.0"
```
### Dependency Types
- **Caret (^)**: Compatible versions (^0.2.0 = >=0.2.0 <0.3.0)
- **Tilde (~)**: Patch-level changes (~0.1.0 = >=0.1.0 <0.2.0)
- **Exact**: Specific version (=0.2.1)
- **Range**: Version range (>=0.1.0 <0.3.0)
### Dependency Resolution
```bash
# Check dependencies
ggen pack deps
# Update dependencies
ggen pack update
# Resolve conflicts
ggen pack resolve
```
## Best Practices
### Gpack Design
1. **Single Responsibility**: One gpack, one purpose
2. **Consistent API**: Use standard variable names
3. **Documentation**: Include README and examples
4. **Testing**: Comprehensive golden tests
5. **Versioning**: Follow semver strictly
### Template Quality
1. **Readability**: Clear, well-commented code
2. **Maintainability**: Modular, reusable templates
3. **Performance**: Efficient SPARQL queries
4. **Security**: Validate all inputs
5. **Accessibility**: Follow language best practices
### Community Guidelines
1. **Naming**: Use descriptive, consistent names
2. **Licensing**: Choose appropriate licenses
3. **Contributing**: Welcome community contributions
4. **Support**: Provide issue tracking
5. **Updates**: Regular maintenance and updates
## Troubleshooting
### Common Issues
#### Template Not Found
```bash
# Check template path
ggen pack lint --template templates/cli/subcommand/rust.tmpl
# Verify entrypoints in manifest
#### Dependency Conflicts
```bash
# Check dependency tree
ggen pack deps --tree
# Resolve conflicts
ggen pack resolve --force
```
#### RDF Validation Errors
```bash
# Validate RDF graphs
ggen pack lint --rdf-only
# Check SPARQL syntax
ggen pack lint --sparql-only
```
#### Test Failures
```bash
# Run tests with verbose output
ggen pack test --verbose
# Check test configuration
### Getting Help
- **Documentation**: Check this guide and other docs
- **Community**: Join ggen community forums
- **Issues**: Report bugs and request features
- **Discussions**: Ask questions and share ideas
## Advanced Topics
### Custom Filters
```rust
// Add custom Tera filters
use tera::{Filter, Value, Result};
pub fn custom_filter(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
// Custom filter logic
Ok(value.clone())
}
```
### Plugin System
```toml
# ggen.toml
[plugins]
"io.ggen.plugin.custom" = "^0.1.0"
```
### CI/CD Integration
```yaml
# .github/workflows/publish.yml
name: Publish Gpack
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install ggen
run: cargo install ggen
- name: Test gpack
run: ggen pack test
- name: Lint gpack
run: ggen pack lint
- name: Publish gpack
run: ggen pack publish
env:
GGEN_REGISTRY_TOKEN: ${{ secrets.GGEN_REGISTRY_TOKEN }}
```
This guide provides comprehensive coverage of gpack development, from initial creation to publishing and maintenance. Follow these practices to create high-quality, maintainable gpacks for the ggen community.