This comprehensive guide covers all aspects of using DotGitHub to manage your GitHub Actions workflows.
- Project Structure
- Configuration
- Actions Management
- Construct System
- Stack Management
- Workflow Generation
- Advanced Features
- Best Practices
A typical DotGitHub project has the following structure:
my-project/
├── src/ # Generated TypeScript files
│ ├── dotgithub.json # Main configuration
│ ├── package.json # Node.js package file
│ ├── tsconfig.json # TypeScript configuration
│ ├── index.ts # Entry point
│ └── actions/ # Generated action wrappers
│ ├── index.ts # Root actions index
│ └── actions/ # GitHub Actions
│ ├── index.ts # Actions organization index
│ ├── checkout.ts # Checkout action wrapper
│ └── setup-node.ts # Setup Node action wrapper
├── .github/ # Generated workflows
│ └── workflows/
│ ├── ci.yml # CI workflow
│ └── deploy.yml # Deployment workflow
└── constructs/ # Custom constructs (optional)
└── my-construct.ts
The main configuration file controls all aspects of your DotGitHub project:
{
"version": "1.0.0",
"rootDir": "src",
"outputDir": ".",
"actions": [
{
"orgRepo": "actions/checkout",
"ref": "0057852bfaa89a56745cba8c7296529d2fc39830",
"versionRef": "v4",
"actionName": "checkout",
"outputPath": "actions/actions/checkout.ts"
}
],
"constructs": [
{
"name": "local",
"package": "./index.ts",
"config": {
"environment": "production"
},
"enabled": true
}
],
"stacks": [
{
"name": "ci",
"constructs": ["local"],
"config": {
"nodeVersion": "18"
}
}
],
"options": {
"tokenSource": "env",
"formatting": {
"prettier": true
}
}
}- version - Configuration schema version
- rootDir - Directory for generated TypeScript files
- outputDir - Directory for generated workflow files
Each action entry contains:
- orgRepo - GitHub repository (org/repo)
- ref - Specific commit SHA
- versionRef - Version reference (tag or branch)
- actionName - Generated function name
- outputPath - Relative path to generated TypeScript file
- actionPath - Sub-path for composite actions
- name - Unique construct identifier
- package - Construct package path or npm package name
- config - Construct-specific configuration
- enabled - Whether the construct is active
- name - Stack identifier
- constructs - Array of construct names to include
- config - Stack-specific configuration
Add GitHub Actions to your project:
# Add a single action
dotgithub add actions/checkout@v4
# Add multiple actions
dotgithub add actions/checkout@v4 actions/setup-node@v4
# Add with custom name
dotgithub add actions/setup-node@v4 --name setupNodeView all tracked actions:
dotgithub listUpdate actions to newer versions:
# Update all actions
dotgithub update
# Update specific action
dotgithub update actions/checkout
# Update to latest available
dotgithub update actions/checkout --latestRemove actions from your project:
# Remove completely
dotgithub remove actions/checkout@v4
# Remove from tracking only
dotgithub remove actions/checkout@v4 --keep-filesRegenerate TypeScript files:
# Regenerate all actions
dotgithub regenerate
# Regenerate specific actions
dotgithub regenerate "actions/*"
# Regenerate with cleanup
dotgithub regenerate --pruneConstructs are TypeScript classes that implement the GitHubConstruct interface:
import {
GitHubConstruct,
GitHubStack,
WorkflowConstruct,
JobConstruct,
} from '@dotgithub/core';
export class MyConstruct implements GitHubConstruct {
readonly name = 'my-construct';
readonly version = '1.0.0';
readonly description = 'My custom construct';
validate(stack: GitHubStack): void {
// Validate stack configuration
}
describe() {
return {
name: this.name,
version: this.version,
description: this.description,
// ... other metadata
};
}
async synthesize(stack: GitHubStack): Promise<void> {
// Generate workflow content
}
}
export default new MyConstruct();Constructs can accept configuration through the config property:
{
"constructs": [
{
"name": "my-construct",
"package": "./constructs/my-construct.ts",
"config": {
"environment": "production",
"timeout": 30,
"retries": 3
},
"enabled": true
}
]
}Use Zod schemas for configuration validation:
import { z } from 'zod';
private readonly configSchema = z.object({
environment: z.enum(['development', 'staging', 'production']),
timeout: z.number().min(1).max(60).default(10),
retries: z.number().min(0).max(5).default(3)
});
validate(stack: GitHubStack): void {
this.configSchema.parse(stack.config);
}Manage constructs using the CLI:
# List constructs
dotgithub construct list
# Add construct
dotgithub construct add --name "my-construct" --package "./constructs/my-construct.ts"
# Remove construct
dotgithub construct remove --name "my-construct"
# Describe construct
dotgithub construct describe --name "my-construct"Stacks group constructs together for organized workflow generation:
{
"stacks": [
{
"name": "ci",
"constructs": ["checkout", "setup-node", "test"],
"config": {
"nodeVersion": "18",
"testCommand": "npm test"
}
},
{
"name": "deploy",
"constructs": ["build", "deploy"],
"config": {
"environment": "production",
"region": "us-east-1"
}
}
]
}Manage stacks using the CLI:
# List stacks
dotgithub construct stack list
# Add stack
dotgithub construct stack add --name "ci" --constructs "checkout,setup-node,test"
# Remove stack
dotgithub construct stack remove --name "ci"Create workflows using the WorkflowConstruct:
const wf = new WorkflowConstruct(stack, 'ci', {
name: 'CI Workflow',
on: {
push: { branches: ['main'] },
pull_request: {},
},
jobs: {},
});Add jobs to workflows using JobConstruct:
new JobConstruct(wf, 'test', {
'runs-on': 'ubuntu-latest',
steps: [
checkout('Checkout code').toStep(),
setupNode('Setup Node.js', {
'node-version': '18',
}).toStep(),
run('Install dependencies', 'npm install').toStep(),
run('Run tests', 'npm test').toStep(),
],
});Access actions through the Actions class:
const { checkout, setupNode, uploadArtifact } = new Actions(stack, 'actions');
// Type-safe usage
checkout('Checkout code', {
'fetch-depth': 1,
submodules: 'recursive',
}).toStep();Configure complex jobs with dependencies, matrices, and conditions:
// Job with dependencies
new JobConstruct(wf, 'deploy', {
'runs-on': 'ubuntu-latest',
needs: ['test', 'build'],
steps: [
// ... deployment steps
],
});
// Matrix job
new JobConstruct(wf, 'test', {
'runs-on': 'ubuntu-latest',
strategy: {
matrix: {
'node-version': ['16', '18', '20'],
os: ['ubuntu-latest', 'windows-latest', 'macos-latest'],
},
},
steps: [
setupNode('Setup Node.js', {
'node-version': '${{ matrix.node-version }}',
}).toStep(),
],
});
// Conditional job
new JobConstruct(wf, 'deploy', {
'runs-on': 'ubuntu-latest',
if: "github.ref == 'refs/heads/main'",
steps: [
// ... deployment steps
],
});Set environment variables for jobs:
new JobConstruct(wf, 'test', {
'runs-on': 'ubuntu-latest',
env: {
NODE_ENV: 'test',
CI: 'true',
},
steps: [
// ... test steps
],
});Use GitHub secrets and variables:
new JobConstruct(wf, 'deploy', {
'runs-on': 'ubuntu-latest',
steps: [
run('Deploy', 'echo "Deploying to ${{ secrets.ENVIRONMENT }}"').toStep(),
],
});Pin specific action versions for constructs or stacks:
# Pin for construct
dotgithub pin actions/checkout v4 --construct my-construct
# Pin for stack
dotgithub pin actions/setup-node v4.1.0 --stack ci
# List pins
dotgithub list-pins
# Remove pins
dotgithub unpin actions/checkout --construct my-constructOverride generated action names:
dotgithub add actions/setup-node@v4 --name setupNodeGenerate workflows to different directories:
dotgithub synth --output ./custom-workflowsPreview generated workflows without writing files:
dotgithub synth --dry-runGet detailed information about synthesis:
dotgithub synth --verbose- Use meaningful names - Choose descriptive names for constructs and stacks
- Organize by purpose - Group related functionality into constructs
- Version control - Commit generated workflows to your repository
- Document configuration - Add comments to explain complex configurations
- Validate configuration - Always validate construct configuration
- Handle errors gracefully - Provide clear error messages
- Use TypeScript - Leverage type safety for better development experience
- Test thoroughly - Test constructs with different configurations
- Keep jobs focused - Each job should have a single responsibility
- Use dependencies - Chain jobs with
needsfor proper execution order - Optimize for speed - Use caching and parallel execution where possible
- Handle failures - Include proper error handling and notifications
- Use secrets - Store sensitive data in GitHub secrets
- Minimize permissions - Use least-privilege access
- Validate inputs - Always validate user inputs and configuration
- Keep actions updated - Regularly update actions for security patches
- Use caching - Cache dependencies and build artifacts
- Parallel execution - Run independent jobs in parallel
- Optimize images - Use smaller, more efficient runner images
- Monitor usage - Track GitHub Actions usage and costs
- TypeScript errors - Check your
tsconfig.jsonconfiguration - Missing actions - Ensure all used actions are added with
dotgithub add - Synthesis failures - Validate construct configuration and check error messages
- Permission issues - Verify GitHub token permissions and repository access
- Use dry run - Preview changes with
dotgithub synth --dry-run - Check logs - Review synthesis output for error details
- Validate configuration - Use
dotgithub config showto verify settings - Test incrementally - Build and test constructs one at a time
- Command Documentation - Detailed CLI command reference
- API Reference - Complete API documentation
- Construct Development - Advanced construct creation
- GitHub Issues - Report bugs and request features
- Discord Community - Get help from the community
- Construct Development Guide - Create advanced constructs
- API Reference - Complete API documentation
- Configuration Guide - Deep dive into configuration options
- Examples - Real-world usage examples