diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bea1011 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,75 @@ +# ============================================================================== +# EditorConfig for {{project_name}} +# https://editorconfig.org +# +# This file enforces consistent coding styles across multiple editors and IDEs. +# It is designed to work out-of-the-box for 95% of standard programming +# environments and aligns with high-quality open-source standards. +# ============================================================================== + +# Top-most EditorConfig file for the project +root = true + +# ------------------------------------------------------------------------------ +# Default Settings (Applies to all files) +# ------------------------------------------------------------------------------ +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +# ------------------------------------------------------------------------------ +# Web, Data, and Frontend (2 spaces) +# ------------------------------------------------------------------------------ +[*.{js,jsx,ts,tsx,vue,json,yml,yaml,toml,html,css,scss,xml}] +indent_style = space +indent_size = 2 + +# ------------------------------------------------------------------------------ +# Python (4 spaces, standard PEP-8) +# ------------------------------------------------------------------------------ +[*.py] +indent_style = space +indent_size = 4 + +# ------------------------------------------------------------------------------ +# Go (Tabs) +# ------------------------------------------------------------------------------ +[*.go] +indent_style = tab + +# ------------------------------------------------------------------------------ +# Rust, C, C++, Java, C# (4 spaces) +# ------------------------------------------------------------------------------ +[*.{rs,c,h,cpp,hpp,java,cs}] +indent_style = space +indent_size = 4 + +# ------------------------------------------------------------------------------ +# Shell Scripts and Docker (2 spaces) +# ------------------------------------------------------------------------------ +[*.{sh,bash}] +indent_style = space +indent_size = 2 + +[{Dockerfile,*.dockerfile}] +indent_style = space +indent_size = 2 + +# ------------------------------------------------------------------------------ +# Makefiles (Must use tabs for indentation) +# ------------------------------------------------------------------------------ +[{Makefile,*.mk}] +indent_style = tab + +# ------------------------------------------------------------------------------ +# Markdown Documents +# ------------------------------------------------------------------------------ +[*.md] +# Markdown allows double spaces at the end of a line for hard line breaks. +trim_trailing_whitespace = false +indent_style = space +indent_size = 2 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..df53bbb --- /dev/null +++ b/.env.example @@ -0,0 +1,154 @@ +# ============================================================================== +# Environment Configuration Template +# ============================================================================== +# INSTRUCTIONS: +# 1. Copy this file and rename it to `.env` (this file is ignored by git). +# 2. Replace the placeholder values with your actual local configuration. +# 3. DO NOT commit actual secrets (passwords, API keys) to version control. +# 4. Use meaningful defaults for development where safe. +# ============================================================================== + +# ------------------------------------------------------------------------------ +# Core Application Settings +# ------------------------------------------------------------------------------ +# Application Environment (e.g., development, staging, production, testing) +APP_ENV=development +# Enable/disable debug mode (verbose logging, stack traces) +APP_DEBUG=true +APP_NAME="{{project_name}}" +APP_VERSION="1.0.0" +# Base URL for the application (useful for generating absolute links, emails) +APP_URL=http://localhost:8080 +# Timezone context for the application +APP_TIMEZONE=UTC +# Default locale/language +APP_LOCALE=en + +# ------------------------------------------------------------------------------ +# Server / Network Configuration +# ------------------------------------------------------------------------------ +# Port the application server listens on +PORT=8080 +APP_PORT=8080 +# Host to bind to (0.0.0.0 for all interfaces, useful in Docker environments) +HOST=0.0.0.0 +# Allowed hosts/CORS origins (comma separated) +CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8080 + +# ------------------------------------------------------------------------------ +# Database Configuration (Relational / SQL) +# ------------------------------------------------------------------------------ +# Connection type (e.g., postgres, mysql, sqlite, mssql) +DB_CONNECTION=postgres +DB_HOST=localhost +DB_PORT=5432 +DB_DATABASE={{project_name}}_dev +DB_USERNAME=admin +DB_PASSWORD=secret +# Database schema (if applicable, e.g., public for postgres) +DB_SCHEMA=public +# Full connection string alternative (often used by ORMs like Prisma or SQLAlchemy) +# DATABASE_URL=postgres://admin:secret@localhost:5432/{{project_name}}_dev + +# ------------------------------------------------------------------------------ +# Cache / Key-Value Store / Message Brokers +# ------------------------------------------------------------------------------ +# Redis configuration +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD=null +REDIS_DB=0 +# REDIS_URL=redis://localhost:6379/0 + +# Memcached configuration +MEMCACHED_HOST=localhost +MEMCACHED_PORT=11211 + +# RabbitMQ / Celery / Message Queue +# RABBITMQ_URL=amqp://guest:guest@localhost:5672/ + +# ------------------------------------------------------------------------------ +# Security & Authentication +# ------------------------------------------------------------------------------ +# Application secret key (used for sessions, cookie signing, CSRF tokens) +APP_SECRET_KEY=your_super_secret_key_change_in_production +# JWT (JSON Web Token) configuration +JWT_SECRET=your_jwt_secret_key +JWT_EXPIRES_IN=86400 # e.g., in seconds (1 day) +# OAuth / Single Sign-On (SSO) generic providers +OAUTH_CLIENT_ID=your_oauth_client_id +OAUTH_CLIENT_SECRET=your_oauth_client_secret + +# ------------------------------------------------------------------------------ +# Email / SMTP Configuration +# ------------------------------------------------------------------------------ +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS=noreply@example.com +MAIL_FROM_NAME="${APP_NAME}" + +# ------------------------------------------------------------------------------ +# Object Storage / Cloud Providers +# ------------------------------------------------------------------------------ +# AWS S3 / MinIO configuration +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false +# AWS_ENDPOINT=http://localhost:9000 # Uncomment for MinIO + +# Google Cloud Platform +# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json +# GCP_PROJECT_ID= + +# ------------------------------------------------------------------------------ +# Observability / Logging / Telemetry +# ------------------------------------------------------------------------------ +# Log level: debug, info, warn, error, fatal +LOG_LEVEL=debug +LOG_FORMAT=json # or text +# Sentry DSN for error tracking +# SENTRY_DSN=https://examplePublicKey@o0.ingest.sentry.io/0 +# Datadog, Prometheus, NewRelic etc. +# DD_API_KEY= +# TELEMETRY_ENABLED=true + +# ------------------------------------------------------------------------------ +# Common Third-Party API Keys (Placeholders) +# ------------------------------------------------------------------------------ +# Stripe / Payment Gateway +# STRIPE_PUBLIC_KEY=pk_test_... +# STRIPE_SECRET_KEY=sk_test_... +# STRIPE_WEBHOOK_SECRET=whsec_... + +# AI / LLM APIs (OpenAI, Anthropic, etc.) +# OPENAI_API_KEY=sk-... +# ANTHROPIC_API_KEY=sk-ant-... + +# ------------------------------------------------------------------------------ +# Frontend / UI Specific Variables +# ------------------------------------------------------------------------------ +# Note: Many frontend frameworks require specific prefixes to expose vars to the client. +# The below variables show how to map backend values to frontend framework standards. +# Next.js: NEXT_PUBLIC_ +# Vite: VITE_ +# Create React App: REACT_APP_ +# Vue/Nuxt: NUXT_PUBLIC_ / VUE_APP_ + +NEXT_PUBLIC_APP_URL=${APP_URL} +NEXT_PUBLIC_API_URL=${APP_URL}/api/v1 +VITE_API_BASE_URL=${APP_URL}/api/v1 +REACT_APP_API_URL=${APP_URL}/api/v1 + +# ------------------------------------------------------------------------------ +# CI/CD & Deployment Flags +# ------------------------------------------------------------------------------ +# Flags to trigger specific build or deployment behaviors in GitHub Actions, GitLab CI, etc. +# CI=true +# SKIP_PREFLIGHT_CHECK=true +# DOCKER_BUILD_TARGET=development diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..85e2639 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,64 @@ +# ============================================================================= +# CODEOWNERS — Automated Review Assignment +# +# GitHub uses this file to automatically request reviews from the designated +# code owners when a pull request modifies files matching a given pattern. +# +# HOW TO USE THIS FILE: +# 1. Replace all placeholder GitHub usernames (e.g., @org/team-name or +# @username) with your actual GitHub team or individual usernames. +# 2. Rules are evaluated from top to bottom. The LAST matching rule wins. +# 3. Patterns follow the same syntax as .gitignore. +# +# REFERENCE: +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +# ============================================================================= + +# ----------------------------------------------------------------------------- +# Default Owner +# Catches all files not matched by a more specific rule below. +# This team or user is the reviewer of last resort. +# ----------------------------------------------------------------------------- +* @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# CI/CD & Infrastructure +# Requires review from a platform/infrastructure team for any workflow changes. +# ----------------------------------------------------------------------------- +.github/ @{{maintainer_username}} +.github/workflows/ @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# Documentation +# Route docs changes to the team responsible for content quality. +# ----------------------------------------------------------------------------- +docs/ @{{maintainer_username}} +*.md @{{maintainer_username}} +mkdocs.yml @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# Security-Sensitive Files +# Any change to security policy, secrets config, or dependencies must be +# reviewed by the security team. +# ----------------------------------------------------------------------------- +SECURITY.md @{{maintainer_username}} +.github/dependabot.yml @{{maintainer_username}} +.pre-commit-config.yaml @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# Core Source Code +# Replace with the path to your primary package directory. +# ----------------------------------------------------------------------------- +src/ @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# Tests +# Requires review from someone responsible for test quality and coverage. +# ----------------------------------------------------------------------------- +tests/ @{{maintainer_username}} + +# ----------------------------------------------------------------------------- +# Container & Deployment +# ----------------------------------------------------------------------------- +Dockerfile @{{maintainer_username}} +docker-compose.yml @{{maintainer_username}} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..52d667e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,75 @@ +name: 🐛 Bug Report +description: Create a report to help us improve {{project_name}} +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug to `{{project_name}}`! + + > [!IMPORTANT] + > If you have found a **security vulnerability**, please refer to our [Security Policy](../SECURITY.md) and do not open a public issue. + + For general help and Q&A, please use [GitHub Discussions](https://github.com/{{organization}}/{{project_name}}/discussions) instead. + + - type: checkboxes + id: checks + attributes: + label: Search before asking + description: Please confirm that you have checked the following before submitting your bug report. + options: + - label: I have searched the [existing issues](https://github.com/{{organization}}/{{project_name}}/issues) and could not find a similar bug. + required: true + - label: I have read the [Official Documentation](https://{{organization}}.github.io/{{project_name}}). + required: true + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is. + placeholder: Tell us what happened... + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: Provide a minimal, reproducible example or the exact steps to reproduce the behavior. + placeholder: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: A clear and concise description of what you expected to happen instead. + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Please provide details about your environment. + value: | + - OS (e.g., Linux, macOS, Windows): + - Language Version (e.g., Python 3.10): + - `{{project_name}}` Version: + - Other relevant dependency versions: + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Relevant Logs or Screenshots + description: If applicable, add screenshots or paste command output/logs to help explain your problem. Please use code blocks (```) to format logs. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..ba7f226 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,45 @@ +name: Feature Request +description: Suggest an idea for {{project_name}} +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to suggest a feature for {{project_name}}! + + Before submitting, please ensure you have searched our existing [Issues](https://github.com/{{organization}}/{{project_name}}/issues) and [Discussions](https://github.com/{{organization}}/{{project_name}}/discussions) to see if this feature has already been requested. + - type: textarea + id: problem + attributes: + label: Is your feature request related to a problem? Please describe. + description: A clear and concise description of what the problem is. + placeholder: "Ex. I'm always frustrated when [...]" + validations: + required: true + - type: textarea + id: solution + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + placeholder: "Ex. I would like an API that allows me to [...]" + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + placeholder: "Ex. I tried using feature X, but it didn't work because [...]" + - type: textarea + id: additional + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. + placeholder: "Add any mockups, log snippets, or other context here..." + - type: checkboxes + id: contribute + attributes: + label: Willingness to contribute + description: Would you be willing to contribute a pull request for this feature? + options: + - label: Yes, I am willing to submit a PR! diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..c3847a5 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,70 @@ + + +## Description + + + +- + +## Type of Change + + + +- [ ] 🐛 Bug fix (non-breaking change which fixes an issue) +- [ ] ✨ New feature (non-breaking change which adds functionality) +- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] 📝 Documentation update (changes to `README.md`, `SUPPORT.md`, docstrings, etc.) +- [ ] 🛠️ Maintenance/Refactoring (non-breaking change that improves code structure or quality) + +## Test Plan + + + +- + +## Related Issues + + + +- Fixes # + +## Screenshots / Visuals (if applicable) + + + +## Use of AI + + + +- [ ] Includes AI-assisted code completion +- [ ] Includes code generated by an AI application +- [ ] Includes AI-generated tests (NOTE: AI written tests should have a docstring that includes `## WRITTEN BY AI ##`) + +## Checklist + +> [!IMPORTANT] +> Please review and complete this checklist before submitting your PR. This helps our maintainers process your contribution faster and ensures it meets the quality standards of `{{project_name}}`. + +- [ ] "I certify that all code in this PR is my own, except as noted below." +- [ ] I have read the [CONTRIBUTING.md](../CONTRIBUTING.md) guide. +- [ ] My code follows the established style guidelines of `{{project_name}}`. +- [ ] I have performed a self-review of my own code. +- [ ] I have commented my code, particularly in hard-to-understand areas. +- [ ] I have made corresponding changes to the documentation. +- [ ] My changes generate no new warnings or errors. +- [ ] I have added tests that prove my fix is effective or that my feature works. +- [ ] New and existing unit tests pass locally with my changes. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8c7cb68 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,100 @@ +# ============================================================================= +# dependabot.yml — Automated Dependency Management +# +# GitHub Dependabot natively creates PRs for outdated dependencies. +# All updates are grouped to minimize PR noise (one PR per ecosystem/week). +# +# Supported ecosystems: +# • github-actions — workflow action version pins +# • pip — Python packages (uncomment if applicable) +# • npm — Node.js packages (uncomment if applicable) +# • docker — Base image tags (uncomment if applicable) +# +# After PRs are opened, weekly.yml surfaces them via Slack for human review. +# ============================================================================= +version: 2 + +updates: + # ── GitHub Actions ────────────────────────────────────────────────────────── + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + timezone: "America/New_York" + # Group all action updates into a single PR to reduce noise + groups: + github-actions-updates: + patterns: + - "*" + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "chore(actions)" + # TODO: Add at least one reviewer here! Without an assigned reviewer, + # Dependabot PRs often rot in the queue and are ignored. + reviewers: [] # e.g., ["maintainer1", "org/platform-team"] + assignees: [] # e.g., ["maintainer1"] + open-pull-requests-limit: 5 + + # ── Python (pip) ──────────────────────────────────────────────────────────── + # Uncomment when this repository contains Python dependencies. + # - package-ecosystem: "pip" + # directory: "/" + # schedule: + # interval: "weekly" + # day: "monday" + # time: "09:00" + # timezone: "America/New_York" + # groups: + # python-dependencies: + # patterns: + # - "*" + # labels: + # - "dependencies" + # - "python" + # commit-message: + # prefix: "chore(deps)" + # open-pull-requests-limit: 5 + + # ── Node.js (npm) ──────────────────────────────────────────────────────────── + # Uncomment when this repository contains a package.json. + # - package-ecosystem: "npm" + # directory: "/" + # schedule: + # interval: "weekly" + # day: "monday" + # time: "09:00" + # timezone: "America/New_York" + # groups: + # npm-dependencies: + # update-types: + # - "minor" + # - "patch" + # npm-major-dependencies: + # update-types: + # - "major" + # labels: + # - "dependencies" + # - "javascript" + # commit-message: + # prefix: "chore(deps)" + # open-pull-requests-limit: 5 + + # ── Docker ─────────────────────────────────────────────────────────────────── + # Uncomment to receive PRs for Dockerfile base image updates. + # - package-ecosystem: "docker" + # directory: "/" + # schedule: + # interval: "weekly" + # day: "monday" + # time: "09:00" + # timezone: "America/New_York" + # labels: + # - "dependencies" + # - "docker" + # commit-message: + # prefix: "chore(docker)" + # open-pull-requests-limit: 3 diff --git a/.github/workflows/_build_container.yml b/.github/workflows/_build_container.yml new file mode 100644 index 0000000..edee836 --- /dev/null +++ b/.github/workflows/_build_container.yml @@ -0,0 +1,71 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _build_container.yml — Reusable Container Builder +# +# Builds container images for the project. This workflow handles only the +# build step. It returns the image name and tag, allowing calling workflows +# to handle pushing, publishing, or vulnerability scanning. +# +# Inputs: +# build_type (required): "release", "post", "nightly", or "dev" +# +# Outputs: +# image_name — The name of the built container image +# image_tag — The tag of the built container image +# +# Callers: development.yml, nightly.yml, release.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Build Container (Reusable)" + +on: + workflow_call: + inputs: + build_type: + description: "Type of build: release, post, nightly, or dev" + required: true + type: string + outputs: + image_name: + description: "The name of the built container image" + value: ${{ jobs.build-container.outputs.image_name }} + image_tag: + description: "The tag of the built container image" + value: ${{ jobs.build-container.outputs.image_tag }} + +permissions: + contents: read + +jobs: + + build-container: + name: "Build Container (${{ inputs.build_type }})" + runs-on: ubuntu-latest + outputs: + image_name: ${{ steps.build.outputs.image_name }} + image_tag: ${{ steps.build.outputs.image_tag }} + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up container toolchain" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Set up Docker, Buildx, or other container tools. + # ─────────────────────────────────────────────────────────────────── + echo "TODO: set up container toolchain" + # exit 1 # Uncomment when enforcing implementation + + - name: "# TODO: Build container" + id: build + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Build the container image. + # Example: docker build -t "my-app:${{ inputs.build_type }}" . + # ─────────────────────────────────────────────────────────────────── + echo "TODO: build container for ${{ inputs.build_type }}" + + IMAGE_NAME="my-app" + IMAGE_TAG="${{ inputs.build_type }}-${{ github.sha }}" + + echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT" + echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" + # exit 1 # Uncomment when enforcing implementation diff --git a/.github/workflows/_build_package.yml b/.github/workflows/_build_package.yml new file mode 100644 index 0000000..754bec7 --- /dev/null +++ b/.github/workflows/_build_package.yml @@ -0,0 +1,86 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _build_package.yml — Reusable Package Builder +# +# Compiles or packages the project. This workflow handles only the build step. +# It returns the directory where the build artifacts are located, allowing +# calling workflows to handle uploading, publishing, or further processing. +# +# Inputs: +# build_type (required): "release", "post", "nightly", or "dev" +# +# Outputs: +# build_location — Path to the directory containing the build output +# build_metadata — Any important metadata about the build (e.g., version, sha256) +# +# Callers: development.yml, nightly.yml, release.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Build Package (Reusable)" + +on: + workflow_call: + inputs: + build_type: + description: "Type of build: release, post, nightly, or dev" + required: true + type: string + outputs: + build_location: + description: "Directory path containing the built artifacts" + value: ${{ jobs.build-package.outputs.location }} + build_metadata: + description: "Metadata regarding the build (e.g. SHA256)" + value: ${{ jobs.build-package.outputs.metadata }} + +permissions: + contents: read + +jobs: + + build-package: + name: "Build Package (${{ inputs.build_type }})" + runs-on: ubuntu-latest + outputs: + location: ${{ steps.build.outputs.location }} + metadata: ${{ steps.build.outputs.metadata }} + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up build toolchain" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Install tools and dependencies for packaging. + # Example (Python): pip install build + # Example (Node.js): npm ci + # ─────────────────────────────────────────────────────────────────── + echo "TODO: set up build toolchain" + # exit 1 # Uncomment when enforcing implementation + + - name: "# TODO: Build package" + id: build + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Compile/package the distributable artifact. + # The output must land in a specific directory (e.g., dist/) + # ─────────────────────────────────────────────────────────────────── + echo "TODO: build project for ${{ inputs.build_type }}" + + # Simulate build output directory creation + mkdir -p dist/ + echo "dummy package content" > dist/dummy.pkg + + # Output the location + echo "location=dist/" >> "$GITHUB_OUTPUT" + + # Optional: compute SHA256 or other metadata + SHA=$(find dist/ -type f | sort | xargs sha256sum | sha256sum | awk '{print $1}') + echo "metadata=${SHA}" >> "$GITHUB_OUTPUT" + # exit 1 # Uncomment when enforcing implementation + + - name: Upload build artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: build-artifact-${{ inputs.build_type }}-${{ github.run_id }} + path: dist/ + retention-days: 7 + if-no-files-found: warn diff --git a/.github/workflows/_docs.yml b/.github/workflows/_docs.yml new file mode 100644 index 0000000..88524db --- /dev/null +++ b/.github/workflows/_docs.yml @@ -0,0 +1,96 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _docs.yml — Reusable Documentation Builder & Deployer +# +# Builds static documentation using MkDocs and Mike for versioning, and +# deploys it to GitHub Pages. +# +# Inputs: +# build_type (required): "dev-branch", "dev", "nightly", "release", or "post" +# alias (required): The alias to use for the deployment (e.g., "latest", "nightly") +# +# Outputs: +# deployed_url — The URL/path where the docs were deployed +# +# Callers: development.yml, nightly.yml, release.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Docs Builder & Deployer (Reusable)" + +on: + workflow_call: + inputs: + build_type: + description: "Deploy target type: dev-branch, dev, nightly, release, or post" + required: true + type: string + alias: + description: "The alias to use for the documentation version (e.g., latest, nightly)" + required: true + type: string + outputs: + deployed_url: + description: "Path where the docs were deployed" + value: ${{ jobs.build-and-deploy-docs.outputs.deployed_url }} + +permissions: + contents: write # Push to gh-pages branch + +jobs: + + build-and-deploy-docs: + name: "Build & Deploy Docs (${{ inputs.build_type }})" + runs-on: ubuntu-latest + outputs: + deployed_url: ${{ steps.dest.outputs.path }} + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.x" + + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email github-actions[bot]@users.noreply.github.com + + - name: Install MkDocs and dependencies + run: | + # Install standard mkdocs, material theme, and mike for versioning + pip install mkdocs-material mike + # Install any other requirements if they exist + if [ -f docs/requirements.txt ]; then pip install -r docs/requirements.txt; fi + + - name: Compute deployment destination path + id: dest + run: | + case "${{ inputs.build_type }}" in + dev-branch) echo "path=pr-${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" ;; + dev) echo "path=dev" >> "$GITHUB_OUTPUT" ;; + nightly) echo "path=nightly" >> "$GITHUB_OUTPUT" ;; + release) echo "path=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" ;; + post) echo "path=post" >> "$GITHUB_OUTPUT" ;; + *) echo "path=${{ inputs.alias }}" >> "$GITHUB_OUTPUT" ;; + esac + + - name: Build and deploy using Mike + run: | + VERSION_PATH="${{ steps.dest.outputs.path }}" + ALIAS="${{ inputs.alias }}" + + # Use mike to deploy to gh-pages branch + # --push: push to origin + # --update-aliases: update the alias pointer + if [ "$ALIAS" != "" ] && [ "$ALIAS" != "$VERSION_PATH" ]; then + mike deploy --push --update-aliases $VERSION_PATH $ALIAS + else + mike deploy --push $VERSION_PATH + fi + + # If release, also set it as default + if [ "${{ inputs.build_type }}" == "release" ]; then + mike set-default --push $ALIAS + fi diff --git a/.github/workflows/_link-check.yml b/.github/workflows/_link-check.yml new file mode 100644 index 0000000..6847222 --- /dev/null +++ b/.github/workflows/_link-check.yml @@ -0,0 +1,65 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _link-check.yml — Reusable Documentation Link Checker +# +# Validates that all hyperlinks in project documentation and Markdown files +# are reachable and not returning errors. +# +# Inputs: +# fail_on_error — whether to fail the workflow on broken links (default: true) +# +# Outputs: +# report_content — The content of the link check report. +# +# Callers: development.yml, nightly.yml, release.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Link Checker (Reusable)" + +on: + workflow_call: + inputs: + fail_on_error: + description: "Fail the workflow if broken links are detected" + required: false + type: boolean + default: true + outputs: + report_content: + description: "The contents of the link check report" + value: ${{ jobs.link-check.outputs.report_content }} + +permissions: + contents: read + +jobs: + + link-check: + name: "Check Links" + runs-on: ubuntu-latest + outputs: + report_content: ${{ steps.read-report.outputs.content }} + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Run lychee link checker + uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2 + id: lychee + with: + args: --verbose --no-progress --accept 200,206,301,302,429 --exclude-loopback --exclude-mail --exclude "\{\{[^}]+\}\}" '**/*.md' + fail: ${{ inputs.fail_on_error }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Read report content + id: read-report + if: always() + run: | + if [ -f "lychee/out.md" ]; then + # Read file into output variable safely + EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) + echo "content<<$EOF" >> "$GITHUB_OUTPUT" + cat lychee/out.md >> "$GITHUB_OUTPUT" + echo "$EOF" >> "$GITHUB_OUTPUT" + else + echo "content=No link errors found." >> "$GITHUB_OUTPUT" + fi diff --git a/.github/workflows/_publish.yml b/.github/workflows/_publish.yml new file mode 100644 index 0000000..93af4e2 --- /dev/null +++ b/.github/workflows/_publish.yml @@ -0,0 +1,52 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _publish.yml — Reusable Artifact Publisher +# +# Handles publishing built artifacts or containers to an artifact repository +# or container registry. +# +# Inputs: +# build_location — Directory path containing the built artifacts (if package) +# build_type — The type of build (e.g., nightly, release) +# +# Callers: nightly.yml, release.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Publish Artifacts (Reusable)" + +on: + workflow_call: + inputs: + build_location: + description: "Directory path containing the built artifacts" + required: false + type: string + default: "" + build_type: + description: "The type of build (e.g., nightly, release)" + required: true + type: string + +permissions: + contents: read + packages: write # To publish to GitHub Container Registry or GitHub Packages + +jobs: + + publish: + name: "Publish (${{ inputs.build_type }})" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Publish artifacts" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Publish artifacts to a registry. + # + # Examples: + # Python (PyPI): twine upload ${{ inputs.build_location }}/* + # Node.js (npm): npm publish + # Container (GHCR): docker push ... + # ─────────────────────────────────────────────────────────────────── + echo "TODO: publish artifacts located in ${{ inputs.build_location }} for build type ${{ inputs.build_type }}" + # exit 1 # Uncomment when enforcing implementation diff --git a/.github/workflows/_quality.yml b/.github/workflows/_quality.yml new file mode 100644 index 0000000..18686bf --- /dev/null +++ b/.github/workflows/_quality.yml @@ -0,0 +1,84 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _quality.yml — Reusable Quality Gate +# +# Encapsulates quality checking, style/lint, and type checking. +# Fails the pipeline if any of these checks fail. +# +# Callers: development.yml, main.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Quality Gate (Reusable)" + +on: + workflow_call: + +permissions: + contents: read + security-events: write + +jobs: + + quality: + name: "Code Quality" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up toolchain" + run: | + echo "TODO: set up toolchain for quality checks" + # exit 1 + + - name: "# TODO: Run quality checks" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Run code quality analysis. + # Example (Python): ruff check . + # Example (Node.js): npm run lint:quality + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run quality checks" + # exit 1 + + style: + name: "Code Style" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up toolchain" + run: | + echo "TODO: set up toolchain for style checks" + # exit 1 + + - name: "# TODO: Run style checks" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Run code formatting checks. + # Example (Python): black --check . + # Example (Node.js): prettier --check . + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run style checks" + # exit 1 + + types: + name: "Type Checking" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up toolchain" + run: | + echo "TODO: set up toolchain for type checks" + # exit 1 + + - name: "# TODO: Run type checks" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Run static type checking. + # Example (Python): mypy . + # Example (Node.js): tsc --noEmit + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run type checks" + # exit 1 diff --git a/.github/workflows/_security.yml b/.github/workflows/_security.yml new file mode 100644 index 0000000..2d2210c --- /dev/null +++ b/.github/workflows/_security.yml @@ -0,0 +1,63 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _security.yml — Reusable Security Audit +# +# Performs dependency vulnerability scanning and secret scanning. +# +# Callers: development.yml, main.yml, nightly.yml, release.yml, weekly.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Security Audit (Reusable)" + +on: + workflow_call: + +permissions: + contents: read + security-events: write # Upload SARIF to GitHub Security tab + +jobs: + + secret-scan: + name: "Secret Scan" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: "# TODO: Run your secret scanner" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Perform a repository secret scan. + # Examples: + # TruffleHog: https://github.com/trufflesecurity/trufflehog + # Gitleaks: https://github.com/gitleaks/gitleaks-action + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run secret scan" + # exit 1 + + dependency-audit: + name: "Dependency Vulnerability Scan" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Run your deep dependency vulnerability scan" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Perform a deep SCA scan of your dependency tree. + # Examples: + # Python: pip install pip-audit && pip-audit --output json -o audit.json + # Node.js: npm audit --json > audit.json + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run SCA dependency audit" + # exit 1 + + - name: Upload SCA results + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: sca-results-${{ github.run_id }} + path: audit.json + retention-days: 30 + if-no-files-found: ignore diff --git a/.github/workflows/_tests.yml b/.github/workflows/_tests.yml new file mode 100644 index 0000000..b263d6b --- /dev/null +++ b/.github/workflows/_tests.yml @@ -0,0 +1,109 @@ +# ───────────────────────────────────────────────────────────────────────────── +# _tests.yml — Reusable Test Runner +# +# Executes the project test suite using specified types and levels. +# +# Inputs: +# test_types (required) — Comma-separated list: smoke, sanity, regression +# test_levels (required) — Comma-separated list: unit, integration, e2e +# generate_coverage (optional) — Generate test coverage report (default: false) +# publish_results (optional) — Upload test results/coverage (default: true) +# retention_days (optional) — Days to retain artifacts (default: 7) +# +# Outputs: +# results_location — Path to the uploaded test results artifact +# coverage_location — Path to the uploaded coverage artifact +# +# Callers: development.yml, main.yml, nightly.yml, release.yml, weekly.yml +# ───────────────────────────────────────────────────────────────────────────── +name: "Test Runner (Reusable)" + +on: + workflow_call: + inputs: + test_matrix: + description: "JSON array of test levels and types (e.g., '[{\"level\": \"unit\", \"types\": \"smoke, sanity\"}]')" + required: true + type: string + generate_coverage: + description: "Generate test coverage report" + required: false + type: boolean + default: false + publish_results: + description: "Publish test results as artifacts" + required: false + type: boolean + default: true + retention_days: + description: "Days to retain test artifacts" + required: false + type: number + default: 7 + outputs: + results_location: + description: "Path to the test results artifact" + value: ${{ jobs.run-tests.outputs.results_location }} + coverage_location: + description: "Path to the coverage artifact" + value: ${{ jobs.run-tests.outputs.coverage_location }} + +permissions: + contents: read + +jobs: + + run-tests: + name: "Run ${{ matrix.level }} Tests" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(inputs.test_matrix) }} + outputs: + results_location: "reports/" + coverage_location: "coverage/" + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: "# TODO: Set up language runtime and test dependencies" + run: | + echo "TODO: set up test environment" + # exit 1 + + - name: "# TODO: Run tests" + run: | + # ─────────────────────────────────────────────────────────────────── + # PLACEHOLDER — Execute the test suite for the requested scope. + # Use inputs to filter what tests run. + # Level: ${{ matrix.level }} + # Types: ${{ matrix.types }} + # Coverage: ${{ inputs.generate_coverage }} + # ─────────────────────────────────────────────────────────────────── + echo "TODO: run tests matching level '${{ matrix.level }}' and types '${{ matrix.types }}'" + + mkdir -p reports/ coverage/ + echo "dummy report" > reports/test-report.xml + if [ "${{ inputs.generate_coverage }}" == "true" ]; then + echo "dummy coverage" > coverage/coverage.xml + fi + # exit 1 + + - name: Upload test results + if: ${{ inputs.publish_results }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: test-results-${{ matrix.level }}-${{ github.run_id }} + path: reports/ + retention-days: ${{ inputs.retention_days }} + if-no-files-found: warn + + - name: Upload coverage report + if: ${{ inputs.publish_results && inputs.generate_coverage }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: coverage-report-${{ matrix.level }}-${{ github.run_id }} + path: coverage/ + retention-days: ${{ inputs.retention_days }} + if-no-files-found: warn diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml new file mode 100644 index 0000000..6e0c8c8 --- /dev/null +++ b/.github/workflows/development.yml @@ -0,0 +1,94 @@ +# ============================================================================= +# development.yml — PR CI +# +# Triggers: +# pull_request → main +# +# Stage 1 — Quality & Security +# Stage 2 — Tests (Unit & Integration) +# Stage 3 — Docs (Conditional on changes) +# Stage 4 — Build Package +# Stage 5 — Comment on PR +# ============================================================================= +name: "CI — Development" + +on: + pull_request: + branches: + - main + +concurrency: + group: "dev-${{ github.head_ref }}" + cancel-in-progress: true + +permissions: + contents: read + +jobs: + + # ── Determine Changes ────────────────────────────────────────────────────── + changes: + name: "Detect Changes" + runs-on: ubuntu-latest + outputs: + docs: ${{ steps.filter.outputs.docs }} + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Check for docs changes + uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3 + id: filter + with: + filters: | + docs: + - 'docs/**' + - 'mkdocs.yml' + + # ── Stage 1: Quality & Security ──────────────────────────────────────────── + quality: + name: "Quality Gate" + uses: ./.github/workflows/_quality.yml + permissions: + contents: read + security-events: write + + security: + name: "Security Audit" + uses: ./.github/workflows/_security.yml + permissions: + contents: read + security-events: write + + # ── Stage 2: Tests ───────────────────────────────────────────────────────── + tests: + name: "Run Tests" + uses: ./.github/workflows/_tests.yml + with: + test_matrix: >- + [ + {"level": "unit", "types": "smoke, sanity"}, + {"level": "integration", "types": "smoke"} + ] + generate_coverage: true + publish_results: true + retention_days: 7 + + # ── Stage 3: Docs (Conditional) ──────────────────────────────────────────── + docs: + name: "Build & Deploy Docs" + needs: changes + if: needs.changes.outputs.docs == 'true' && github.event.pull_request.head.repo.fork == false + uses: ./.github/workflows/_docs.yml + permissions: + contents: write + with: + build_type: "dev-branch" + alias: "pr-${{ github.event.pull_request.number }}" + + # ── Stage 4: Build ───────────────────────────────────────────────────────── + build: + name: "Build Package" + uses: ./.github/workflows/_build_package.yml + with: + build_type: "dev" + diff --git a/.github/workflows/development_cleanup.yml b/.github/workflows/development_cleanup.yml new file mode 100644 index 0000000..d3e0f0d --- /dev/null +++ b/.github/workflows/development_cleanup.yml @@ -0,0 +1,49 @@ +# ============================================================================= +# development_cleanup.yml — PR Documentation Cleanup +# +# Triggers: +# pull_request → closed (merged or abandoned) +# +# Purpose: +# Deletes the ephemeral documentation preview deployed to GitHub Pages +# during the PR lifecycle (e.g., pr-123/) to prevent gh-pages branch bloat. +# ============================================================================= +name: "CI — Development Cleanup" + +on: + pull_request: + types: [closed] + +permissions: + contents: write # Required to push deletion to gh-pages + +jobs: + + cleanup-pr-docs: + name: "Delete PR Docs Preview" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.x" + + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config user.email github-actions[bot]@users.noreply.github.com + + - name: Install Mike + run: pip install mike + + - name: Delete PR docs preview + run: | + PR_PATH="pr-${{ github.event.pull_request.number }}" + echo "Deleting docs preview at path: ${PR_PATH}" + # Delete the versioned path from gh-pages; ignore errors if it doesn't exist + mike delete --push "${PR_PATH}" || echo "No docs preview found for ${PR_PATH}, nothing to clean up." diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..aa54d28 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,60 @@ +# ============================================================================= +# main.yml — Post-Merge CI +# +# Triggers: +# push → main +# +# Stage 1 — Quality Gate & Security Audit +# Stage 2 — Tests (Unit, Integration, E2E) +# Stage 3 — Documentation (dev) +# ============================================================================= +name: "CI — Main" + +on: + push: + branches: + - main + +concurrency: + group: "main-${{ github.ref_name }}" + cancel-in-progress: true + +permissions: + contents: write + security-events: write + actions: read + +jobs: + + # ── Stage 1: Quality Gate & Security ─────────────────────────────────────── + quality: + name: "Quality Gate" + uses: ./.github/workflows/_quality.yml + + security: + name: "Security Audit" + uses: ./.github/workflows/_security.yml + + # ── Stage 2: Tests ───────────────────────────────────────────────────────── + tests: + name: "Run Tests" + uses: ./.github/workflows/_tests.yml + with: + test_matrix: >- + [ + {"level": "unit", "types": "smoke, sanity"}, + {"level": "integration", "types": "smoke, sanity"}, + {"level": "e2e", "types": "smoke"} + ] + generate_coverage: true + publish_results: true + retention_days: 14 + + # ── Stage 3: Documentation ───────────────────────────────────────────────── + docs: + name: "Build & Deploy Docs" + needs: quality + uses: ./.github/workflows/_docs.yml + with: + build_type: "dev" + alias: "latest" diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..379e23e --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,72 @@ +# ============================================================================= +# nightly.yml — The Deep Dive +# +# Trigger: Cron 00:00 UTC daily + manual workflow_dispatch +# Purpose: Extended regression, security SCA, alpha build, docs & publish +# ============================================================================= +name: "CI — Nightly Deep Dive" + +on: + schedule: + - cron: "0 0 * * *" # 00:00 UTC daily + workflow_dispatch: + +permissions: + contents: write + packages: write + security-events: write + actions: read + +jobs: + + # ── Stage 1: Security Audit ──────────────────────────────────────────────── + security: + name: "Security Audit" + uses: ./.github/workflows/_security.yml + + # ── Stage 2: Extended Test Suite ─────────────────────────────────────────── + test: + name: "Extended Tests" + uses: ./.github/workflows/_tests.yml + with: + test_matrix: >- + [ + {"level": "unit", "types": "smoke, sanity, regression"}, + {"level": "integration", "types": "smoke, sanity"}, + {"level": "e2e", "types": "smoke, sanity"} + ] + generate_coverage: true + publish_results: true + retention_days: 14 + + # ── Stage 3: Link Check ──────────────────────────────────────────────────── + link-check: + name: "Link Check" + uses: ./.github/workflows/_link-check.yml + with: + fail_on_error: false + + # ── Stage 4: Alpha Docs ──────────────────────────────────────────────────── + docs: + name: "Nightly Docs" + uses: ./.github/workflows/_docs.yml + with: + build_type: "nightly" + alias: "nightly" + + # ── Stage 5: Alpha Build ─────────────────────────────────────────────────── + build: + name: "Nightly Build" + needs: [test, security] + uses: ./.github/workflows/_build_package.yml + with: + build_type: "nightly" + + # ── Stage 6: Publish Artifacts ───────────────────────────────────────────── + publish: + name: "Publish Nightly" + needs: build + uses: ./.github/workflows/_publish.yml + with: + build_type: "nightly" + build_location: "dist/" diff --git a/.github/workflows/pr_comment.yml b/.github/workflows/pr_comment.yml new file mode 100644 index 0000000..ca52d05 --- /dev/null +++ b/.github/workflows/pr_comment.yml @@ -0,0 +1,66 @@ +# ============================================================================= +# pr_comment.yml — Safe PR Commenting +# +# Triggers: +# workflow_run → CI — Development (completed) +# +# Resolves the GitHub Actions fork permission issue. Workflows triggered +# via `pull_request` from a fork do not have `write` permissions to post +# comments. `workflow_run` executes in the context of the base repository. +# ============================================================================= +name: "PR Commenter" + +on: + workflow_run: + workflows: ["CI — Development"] + types: + - completed + +permissions: + pull-requests: write + actions: read + +jobs: + post_comment: + name: "Post PR Status Comment" + runs-on: ubuntu-latest + if: > + github.event.workflow_run.event == 'pull_request' + steps: + - name: "Download PR Number Artifact" + # Wait, how does it know the PR number? The `development.yml` needs to upload the PR number as an artifact + # so this workflow can read it. Let's write the script to find the PR associated with the commit. + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 + with: + script: | + const workflowRun = context.payload.workflow_run; + + // Get the pull request associated with the commit + const response = await github.rest.search.issuesAndPullRequests({ + q: `is:pr repo:${context.repo.owner}/${context.repo.repo} sha:${workflowRun.head_sha}` + }); + + if (response.data.total_count === 0) { + console.log('No PR found for this commit.'); + return; + } + + const prNumber = response.data.items[0].number; + const runUrl = workflowRun.html_url; + const status = workflowRun.conclusion; + + let body = `## CI Development Pipeline Status\n\n`; + + if (status === 'success') { + body += `✅ **Pipeline**: Completed successfully. [View Run Details](${runUrl})\n`; + } else { + body += `❌ **Pipeline**: Failed or was cancelled. [Check logs](${runUrl})\n`; + } + + // Post comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: body + }); diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..eb22b77 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,75 @@ +# ============================================================================= +# release.yml — The Gold Master +# +# Trigger: Push of a version tag matching v*.*.* +# Purpose: Final verification, immutable build, versioned docs, release publish +# ============================================================================= +name: "CI — Release Gold Master" + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" # Strict semver: v1.2.3 + - "v[0-9]+.[0-9]+.[0-9]+-*" # Pre-releases: v1.2.3-rc.1 + +permissions: + contents: write + packages: write + id-token: write + security-events: write + attestations: write + +jobs: + + # ── Stage 1: Security Audit ──────────────────────────────────────────────── + security: + name: "Security Audit" + uses: ./.github/workflows/_security.yml + + # ── Stage 2: Link Check ──────────────────────────────────────────────────── + link-check: + name: "Link Check" + uses: ./.github/workflows/_link-check.yml + with: + fail_on_error: true + + # ── Stage 3: Full Verification ───────────────────────────────────────────── + test: + name: "Full Verification Suite" + uses: ./.github/workflows/_tests.yml + with: + test_matrix: >- + [ + {"level": "unit", "types": "smoke, sanity, regression"}, + {"level": "integration", "types": "smoke, sanity, regression"}, + {"level": "e2e", "types": "smoke, sanity, regression"} + ] + generate_coverage: true + publish_results: true + retention_days: 90 + + # ── Stage 4: Versioned Docs ──────────────────────────────────────────────── + docs: + name: "Versioned Docs" + uses: ./.github/workflows/_docs.yml + with: + build_type: "release" + alias: "${{ github.ref_name }}" + + # ── Stage 5: Immutable Build ─────────────────────────────────────────────── + build: + name: "Release Build" + needs: [test, security] + uses: ./.github/workflows/_build_package.yml + with: + build_type: "release" + + # ── Stage 6: Publish Artifacts ───────────────────────────────────────────── + publish: + name: "Publish Release" + needs: build + uses: ./.github/workflows/_publish.yml + with: + build_type: "release" + build_location: "dist/" + diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml new file mode 100644 index 0000000..e2279a7 --- /dev/null +++ b/.github/workflows/weekly.yml @@ -0,0 +1,38 @@ +# ============================================================================= +# weekly.yml — The Janitor +# +# Trigger: Cron 00:00 UTC every Sunday + manual workflow_dispatch +# Purpose: Dependency hygiene, full test suite regression. +# ============================================================================= +name: "CI — Weekly Housekeeping" + +on: + schedule: + - cron: "0 0 * * 0" # 00:00 UTC every Sunday + workflow_dispatch: # Allow manual trigger + +permissions: + contents: read + security-events: write + +jobs: + + # ── Stage 1: Security Audit ──────────────────────────────────────────────── + security: + name: "Security Audit" + uses: ./.github/workflows/_security.yml + + # ── Stage 2: Full Test Suite ─────────────────────────────────────────────── + test: + name: "Full Verification Suite" + uses: ./.github/workflows/_tests.yml + with: + test_matrix: >- + [ + {"level": "unit", "types": "smoke, sanity, regression"}, + {"level": "integration", "types": "smoke, sanity, regression"}, + {"level": "e2e", "types": "smoke, sanity, regression"} + ] + generate_coverage: true + publish_results: true + retention_days: 14 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01f7d8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,354 @@ +# ============================================================================== +# Operating Systems +# ============================================================================== + +# macOS +.DS_Store +.AppleDouble +.LSOverride +Icon +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +[Dd]esktop.ini +$RECYCLE.BIN/ +*.lnk + +# Linux +.Trash-* +*~ + +# ============================================================================== +# IDEs and Editors +# ============================================================================== + +# JetBrains (IntelliJ, PyCharm, WebStorm, CLion, etc.) +.idea/ +.idea_modules/ +*.iml +*.iws +*.ipr +out/ +cmake-build-*/ +.run/ + +# VS Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace +.history/ + +# Eclipse +.project +.classpath +.cproject +.settings/ +.metadata/ +bin/ + +# Vim / Emacs / Sublime Text +*~ +*.swp +*.swo +.sconsign.dblite +*.sublime-workspace +*.sublime-project +\#*\# +.\#* + +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ +*.xccheckout +*.moved-aside +DerivedData/ +*.hmap +*.ipa +*.xcuserstate + +# Android Studio +.navigation/ +captures/ +*.apk +*.ap_ +*.dex + +# ============================================================================== +# Environments and Secrets +# ============================================================================== +.env +.env.local +.env.development.local +.env.test.local +.env.production.local +.env.development +.env.test +.env.production +.env.staging +.env.secret +.env.override +.env.backup +.env.*.local +*.pem +*.key +*.cert +*.p12 +*.pfx + +# ============================================================================== +# Logs, Caches, and Coverage +# ============================================================================== +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +.cache/ +.eslintcache +.stylelintcache +.npm/ +coverage/ +.nyc_output/ +.coverage +.coverage.* +coverage.xml +htmlcov/ +*.cover +*.py,cover + +# ============================================================================== +# Programming Languages +# ============================================================================== + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +.tox/ +.nox/ +.hypothesis/ +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +profile_default/ +ipython_config.py +*.ipynb_checkpoints/ +pip-log.txt +pip-delete-this-directory.txt +.venv/ +venv/ +env/ +ENV/ +virtualenv/ +.virtualenv/ +# Pipfile.lock # Note: Often committed for reproducible builds +# poetry.lock # Note: Often committed for reproducible builds + +# Node.js / JavaScript / TypeScript +node_modules/ +jspm_packages/ +.yarn/ +!.yarn/cache +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions +.pnp.* +out-tsc/ +.tsbuildinfo + +# Java / Kotlin / Maven / Gradle +*.class +*.jar +*.war +*.ear +*.nar +target/ +.mtj.tmp/ +hs_err_pid* +replay_pid* +.gradle/ +*.versionsBackup + +# C / C++ / C# +*.o +*.obj +*.out +*.app +*.i*86 +*.x86_64 +*.hex +*.exe +*.dll +*.dylib +*.suo +*.user +*.userosscache +*.sln.docstates +Debug/ +Release/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Rust +# target/ (Moved to avoid conflict with Java target/ if in same dir, but fine to ignore twice) +**/*.rs.bk +# Cargo.lock # Note: Cargo.lock should typically be committed for executables + +# Go +# bin/ (handled globally or below) +# pkg/ (handled globally or below) +vendor/ +*.test +*.prof + +# Ruby +*.gem +.bundle/ +vendor/bundle +lib/bundler/man/ + +# PHP +.phpunit.result.cache + +# Swift / Objective-C +.build/ +Packages/ +Package.pins +Package.resolved +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata + +# Dart / Flutter +.dart_tool/ +.packages +.pub-cache/ +.pub/ + +# ============================================================================== +# Frameworks & Web Dev +# ============================================================================== + +# Next.js +.next/ + +# Nuxt.js / Vue +.nuxt/ +.output/ + +# Gatsby / Jekyll / Hugo / Docusaurus +_site/ +.docusaurus/ + +# ============================================================================== +# Infrastructure, DevOps & CI/CD +# ============================================================================== + +# Terraform +.terraform/ +*.tfstate +*.tfstate.* +crash.log +crash.*.log +*.tfvars +*.tfvars.json +override.tf +override.tf.json +*_override.tf +*_override.tf.json +.terraformrc +terraform.rc + +# Serverless & Cloud +.serverless/ +.aws-sam/ +cdk.out/ +.pulumi/ + +# Docker & Vagrant +.vagrant/ +*.box + +# Ansible +*.retry + +# ============================================================================== +# Miscellaneous +# ============================================================================== +# SQLite +*.sqlite +*.sqlite3 +*.db +*.db-shm +*.db-wal + +# Build artifacts and archives +*.zip +*.tar.gz +*.rar +*.7z +*.gz +*.bz2 + +# Machine Learning / Data Science +*.csv +*.dat +*.seed + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..a2c20ce --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,59 @@ +# AGENTS.md — AI Agent & Coding Assistant Guide + +> **This file provides repository-specific instructions to AI coding agents** (e.g., OpenAI Codex, GitHub Copilot, Gemini, Claude, Cursor). +> Human contributors should refer to [DEVELOPING.md](DEVELOPING.md). + +## Project Context + +**`{{project_name}}`** is a production-ready Apache 2.0 template repository for bootstrapping modern software projects. +**Primary language:** `` +**Package manager:** `` + +## Critical Constraints + +> [!CAUTION] +> 1. **Never commit secrets.** Do not add API keys, tokens, or credentials anywhere. +> 2. **Do not modify `LICENSE` or `NOTICE`.** These are legally binding. +> 3. **Do not modify workflow trigger conditions** without human review. +> 4. **All new source files must include the Apache 2.0 copyright header.** +> 5. **Use `{{double_braces}}` for template placeholders.** Never hard-code them. + +## Repository Layout + +- `.github/workflows/`: CI/CD pipelines. Files prefixed with `_` are reusable templates. +- `docs/`: MkDocs Material source. +- `src/`: Primary application source code. +- `tests/`: Organized into `unit/`, `integration/`, and `e2e/`. + +## Executable Commands + +- **Linting:** `` +- **Testing:** `` +- **Docs:** `mkdocs serve` / `mkdocs build` +- **Build:** `` + +## Code Style & Patterns + +- **No magic strings or numbers** — define constants. +- **Prefer explicit over implicit.** +- **One responsibility per module.** +- Every public function, class, and module must have a docstring. +- Follow [Conventional Commits](https://www.conventionalcommits.org/). + +## GitHub Actions Workflows + +- **Reusable Templates (`_*.yml`):** Never trigger directly. Ensure changes are backward-compatible. +- **Lifecycle:** + - `development.yml`: PR open/sync (unit + smoke) + - `main.yml`: Push to `main` (unit + integration + sanity) + - `nightly.yml`, `weekly.yml`, `release.yml`: Standard scheduled/release flows. + +## Documentation + +- **`docs/`** and **`mkdocs.yml`** control the site. Do not create docs outside the `nav:` tree. +- `docs/index.md` dynamically includes `README.md` via MkDocs snippets. +- Use `{{placeholder}}` variables for templated fields (e.g., `{{project_name}}`, `{{organization}}`). + +## Agent Notes + +_Add notes here when updating instructions for AI agents._ diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000..8b57e90 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,22 @@ +# This CITATION.cff file was generated from a template. +# Update the placeholders below with your project's specific details. +# For more information on the CFF format, see: https://citation-file-format.github.io/ + +cff-version: 1.2.0 +title: "{{project_name}}" +message: "If you use this software, please cite it as below." +type: software +version: "{{version}}" +date-released: "{{date_released}}" +license: Apache-2.0 + +# You can list individual authors or an organization. +# This defaults to the organization to match the README's BibTeX. +authors: + - name: "{{organization}}" +# - family-names: "{{author_family_name}}" +# given-names: "{{author_given_name}}" +# orcid: "https://orcid.org/{{orcid}}" + +repository-code: "https://github.com/{{organization}}/{{project_name}}" +url: "https://{{organization}}.github.io/{{project_name}}" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..6fd9a98 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,100 @@ +# Code of Conduct for `{{project_name}}` + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +> [!IMPORTANT] +> Instances of abusive, harassing, or otherwise unacceptable behavior may be +> reported to the community leaders responsible for enforcement by contacting +> **conduct@{{organization}}.com**. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +| Level | Community Impact | Consequence | +| :--- | :--- | :--- | +| **1. Correction** | Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. | A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. | +| **2. Warning** | A violation through a single incident or series of actions. | A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. | +| **3. Temporary Ban** | A serious violation of community standards, including sustained inappropriate behavior. | A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. | +| **4. Permanent Ban** | Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. | A permanent ban from any sort of public interaction within the community. | + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available +at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..08fff53 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# Contributing to {{project_name}} + +First off, thank you for considering contributing to `{{project_name}}`! It's people like you that make this project great. + +## Code of Conduct + +By participating in this project, you are expected to uphold our [Code of Conduct](CODE_OF_CONDUCT.md). Please report any unacceptable behavior to the project team. + +## Security Vulnerabilities + +> [!IMPORTANT] +> **Please do not report security vulnerabilities through public GitHub issues.** + +If you discover a security issue, please refer to our [Security Policy](SECURITY.md) for instructions on how to safely report it. + +## How Can I Contribute? + +There are many ways to contribute to `{{project_name}}`, and not all of them involve writing code: + +- **Reporting Bugs:** Help us improve by submitting detailed bug reports via our issue tracker. +- **Suggesting Features:** Propose new features or enhancements that could benefit the project. +- **Improving Documentation:** Fix typos, add examples, or write new guides. +- **Writing Code:** Fix bugs, implement features, or improve performance. +- **Helping Others:** Answer questions in [Discussions](https://github.com/{{organization}}/{{project_name}}/discussions) or issue comments. + +For general questions and help, please see [SUPPORT.md](SUPPORT.md). + +## Contributing Code + +If you are contributing code, please follow these structured steps: + +### 1. Development Setup + +Before you start coding, please refer to our [Development Guide](DEVELOPING.md) (`DEVELOPING.md`) for detailed instructions on: +- Setting up your local environment +- Installing dependencies +- Running the test suite +- Code formatting and linting standards + +### 2. Finding an Issue + +- Look for issues tagged with `good first issue` or `help wanted` if you are a new contributor. +- If you plan to work on a major feature, please open an issue or discussion first to talk it over with the maintainers. + +### 3. Making Changes + +1. **Fork the Repository:** Fork the `{{project_name}}` repository to your GitHub account. +2. **Create a Branch:** Create a new branch from `main` for your work (e.g., `git checkout -b feat/add-new-feature`). +3. **Write Code:** Implement your changes, adhering to the project's coding standards. +4. **Write Tests:** Add unit tests or integration tests for your changes to ensure stability. +5. **Run Tests:** Ensure all tests and linters pass locally before committing. + +### 4. Committing Your Changes + +- Write clear, concise commit messages. +- We recommend using [Conventional Commits](https://www.conventionalcommits.org/) (e.g., `feat: add support for X`, `fix: resolve issue with Y`). +- If you are adding a new file, please include the appropriate Apache 2.0 copyright and license header at the top. + +### 5. Submitting a Pull Request + +1. **Push your branch:** `git push origin your-branch-name`. +2. **Open a Pull Request:** Open a PR against the `main` branch of the upstream repository. +3. **Fill out the PR Template:** Provide a clear description of your changes, link to any relevant issues (e.g., `Closes #123`), and complete any required checklists. +4. **Pass CI:** Ensure all GitHub Actions CI checks pass. +5. **Review:** Address any feedback from the maintainers. Once approved and checks pass, a maintainer will merge your PR. + +## Licensing + +By contributing to `{{project_name}}`, you agree that your contributions will be licensed under its [Apache 2.0 License](LICENSE). diff --git a/DEVELOPING.md b/DEVELOPING.md new file mode 100644 index 0000000..fd1ada5 --- /dev/null +++ b/DEVELOPING.md @@ -0,0 +1,179 @@ +# Developing `{{project_name}}` + +This guide provides instructions for setting up your development environment, navigating the project structure, and adhering to our coding standards. + +## Prerequisites + +Ensure your system meets the following requirements before getting started: + +- **[Docker](https://docs.docker.com/get-docker/)** (Recommended for isolated environments) +- **[Git](https://git-scm.com/)** (Version control) +- + +> [!NOTE] +> We strongly recommend using our Docker setup to ensure your local environment exactly matches our CI/CD pipelines. + +## Quick Start (Docker) + +> [!IMPORTANT] +> The `Dockerfile` and `docker-compose.yml` files included in this template are **placeholders** that must be filled in for your specific language stack before they are usable. The default `CMD` in both files will exit with an error if run without modification. +> +> Once implemented, you can spin up the development environment with: +> ```bash +> git clone https://github.com/{{organization}}/{{project_name}}.git +> cd {{project_name}} +> +> # Build and start the development environment in the background +> docker-compose up -d --build +> ``` + +To view the logs of your running containers: +```bash +docker-compose logs -f +``` + +## Local Setup + +If you prefer to develop directly on your host machine, follow the steps for your language stack. + +> [!NOTE] +> **A note on shared tooling:** This project uses [MkDocs](https://www.mkdocs.org/) for documentation. MkDocs requires Python, regardless of your application's primary language. Install it once globally or in a dedicated virtual environment using `docs/requirements.txt`. + +### Python + +```bash +# 1. Create and activate a virtual environment +python -m venv .venv +source .venv/bin/activate # Windows: .venv\Scripts\activate + +# 2. Install the package and development dependencies +pip install -e ".[dev]" + + +``` + +### Node.js / TypeScript + +```bash +# 1. Install all dependencies (uses lockfile for reproducibility) +npm ci + + +``` + +### Go + +```bash +# 1. Download module dependencies +go mod download + + +``` + +### Rust + +```bash +# 1. All dependencies are managed by Cargo automatically +cargo build + + +``` + +## Running Tests + +We maintain strict testing standards. Our tests are located in the `tests/` directory and are categorized by tier. + +| Test Tier | Directory | Description | +| :--- | :--- | :--- | +| **Unit** | `tests/unit/` | Fast, isolated tests for individual functions and classes. | +| **Integration** | `tests/integration/` | Slower tests that verify interactions between multiple components. | +| **End-to-End** | `tests/e2e/` | Full-stack tests simulating real user workflows. | + +Replace the commands below with those appropriate for your language stack: + +```bash +# Python (pytest) +pytest tests/unit/ +pytest tests/integration/ +pytest tests/ # full suite with coverage +pytest tests/ --cov=src --cov-report=xml + +# Node.js (Jest) +npx jest tests/unit/ +npx jest --ci --coverage + +# Go +go test ./tests/unit/... +go test ./... + +# Rust +cargo test --lib # unit tests +cargo test --test '*' # integration tests +``` + +## Code Quality and Formatting + +We use opinionated formatters and linters to maintain consistency. + +- **Formatters & Linters:** We enforce code quality through CI/CD pipelines. Please refer to your language-specific guidelines for setting up local linting. + +> [!TIP] +> **IDE Configuration:** We highly recommend configuring your editor (e.g., VSCode, IntelliJ) to format on save using the project's formatting tools. For VSCode, ensure you have the relevant extensions installed and check `.vscode/settings.json` if available. + +## Git Workflow & Branching + +We follow a structured branching strategy to maintain a clean git history. + +1. **Branch Naming:** + - Feature branches: `feature/short-description` + - Bug fixes: `bugfix/short-description` + - Documentation: `docs/short-description` + +2. **Commit Messages:** + We encourage following [Conventional Commits](https://www.conventionalcommits.org/). + - `feat: add new user endpoint` + - `fix: resolve crash on startup` + - `docs: update developing guide` + +3. **Pull Requests:** + - Push your branch to the remote repository. + - Open a Pull Request against the `main` branch. + - Ensure all CI checks (tests, linters) pass. + - Request a review from at least one core maintainer. + +## CI/CD Architecture + +This repository uses a modular, standardized GitHub Actions architecture. Workflows are divided into core lifecycle events and reusable helper templates. + +### Lifecycle Workflows + +| Workflow | Trigger | Purpose | +| :--- | :--- | :--- | +| **Development** (`development.yml`) | Pull Request to `main` | Runs quality gates, security audits, unit/integration tests, and builds documentation previews. Blocks merges if checks fail. | +| **Main** (`main.yml`) | Push to `main` | Post-merge validation. Runs unit/integration/e2e tests, quality/security checks, and updates the `latest` documentation. | +| **Nightly** (`nightly.yml`) | Cron (Daily 00:00 UTC) | Runs extended regression tests, alpha builds, nightly documentation deployment, and deeper security analysis. | +| **Release** (`release.yml`) | Push of `v*.*.*` tag | Performs full verification, builds immutable release packages, versioned documentation, and publishes artifacts. | +| **Weekly** (`weekly.yml`) | Cron (Sun 00:00 UTC) | Conducts dependency hygiene and full test suite regression to catch configuration drift. | + +### PR Feedback & Cleanup + +- **Safe PR Commenting:** The `pr_comment.yml` workflow uses `workflow_run` to securely post CI status comments on pull requests, circumventing write permission limits on forks. +- **Environment Cleanup:** When a PR is closed or merged, `development_cleanup.yml` automatically removes ephemeral documentation environments and artifacts to maintain a clean workspace. + +### Reusable Templates + +Our pipelines rely on modular templates located in `.github/workflows/_*.yml` (e.g., `_tests.yml`, `_quality.yml`, `_docs.yml`, `_security.yml`, `_build_package.yml`). This ensures testing granularity and linting rules remain perfectly consistent across all stages of the software lifecycle. + +## Building Documentation + +Our documentation is built using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). To preview documentation changes locally: + +```bash +# Install docs dependencies (if not already installed) +pip install mkdocs-material + +# Serve documentation on http://127.0.0.1:8000 with hot-reload +mkdocs serve +``` + +For further assistance, please refer to our [SUPPORT.md](SUPPORT.md). diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f92bc16 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,81 @@ +# --------------------------------------------------------- +# {{project_name}} Dockerfile +# Licensed under the Apache License, Version 2.0 +# --------------------------------------------------------- +# Standardized Multi-stage Dockerfile Template + +# --------------------------------------------------------- +# Build Stage +# --------------------------------------------------------- +# Choose an appropriate base image for building (e.g., ubuntu, alpine, node, golang) +FROM ubuntu:24.04 AS builder + +# Set working directory +WORKDIR /app + +# Install system build dependencies (if any) +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# --------------------------------------------------------- +# [DEPENDENCIES] +# Copy package manifests (package.json, Cargo.toml, go.mod, etc.) +# and install dependencies to leverage Docker layer caching. +# Example: +# COPY package*.json ./ +# RUN npm ci +# --------------------------------------------------------- + +# Copy application source code +COPY src/ ./src/ + +# --------------------------------------------------------- +# [BUILD] +# Run your compilation or build step here. +# Example: +# RUN npm run build +# RUN make build +# --------------------------------------------------------- + +# --------------------------------------------------------- +# Runtime Stage +# --------------------------------------------------------- +# Choose a minimal base image for runtime (e.g., ubuntu, alpine, distroless) +FROM ubuntu:24.04 + +# OCI Standard Labels +LABEL org.opencontainers.image.title="{{project_name}}" +LABEL org.opencontainers.image.description="Production-ready application container" +LABEL org.opencontainers.image.licenses="Apache-2.0" +LABEL org.opencontainers.image.source="https://github.com/{{organization}}/{{project_name}}" + +# Define environment variables +ENV APP_ENV=production + +# Set working directory +WORKDIR /app + +# Create a non-root user and set permissions +RUN useradd -m appuser && chown -R appuser /app + +# --------------------------------------------------------- +# [RUNTIME_ARTIFACTS] +# Copy necessary built artifacts from the builder stage. +# Example: +# COPY --from=builder --chown=appuser:appuser /app/dist ./dist +# COPY --from=builder --chown=appuser:appuser /app/bin/server ./server +# --------------------------------------------------------- + +# Copy generic source files if needed (uncomment or modify as required) +# COPY --chown=appuser:appuser src/ ./src/ + +# Switch to the non-root user for security +USER appuser + +# Expose necessary ports +EXPOSE 8080 + +# Define the command to run the application +# Replace with the language-specific startup command (e.g., ["node", "dist/index.js"]) +CMD ["/bin/sh", "-c", "echo 'Please define a runtime command in the Dockerfile!'; exit 1"] diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..eed78e4 --- /dev/null +++ b/NOTICE @@ -0,0 +1,11 @@ +{{project_name}} +Copyright {{year}} {{organization}} + +This product includes software developed by {{organization}} +(https://github.com/{{organization}}/{{project_name}}). + +========================================================================= +Third-Party Attributions +========================================================================= + +[ Add third-party attributions, licenses, and notices here ] diff --git a/README.md b/README.md index 00afb22..8e84d4a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,159 @@ -# template-apache2.0 -Standardized repository template for Apache 2.0 projects. Opinionated defaults for modern development, compliance-ready documentation, and automated quality gates. +
+
+
+ An opinionated, production-ready Apache 2.0 template repository for bootstrapping modern software projects. +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Documentation | + Blog | + Roadmap | + Slack | + Weekly Syncs +
+ +--- + +## Overview + +
+
+
+
+
+ An opinionated, production-ready Apache 2.0 template repository for bootstrapping modern software projects. +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Documentation | + Blog | + Roadmap | + Slack | + Weekly Syncs +
+ +## Overview + +
+
+