Day 21 of 25
IntermediateAutomation

Day 21 - Create a Reusable Template Repo

Build a GitHub template repository with DevOps best practices baked in for quick project bootstrapping.

December 21, 2025
Challenge
Day 21 - Create a Reusable Template Repo

Description

Every new project requires the same setup: CI/CD, linting, testing, Docker, documentation. Instead of recreating this each time, build a reusable template repository with all best practices included.

Task

Create a GitHub template repository with DevOps best practices.

Requirements:

  • GitHub Actions CI/CD workflows
  • Pre-commit hooks
  • Docker support
  • Documentation templates
  • Testing framework
  • Code quality tools

Target

  • ✅ Template repository created
  • ✅ CI/CD pipeline working
  • ✅ Pre-commit hooks configured
  • ✅ Dockerfile included
  • ✅ README template complete
  • ✅ New projects can use template

Sample App

Repository Structure

project-template/
├── .github/
│   ├── workflows/
│   │   ├── ci.yml
│   │   ├── release.yml
│   │   └── security.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── pull_request_template.md
├── .devcontainer/
│   └── devcontainer.json
├── .vscode/
│   ├── settings.json
│   └── extensions.json
├── docs/
│   ├── ARCHITECTURE.md
│   ├── CONTRIBUTING.md
│   └── DEPLOYMENT.md
├── scripts/
│   ├── setup.sh
│   ├── test.sh
│   └── deploy.sh
├── src/
│   └── index.js
├── tests/
│   └── index.test.js
├── .dockerignore
├── .editorconfig
├── .gitignore
├── .pre-commit-config.yaml
├── Dockerfile
├── docker-compose.yml
├── package.json
├── README.md
├── LICENSE
└── CHANGELOG.md

View Solution

Solution

1. README.md Template

# Project Name

