Skip to content

Latest commit

 

History

History
355 lines (282 loc) · 7.58 KB

File metadata and controls

355 lines (282 loc) · 7.58 KB

Getting Started

This guide will walk you through creating your first DotGitHub project and generating a simple CI workflow.

Prerequisites

Before starting, ensure you have:

  • DotGitHub installed
  • A GitHub repository
  • Basic knowledge of GitHub Actions
  • Familiarity with TypeScript (helpful but not required)

Step 1: Initialize Your Project

Create a new DotGitHub project:

dotgithub init

This creates a basic project structure:

src/
├── dotgithub.json      # Configuration file
├── package.json        # Node.js package file
├── tsconfig.json       # TypeScript configuration
└── index.ts           # Entry point file

Step 2: Add GitHub Actions

Add the GitHub Actions you need for your workflow:

dotgithub add actions/checkout@v4
dotgithub add actions/setup-node@v4

This downloads the action metadata and generates TypeScript wrappers.

Step 3: Create Your First Construct

Edit src/index.ts to create a simple CI construct:

import {
  createStep,
  GitHubConstruct,
  GitHubStack,
  JobConstruct,
  run,
  WorkflowConstruct,
} from '@dotgithub/core';
import { Actions } from './actions/index.js';

export class MyFirstConstruct extends GitHubConstruct {
  readonly name = 'my-first-construct';
  readonly version = '1.0.0';
  readonly description = 'My first DotGitHub construct';

  validate(stack: GitHubStack): void {
    // No validation needed for this simple construct
  }

  describe() {
    return {
      name: this.name,
      version: this.version,
      description: this.description,
      author: 'Your Name',
      repository: 'https://github.com/yourusername/yourrepo',
      license: 'MIT',
      keywords: ['ci', 'github-actions'],
      category: 'ci',
      tags: ['ci', 'testing'],
      minDotGithubVersion: '1.0.0',
    };
  }

  async synthesize(stack: GitHubStack): Promise<void> {
    const { checkout, setupNode } = new Actions(stack, 'actions');

    // Create a CI workflow
    const wf = new WorkflowConstruct(stack, 'ci', {
      name: 'CI Workflow',
      on: {
        push: { branches: ['main'] },
        pull_request: {},
      },
      jobs: {},
    });

    // Add a test job
    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(),
      ],
    });
  }
}

export default new MyFirstConstruct();

Step 4: Configure Your Construct

Update src/dotgithub.json to include your construct:

{
  "version": "1.0.0",
  "rootDir": "src",
  "outputDir": ".github/workflows",
  "actions": [
    {
      "orgRepo": "actions/checkout",
      "ref": "0057852bfaa89a56745cba8c7296529d2fc39830",
      "versionRef": "v4",
      "actionName": "checkout",
      "outputPath": "actions/actions/checkout.ts"
    },
    {
      "orgRepo": "actions/setup-node",
      "ref": "2028fbc5c25fe9cf00d9f06a71cc4710d4507903",
      "versionRef": "v4",
      "actionName": "setupNode",
      "outputPath": "actions/actions/setup-node.ts"
    }
  ],
  "constructs": [
    {
      "name": "local",
      "package": "./index.ts",
      "config": {},
      "enabled": true
    }
  ],
  "stacks": [
    {
      "name": "app",
      "constructs": ["local"],
      "config": {}
    }
  ],
  "options": {
    "tokenSource": "env",
    "formatting": {
      "prettier": true
    }
  }
}

Step 5: Generate Your Workflow

Run the synthesis command to generate your workflow:

dotgithub synth

This creates .github/workflows/ci.yml:

name: CI Workflow
on:
  push:
    branches:
      - main
  pull_request:
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm install
      - name: Run tests
        run: npm test

Step 6: Commit and Push

Add the generated workflow to your repository:

git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push

Understanding the Generated Code

TypeScript Wrappers

DotGitHub generates type-safe wrappers for GitHub Actions:

const { checkout, setupNode } = new Actions(stack, 'actions');

// Type-safe usage with IntelliSense
checkout('Checkout code').toStep();
setupNode('Setup Node.js', {
  'node-version': '18', // TypeScript knows this is a valid input
}).toStep();

Workflow Constructs

  • WorkflowConstruct - Represents a GitHub workflow
  • JobConstruct - Represents a workflow job
  • Actions - Provides type-safe action wrappers

Construct Structure

Every construct extends the GitHubConstruct base class:

  • name - Unique construct identifier
  • version - Construct version
  • description - Human-readable description
  • validate() - Validates stack configuration
  • describe() - Returns construct metadata
  • synthesize() - Generates workflow content

Next Steps

Now that you have a basic workflow, you can:

1. Add More Actions

dotgithub add actions/setup-python@v5
dotgithub add actions/upload-artifact@v4

2. Create Multiple Workflows

Add more constructs for different workflows:

// Add a deployment construct
export class DeployConstruct extends GitHubConstruct {
  // ... implementation
}

3. Use Configuration

Make your construct configurable:

private readonly configSchema = z.object({
  environment: z.string().default('production'),
  nodeVersion: z.string().default('18')
});

validate(stack: GitHubStack): void {
  this.configSchema.parse(stack.config);
}

4. Add More Jobs

Create complex workflows with multiple jobs:

// Add a build job
new JobConstruct(wf, 'build', {
  'runs-on': 'ubuntu-latest',
  needs: ['test'],
  steps: [
    // ... build steps
  ],
});

Common Patterns

Conditional Steps

const steps = [checkout('Checkout').toStep(), setupNode('Setup Node').toStep()];

if (stack.config.environment === 'production') {
  steps.push(run('Deploy', 'npm run deploy').toStep());
}

Matrix Builds

new JobConstruct(wf, 'test', {
  'runs-on': 'ubuntu-latest',
  strategy: {
    matrix: {
      'node-version': ['16', '18', '20'],
    },
  },
  steps: [
    setupNode('Setup Node', {
      'node-version': '${{ matrix.node-version }}',
    }).toStep(),
  ],
});

Environment Variables

new JobConstruct(wf, 'deploy', {
  'runs-on': 'ubuntu-latest',
  env: {
    NODE_ENV: 'production',
    API_URL: 'https://api.example.com',
  },
  steps: [
    // ... deployment steps
  ],
});

Troubleshooting

Common Issues

  1. TypeScript errors - Ensure your tsconfig.json is configured correctly
  2. Missing actions - Run dotgithub add for any actions you're using
  3. Synthesis errors - Check your construct's synthesize method
  4. Configuration errors - Validate your dotgithub.json syntax

Getting Help

What's Next?