[![CI](https://github.com/username/repo/workflows/CI/badge.svg)](https://github.com/username/repo/actions)
[![License](https://img.shields.io/github/license/username/repo)](LICENSE)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)

> Brief description of what this project does

## Features

- Feature 1
- Feature 2
- Feature 3

## Quick Start

```bash
# Clone the repository
git clone https://github.com/username/repo.git
cd repo

# Install dependencies
npm install

# Run tests
npm test

# Start development server
npm run dev

Prerequisites

  • Node.js >= 20.x
  • Docker (optional)
  • kubectl (for Kubernetes deployment)

Installation

Local Development

# Install dependencies
npm install

# Copy environment variables
cp .env.example .env

# Run the application
npm start

Docker

# Build image
docker build -t myapp:latest .

# Run container
docker run -p 3000:3000 myapp:latest

Kubernetes

# Deploy to Kubernetes
kubectl apply -f k8s/

# Check status
kubectl get pods

Configuration

Environment Variable Description Default
PORT Server port 3000
NODE_ENV Environment development
DATABASE_URL Database connection -

Development

# Run in development mode
npm run dev

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Lint code
npm run lint

# Format code
npm run format

# Build for production
npm run build

Testing

# Unit tests
npm test

# Integration tests
npm run test:integration

# E2E tests
npm run test:e2e

# Coverage report
npm run test:coverage

Deployment

See DEPLOYMENT.md for deployment instructions.

Contributing

Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • Inspiration
  • References
  • Contributors

### 2. CI/CD Workflows

#### .github/workflows/ci.yml

```yaml
name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
      - uses: actions/checkout@v4

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build
        run: npm run build

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        if: matrix.node-version == '20.x'

  docker:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t myapp:test .

      - name: Test Docker image
        run: |
          docker run -d -p 3000:3000 --name test-container myapp:test
          sleep 5
          curl -f http://localhost:3000/health || exit 1
          docker stop test-container

  security:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          format: 'sarif'
          output: 'trivy-results.sarif'

      - name: Upload Trivy results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Dependency audit
        run: npm audit --audit-level=high

.github/workflows/release.yml

name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Create Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false

      - name: Build and push Docker image
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
        run: |
          echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
          docker build -t $DOCKER_USERNAME/myapp:${GITHUB_REF#refs/tags/} .
          docker push $DOCKER_USERNAME/myapp:${GITHUB_REF#refs/tags/}

3. Pre-commit Configuration

.pre-commit-config.yaml

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files
        args: ['--maxkb=1000']
      - id: check-merge-conflict
      - id: detect-private-key

  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.56.0
    hooks:
      - id: eslint
        files: \.[jt]sx?$
        types: [file]
        additional_dependencies:
          - [email protected]
          - [email protected]

  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        files: \.(js|jsx|ts|tsx|json|yaml|yml|md)$

  - repo: local
    hooks:
      - id: tests
        name: run tests
        entry: npm test
        language: system
        pass_filenames: false
        always_run: true

4. Dockerfile

# Multi-stage build
FROM node:20-alpine AS builder

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Build application
COPY . .
RUN npm run build

# Production image
FROM node:20-alpine

WORKDIR /app

# Copy built application
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./

# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001

USER nodejs

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js || exit 1

CMD ["node", "dist/index.js"]

5. Setup Script

scripts/setup.sh

#!/bin/bash

set -euo pipefail

echo "🚀 Setting up development environment..."

# Check prerequisites
command -v node >/dev/null 2>&1 || { echo "❌ Node.js is required but not installed."; exit 1; }
command -v git >/dev/null 2>&1 || { echo "❌ Git is required but not installed."; exit 1; }

# Install dependencies
echo "📦 Installing dependencies..."
npm install

# Setup pre-commit hooks
echo "🔨 Setting up pre-commit hooks..."
pip install pre-commit
pre-commit install

# Copy environment file
if [ ! -f .env ]; then
    echo "📝 Creating .env file..."
    cp .env.example .env
    echo "⚠️  Please update .env with your configuration"
fi

# Run initial tests
echo "🧪 Running tests..."
npm test

echo "✅ Setup complete!"
echo ""
echo "Next steps:"
echo "  1. Update .env with your configuration"
echo "  2. Run 'npm run dev' to start development server"
echo "  3. Visit http://localhost:3000"

6. Package.json

{
  "name": "project-template",
  "version": "1.0.0",
  "description": "DevOps-ready project template",
  "main": "dist/index.js",
  "scripts": {
    "dev": "nodemon src/index.js",
    "start": "node dist/index.js",
    "build": "tsc",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "lint": "eslint src/**/*.{js,ts}",
    "lint:fix": "eslint src/**/*.{js,ts} --fix",
    "format": "prettier --write \"src/**/*.{js,ts,json}\"",
    "format:check": "prettier --check \"src/**/*.{js,ts,json}\"",
    "prepare": "husky install"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/username/project-template.git"
  },
  "keywords": [
    "template",
    "devops",
    "nodejs"
  ],
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "@types/jest": "^29.5.0",
    "@types/node": "^20.0.0",
    "eslint": "^8.56.0",
    "eslint-config-prettier": "^9.1.0",
    "husky": "^8.0.0",
    "jest": "^29.7.0",
    "nodemon": "^3.0.0",
    "prettier": "^3.1.0",
    "typescript": "^5.3.0"
  },
  "dependencies": {
    "express": "^4.18.0",
    "dotenv": "^16.3.0"
  }
}

7. Contributing Guide

docs/CONTRIBUTING.md

# Contributing Guide

## Getting Started

1. Fork the repository
2. Clone your fork: `git clone https://github.com/yourusername/repo.git`
3. Create a branch: `git checkout -b feature/my-feature`
4. Make your changes
5. Run tests: `npm test`
6. Commit: `git commit -am 'Add some feature'`
7. Push: `git push origin feature/my-feature`
8. Create a Pull Request

## Development Setup

```bash
# Run setup script
./scripts/setup.sh

# Start development server
npm run dev

Code Style

  • Follow ESLint rules
  • Run npm run lint before committing
  • Use Prettier for formatting
  • Write meaningful commit messages

Commit Message Format

type(scope): subject

body

footer

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation
  • style: Formatting
  • refactor: Code restructuring
  • test: Tests
  • chore: Maintenance

Pull Request Process

  1. Update README.md with changes
  2. Update CHANGELOG.md
  3. Ensure all tests pass
  4. Get approval from maintainers
  5. Squash commits before merge

Testing

  • Write tests for new features
  • Maintain >80% coverage
  • Run full test suite before PR

Questions?

Create an issue or reach out to maintainers.


## Explanation

### Template Repository Benefits

**Speed:** New projects start in minutes, not hours
**Consistency:** All projects follow same structure
**Quality:** Best practices built-in
**Maintenance:** Update template, all projects benefit

### Key Components

#### 1. CI/CD Pipeline

Push → Lint → Test → Build → Security Scan → Deploy


#### 2. Pre-commit Hooks

Commit Attempt → Hooks Run → Pass/Fail → Commit Allowed


#### 3. Documentation

- README: Overview and quick start
- CONTRIBUTING: How to contribute
- DEPLOYMENT: How to deploy
- ARCHITECTURE: System design

Try to solve the challenge yourself first!

Click "Reveal Solution" when you're ready to see the answer.

Result

Create Template Repository

# Create new repository on GitHub
# Check "Template repository" option

# Clone locally
git clone https://github.com/yourusername/project-template.git
cd project-template

# Add all template files
# (Copy all files from solution above)

# Commit and push
git add .
git commit -m "feat: initial template setup"
git push origin main

Use Template

# Create new project from template on GitHub
# Click "Use this template" button

# Or via CLI
gh repo create my-new-project --template yourusername/project-template

# Clone and setup
git clone https://github.com/yourusername/my-new-project.git
cd my-new-project

# Run setup
./scripts/setup.sh

# Start developing!
npm run dev

Validation

Template Checklist

# 1. Repository is marked as template
# Check on GitHub repository settings

# 2. CI/CD workflows work
git push origin main
# Check GitHub Actions tab

# 3. Pre-commit hooks installed
git commit -m "test"
# Should run hooks

# 4. Docker build works
docker build -t test .
# Should succeed

# 5. Tests pass
npm test
# Should pass

# 6. Documentation complete
ls docs/
# Should have CONTRIBUTING.md, DEPLOYMENT.md, etc.

Best Practices

✅ Do's

  1. Keep template minimal: Only essentials
  2. Document everything: README, CONTRIBUTING, etc.
  3. Automate setup: Provide setup scripts
  4. Test regularly: Ensure template works
  5. Version template: Tag releases
  6. Update dependencies: Keep current

❌ Don'ts

  1. Don't include secrets: Use .env.example
  2. Don't over-engineer: Keep it simple
  3. Don't skip docs: Documentation is key
  4. Don't forget .gitignore: Exclude build artifacts
  5. Don't hardcode values: Use environment variables

Share Your Success

Created a template repo? Share it!

Tag @thedevopsdaily on X with:

  • Template repository URL
  • What's included
  • Time saved per project
  • Number of projects using it

Use hashtags: #AdventOfDevOps #GitHub #Templates #Day21

Ready to complete this challenge?

Mark this challenge as complete once you've finished the task. We'll track your progress!

Completed this challenge? Share your success!

Tag @thedevopsdaily on X (Twitter) and share your learning journey with the community!

Proudly Sponsored By

These amazing companies help us create free, high-quality DevOps content for the community

Want to support DevOps Daily and reach thousands of developers?

Become a Sponsor

Found an issue?