diff --git a/.github/linters/.jscpd.json b/.github/linters/.jscpd.json index 5f27d220f..729f90f61 100644 --- a/.github/linters/.jscpd.json +++ b/.github/linters/.jscpd.json @@ -1,4 +1,9 @@ { "threshold": 5, - "ignore": [".astro/**"] + "ignore": [ + "**/.astro/**", + "**/node_modules/**", + "**/application/.docusaurus/**", + "**/application/build/**" + ] } diff --git a/README.md b/README.md index 1014d54c8..b3fda134d 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ This command generates static content into the `build` directory and can be serv ``` ├──application/ - ├── blog/ # Blog posts ├── docs/ # Documentation pages ├── src/ # Source files (React components, pages, etc.) │ ├── components/ # React components diff --git a/application/blog/2019-05-28-first-blog-post.md b/application/blog/2019-05-28-first-blog-post.md deleted file mode 100644 index d3032efb3..000000000 --- a/application/blog/2019-05-28-first-blog-post.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -slug: first-blog-post -title: First Blog Post -authors: [slorber, yangshun] -tags: [hola, docusaurus] ---- - -Lorem ipsum dolor sit amet... - - - -...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/application/blog/2019-05-29-long-blog-post.md b/application/blog/2019-05-29-long-blog-post.md deleted file mode 100644 index eb4435de5..000000000 --- a/application/blog/2019-05-29-long-blog-post.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -slug: long-blog-post -title: Long Blog Post -authors: yangshun -tags: [hello, docusaurus] ---- - -This is the summary of a very long blog post, - -Use a `` comment to limit blog post size in the list view. - - - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/application/blog/2021-08-01-mdx-blog-post.mdx b/application/blog/2021-08-01-mdx-blog-post.mdx deleted file mode 100644 index 0c4b4a48b..000000000 --- a/application/blog/2021-08-01-mdx-blog-post.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -slug: mdx-blog-post -title: MDX Blog Post -authors: [slorber] -tags: [docusaurus] ---- - -Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). - -:::tip - -Use the power of React to create interactive blog posts. - -::: - -{/* truncate */} - -For example, use JSX to create an interactive button: - -```js - -``` - - diff --git a/application/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/application/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg deleted file mode 100644 index 11bda0928..000000000 Binary files a/application/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg and /dev/null differ diff --git a/application/blog/2021-08-26-welcome/index.md b/application/blog/2021-08-26-welcome/index.md deleted file mode 100644 index aeacc2b41..000000000 --- a/application/blog/2021-08-26-welcome/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -slug: welcome -title: Welcome -authors: [slorber, yangshun] -tags: [facebook, hello, docusaurus] ---- - -[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). - -Here are a few tips you might find useful. - - - -Simply add Markdown files (or folders) to the `blog` directory. - -Regular blog authors can be added to `authors.yml`. - -The blog post date can be extracted from filenames, such as: - -- `2019-05-30-welcome.md` -- `2019-05-30-welcome/index.md` - -A blog post folder can be convenient to colocatee blog post images: - -![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) - -The blog supports tags as well! - -**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. diff --git a/application/blog/authors.yml b/application/blog/authors.yml deleted file mode 100644 index 18418b3b9..000000000 --- a/application/blog/authors.yml +++ /dev/null @@ -1,25 +0,0 @@ -yangshun: - name: Yangshun Tay - title: Ex-Meta Staff Engineer, Co-founder GreatFrontEnd - url: https://linkedin.com/in/yangshun - image_url: https://github.com/yangshun.png - page: true - socials: - x: yangshunz - linkedin: yangshun - github: yangshun - newsletter: https://www.greatfrontend.com - -slorber: - name: Sébastien Lorber - title: Docusaurus maintainer - url: https://sebastienlorber.com - image_url: https://github.com/slorber.png - page: - # customize the url of the author page at /blog/authors/ - permalink: "/all-sebastien-lorber-articles" - socials: - x: sebastienlorber - linkedin: sebastienlorber - github: slorber - newsletter: https://thisweekinreact.com diff --git a/application/blog/tags.yml b/application/blog/tags.yml deleted file mode 100644 index bfaa778fb..000000000 --- a/application/blog/tags.yml +++ /dev/null @@ -1,19 +0,0 @@ -facebook: - label: Facebook - permalink: /facebook - description: Facebook tag description - -hello: - label: Hello - permalink: /hello - description: Hello tag description - -docusaurus: - label: Docusaurus - permalink: /docusaurus - description: Docusaurus tag description - -hola: - label: Hola - permalink: /hola - description: Hola tag description diff --git a/application/docs/methodology/ci-cd/github/01-getting-started.md b/application/docs/methodology/ci-cd/github/01-getting-started.md new file mode 100644 index 000000000..63766a7f2 --- /dev/null +++ b/application/docs/methodology/ci-cd/github/01-getting-started.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +--- + +# Getting Started with GitHub Actions CI/CD + +Set up CI/CD for your project using GitHub Actions and Hoverkraft reusable workflows. The pattern works for single applications, monorepos, and containerized services alike—adjust the working directory and build steps to match your stack. + +## What You'll Build + +✅ Automated testing on pull requests +✅ Automated builds on commits +✅ On-demand deployments (review apps via `/deploy` comments, production via manual release workflow) +✅ Community automation (semantic PR titles, greetings, stale issues) +✅ Security scanning via the shared CI workflow + +## Prerequisites + +- GitHub repository (public or private) containing your application code +- Deterministic build/test commands (Makefile targets, package scripts, or similar) +- Ability to configure workflow inputs for your stack (working directory, runtime version, artifacts) +- Basic Git/GitHub knowledge +- ~30-60 minutes + +## CI/CD Overview + +**Continuous Integration (CI)**: Automatically builds, lints, and checks code on every change +**Continuous Deployment (CD)**: Deploys once you trigger it—either `/deploy` for review apps or a manual release workflow after CI succeeds + +## Hoverkraft Approach + +Pre-built, reusable workflows that: + +- Centralise CI logic in `__shared-ci.yml` so every workflow reuses the same jobs +- Enforce best practices (version pinning, minimal permissions) +- Stay updated through Dependabot (actions, runtimes, base images) + +## Tutorial Steps + +1. **Project Structure** - Repository layout +2. **Core Workflows** - Essential CI/CD +3. **Community Workflows** - Optional automation +4. **Deployment** - On-demand deployment flows +5. **Testing** - Verification +6. **Best Practices** - Tips and guidelines + +Follow steps in order for best results. + +## Ready? + +👉 **Next: [Project Structure →](./02-project-structure.md)** + +--- + +💡 **Tip**: Implement gradually - start with core workflows, test, then expand diff --git a/application/docs/methodology/ci-cd/github/02-project-structure.md b/application/docs/methodology/ci-cd/github/02-project-structure.md new file mode 100644 index 000000000..9c4250f11 --- /dev/null +++ b/application/docs/methodology/ci-cd/github/02-project-structure.md @@ -0,0 +1,101 @@ +--- +sidebar_position: 2 +--- + +# Project Structure + +Set up a container-first repository skeleton before wiring GitHub Actions. The pattern applies to single applications, monorepos, and collections of microservices—you can adjust directory names, but the responsibilities remain the same. + +## Baseline Layout + +``` +your-repo/ +├── .github/ +│ ├── dependabot.yml +│ └── workflows/ +│ ├── __shared-ci.yml +│ ├── pull-request-ci.yml +│ ├── main-ci.yml +│ ├── deploy.yml +│ ├── clean-deploy.yml +│ └── release.yml +├── .devcontainer/ +│ └── devcontainer.json +├── application/ +│ ├── service-a/ +│ │ ├── src/ +│ │ └── package.json | pyproject.toml | go.mod | pom.xml +│ └── service-b/ +│ ├── src/ +│ └── ... +├── docker/ +│ ├── service-a/Dockerfile +│ └── service-b/Dockerfile +├── charts/ +│ ├── service-a/ +│ └── service-b/ +├── docker-compose.yml +├── docker-compose.dev.yml +├── docker-compose.deploy.yml +└── Makefile | Taskfile.yml | Justfile +``` + +## Essentials by Directory + +| Path | Responsibility | +| ----------------------- | ---------------------------------------------------------------------------------------------- | +| `.github/` | Automation entrypoints (workflows, Dependabot policies, issue templates) | +| `.devcontainer/` | Tooling image definition (editors, Docker CLI, language runtimes needed for local work) | +| `application/` | Deployable code plus package metadata, lint/test scripts, configuration per service or package | +| `docker/` | Multi-stage Dockerfiles and supporting runtime configuration (nginx configs, entrypoints) | +| `charts/` | Helm chart(s), `values.yaml`, chart schema, chart tests, CI metadata (`ct.yaml`) | +| `docker-compose*.yml` | Local orchestration for dev, deploy previews, CI support containers | +| `Makefile` (or similar) | Thin wrapper that shells into the application container so local commands mirror CI | + +The combination delivers consistent DevX: developers use `make` (or your preferred runner) to reach the same container images CI uses, while Helm metadata keeps deployment manifests reproducible. + +## Development Experience (DevX) + +- **Devcontainer as tooling**: Provide only the editor helpers and Docker client. Do **not** run the application inside the devcontainer. CI and developers both build the dedicated application container stages declared in `docker//Dockerfile` (`base`, `build`, `ci`, `dev`, `prod`). +- **Wrapper commands**: Expose `make prepare`, `make lint`, `make build`, `make ci`, `make helm` (or equivalents). Each target shells into the application container via `docker compose` so every command runs with the same OS, Node/Python/Java version, and toolchain. +- **Pre-commit hooks**: Mirror CI checks locally (YAML linting, Helm linting, kubeconform, spelling, etc.) and keep the config in `.pre-commit-config.yaml` so contributors can run `pre-commit run --all-files` when needed. +- **Runtime pins**: Record languages in `.tool-versions`, `.nvmrc`, `.python-version`, `go.mod`, or `package.json#engines`. Dependabot can auto-bump them later, but everyone starts from a known baseline. + +## Application Directory Checklist + +Inside `application/` (and any nested service directories) ensure you have: + +- Package metadata with deterministic scripts (`check`, `lint`, `test`, `build`, `fix`). Whether you use `npm`, `pnpm`, `poetry`, `tox`, `go`, `cargo`, `mvn`, or `gradle`, expose the same entry points so local runs and CI stay aligned. +- Code quality config alongside the code: ESLint/Prettier, Ruff/Black, ktlint, Checkstyle, scalafmt—whatever matches each service’s stack. Keep these configs next to the code so Docker builds can copy them with the source tree. +- Strict compiler/tooling options (`tsconfig.json`, `.flake8`, `.golangci.yml`, `sonar-project.properties`, etc.) to catch issues early. +- Optional integration helpers (path aliases, shared libraries under `src/` or `pkg/`)—workflows do not inspect them, but keeping them colocateed simplifies builds. + +## Deployment Assets + +- **Docker**: Author one multi-stage Dockerfile per deployable component (for example `docker/service-a/Dockerfile`). Each file should expose repeatable targets: + - `base`: Installs system dependencies and globally needed CLIs. + - `build`: Installs application dependencies (e.g., `npm ci`, `poetry install --no-root`, `go mod download`, `mvn dependency:go-offline`). + - `build-app`: Produces the production artifact and prunes dev-only dependencies. + - `prod`: Base image for runtime (nginx/distroless/JRE/alpine/etc.), copies the artifact, defines health probes. + - `ci` and `dev`: Long-running targets used during lint/test (CI) or local development shells. +- **Helm**: Keep a chart per deployable component under `charts/` with `Chart.yaml`, `values.yaml`, templates, and docs. Use `ct.yaml` and `charts/lintconf.yaml` so `ct lint` and `helm kubeconform` can run automatically. +- **Registry metadata**: Declare registry coordinates (`image.registry`, `image.repository`) in `values.yaml`. CI updates only the tag/digest. + +## Automation Configuration + +- **Dependabot**: Enable updates for GitHub Actions, container base images, and your language package manager so pinned SHAs stay fresh. +- **Issue workflows**: Add greeting, semantic PR, stale triage, and need-fix workflows under `.github/workflows/`—they enforce the contribution workflow without touching application code. +- **Secrets & variables**: Plan ahead for `vars.OCI_REGISTRY`, `vars.CI_BOT_APP_ID`, URL variables (`REVIEW_APPS_URL`, etc.), and secrets like `CI_BOT_APP_PRIVATE_KEY`. The core workflows expect these names. + +## Bootstrap Checklist + +1. Scaffold directories shown above (rename `application/` if necessary) and commit the empty tree with placeholder `.gitkeep` files where required. +2. Author your multi-stage Dockerfile under `docker//Dockerfile`, ensuring targets for `dev`, `ci`, and `prod` exist. +3. Configure the application package scripts and lint/test/format config so `make check` (or equivalent) can target each service. For multi-service repos, add parameters (for example `SERVICE=service-a make ci`) or expose dedicated targets. +4. Provision Helm chart(s) and supporting files (`ct.yaml`, `chart-schema.yaml`, `lintconf.yaml`) to unlock automated linting and kubeconform checks. +5. Add `.pre-commit-config.yaml`, `.tool-versions`, `.env`, and devcontainer metadata to freeze the toolchain for contributors. +6. Drop in skeleton workflows under `.github/workflows/` (we will populate them in the next chapter) and add a `dependabot.yml` to keep them current. + +Once the structure is in place, wiring the reusable workflows becomes a matter of filling in the inputs and secrets—they assume this layout. + +👉 **Next: [Core Workflows →](./03-core-workflows.md)** diff --git a/application/docs/methodology/ci-cd/github/03-core-workflows.md b/application/docs/methodology/ci-cd/github/03-core-workflows.md new file mode 100644 index 000000000..e967415bd --- /dev/null +++ b/application/docs/methodology/ci-cd/github/03-core-workflows.md @@ -0,0 +1,263 @@ +--- +sidebar_position: 3 +--- + +# Core Workflows + +Wire the three workflows that orchestrate CI/CD: `__shared-ci.yml`, `pull-request-ci.yml`, and `main-ci.yml`. They mirror the landing-page reference but stay agnostic to your stack because every command ultimately runs inside the container you build—whether the codebase hosts one application or a fleet of services packaged under `application/`. + +## Shared CI Workflow (`__shared-ci.yml`) + +Create `.github/workflows/__shared-ci.yml` and pin each reusable workflow to the commit you validated. The blueprint below matches the Hoverkraft methodology: lint code, build container images, run static analysis and integration checks inside those images, and publish reports back to GitHub. + +```yaml title=".github/workflows/__shared-ci.yml" +name: Shared – Continuous Integration + +on: + workflow_call: + +permissions: + contents: read + statuses: write + security-events: write + packages: write + issues: read + pull-requests: read + # Required for reusable workflows pinned by commit + id-token: write + +jobs: + linter: + uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@ # x.y.z + permissions: + actions: read + contents: read + statuses: write + security-events: write + + build: + uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@ # x.y.z + permissions: + contents: read + packages: write + issues: read + pull-requests: read + id-token: write + with: + oci-registry: ${{ vars.OCI_REGISTRY }} + sign: false + images: | + [ + { + "name": "ci", + "context": ".", + "dockerfile": "./docker/service-a/Dockerfile", + "build-args": { "APP_PATH": "./application/service-a/" }, + "target": "ci", + "platforms": ["linux/amd64"] + }, + { + "name": "service-a", + "context": ".", + "dockerfile": "./docker/service-a/Dockerfile", + "build-args": { "APP_PATH": "./application/service-a/" }, + "target": "prod", + "platforms": ["linux/amd64"] + } + ] + secrets: + oci-registry-password: ${{ secrets.GITHUB_TOKEN }} + + sast: + name: Static analysis inside the service image + needs: build + runs-on: ubuntu-latest + container: + image: ${{ fromJSON(needs.build.outputs.built-images).ci.images[0] }} + credentials: + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + options: --user root + defaults: + run: + working-directory: /usr/src/app + steps: + - name: Run your stack checks + run: | + # Example (Node.js): npm run lint -- --output-file lint-report.json --format json + # Example (Python): poe lint --format json --output lint-report.json + # Example (Go): golangci-lint run --out-format json --output lint-report.json + ./scripts/run-static-analysis.sh + - name: Normalise report paths for annotations + run: sed -i 's@/usr/src/app/@${{ github.workspace }}/application/service-a/@g' /usr/src/app/lint-report.json + - uses: actions/upload-artifact@ # vX.Y.Z + with: + name: lint-report + path: /usr/src/app/lint-report.json + - name: Build application (replace with your build command) + run: ./scripts/build.sh service-a + + report-sast: + if: github.event_name == 'pull_request' + needs: sast + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + checks: write + steps: + - uses: actions/download-artifact@ # vX.Y.Z + with: + name: lint-report + - uses: ataylorme/eslint-annotate-action@ # x.y.z + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + report-json: lint-report.json + markdown-report-on-step-summary: true + + tests-charts: + name: Helm tests + needs: build + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + steps: + - name: Test Helm chart(s) + uses: hoverkraft-tech/ci-github-container/actions/helm/test-chart@ # x.y.z + with: + helm-set: | + image.registry=${{ fromJSON(needs.build.outputs.built-images).service-a.registry }} + image.repository=${{ fromJSON(needs.build.outputs.built-images).service-a.repository }} + image.tag=${{ fromJSON(needs.build.outputs.built-images).service-a.tags[0] }} + image.digest=${{ fromJSON(needs.build.outputs.built-images).service-a.digest }} + oci-registry: ${{ vars.OCI_REGISTRY }} + oci-registry-password: ${{ github.token }} +``` + +> Replace every `` placeholder with the exact commit SHA (and optional release comment) you validated for that reusable workflow or action. Expand the `images` map (and downstream references) for each service you ship. + +### How to adapt it to your stack + +- **Linting**: Toggle `linter-env` values to match the linters you actually execute. Use separate runs per ecosystem if required. +- **Container build**: Point `dockerfile`, `context`, `build-args`, `target`, and `platforms` at each service’s Dockerfile. Extend the `images` array to cover every deployable artifact (Web, API, worker, etc.). +- **Static analysis**: Replace `./scripts/run-static-analysis.sh` with the command(s) you need (`npm run lint`, `poetry run invoke lint`, `go test ./...`, `dotnet test`, etc.). The pattern—run inside the freshly built `ci` image and upload artifacts—remains the same. +- **Report fan-out**: Swap the annotate action if you produce SARIF, JUnit, or other formats. The goal is to comment on pull requests using the report generated in the container job, regardless of language. +- **Charts test**: If you do not ship Helm charts, repurpose this job for integration or contract tests (for example by calling `hoverkraft-tech/compose-action` to spin up databases or message brokers). + +### Required repository configuration + +| Type | Name | Purpose | +| -------- | ----------------------------- | -------------------------------------------------------------------------- | +| Variable | `OCI_REGISTRY` | Registry host used by the container workflow | +| Variable | `CI_BOT_APP_ID` | GitHub App ID used by deployment workflows (later step) | +| Variable | `REVIEW_APPS_URL` / `UAT_URL` | Environment base URLs consumed by `deploy.yml` | +| Secret | `CI_BOT_APP_PRIVATE_KEY` | GitHub App private key passed to publish workflows | +| Secret | (optional) registry password | Use when not pushing to GHCR; else `${{ secrets.GITHUB_TOKEN }}` is enough | + +Add more as your services require (database passwords, third party tokens, etc.). + +## Pull Request Workflow (`pull-request-ci.yml`) + +Create `.github/workflows/pull-request-ci.yml` so every pull request (or merge queue run) reuses the shared pipeline for all services: + +```yaml title=".github/workflows/pull-request-ci.yml" +name: Pull request – Continuous Integration + +on: + pull_request: + branches: [main] + +permissions: + actions: read + checks: write + contents: read + issues: read + packages: write + pull-requests: write + security-events: write + statuses: write + id-token: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ci: + name: Continuous Integration + uses: ./.github/workflows/__shared-ci.yml + secrets: inherit +``` + +The wrapper keeps workflow logic in one place while ensuring PRs get status checks, annotations, and artifacts. + +## Main Branch Workflow (`main-ci.yml`) + +The default branch workflow performs three tasks: clean old images, execute the shared CI pipeline (across all services defined in `__shared-ci.yml`), and regenerate Helm documentation. + +```yaml title=".github/workflows/main-ci.yml" +name: Main – Continuous Integration + +on: + push: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + actions: read + checks: write + contents: read + issues: read + packages: write + pull-requests: write + security-events: write + statuses: write + id-token: write + +jobs: + clean: + uses: hoverkraft-tech/ci-github-container/.github/workflows/prune-pull-requests-images-tags.yml@ # x.y.z + with: + images: '["ci","service-a"]' + + ci: + name: Continuous Integration + uses: ./.github/workflows/__shared-ci.yml + secrets: inherit + + helm-docs: + needs: ci + runs-on: ubuntu-latest + if: github.event_name != 'schedule' + steps: + - uses: actions/checkout@ # vX.Y.Z + - uses: hoverkraft-tech/ci-github-container/actions/helm/generate-docs@ # x.y.z + with: + working-directory: ./charts + github-app-id: ${{ vars.CI_BOT_APP_ID }} + github-app-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }} +``` + +Extend the workflow with publish jobs (for example pushing SBOMs, uploading coverage, or syncing manifests) once you validate CI. + +## Secrets, Variables, and Permissions + +- **Pin everything**: Dependabot can open PRs whenever new releases of the reusable workflows appear. Merge only after testing. +- **Minimal permissions**: Scope jobs to the permissions they need (see each job definition). Avoid granting `contents: write` unless a job commits back to the repository. +- **Secrets forwarding**: Using `secrets: inherit` lets the shared workflow access repository secrets. Provide only what the jobs consume (registry tokens, GitHub App key, etc.). + +## Customising Beyond the Reference + +- Add more jobs to `__shared-ci.yml` (for example UI tests) or split jobs into matrices when multiple services share the same build pipeline. +- If your stack cannot run inside the built container, build a dedicated `ci` target that contains the needed runtime and CLIs. Keep the production `prod` stage minimal. +- For monorepos, parameterise `images` and `helm-set` with matrices or `if` statements so each service builds independently while reusing the same workflow file. + +## Next Steps + +Commit the workflows and push a branch. Once they pass, continue with the community and deployment workflows to complete the Hoverkraft methodology. + +👉 **Next: [Community Workflows →](./04-community-workflows.md)** diff --git a/application/docs/methodology/ci-cd/github/04-community-workflows.md b/application/docs/methodology/ci-cd/github/04-community-workflows.md new file mode 100644 index 000000000..4f4b34aac --- /dev/null +++ b/application/docs/methodology/ci-cd/github/04-community-workflows.md @@ -0,0 +1,219 @@ +--- +sidebar_position: 4 +--- + +# Community Workflows + +Optional workflows help you keep community interactions organised without touching application code. Add the ones that match your team's needs and pin every reusable workflow to a tested commit. + +## Semantic Pull Request Titles + +Create `.github/workflows/semantic-pull-request.yml` to enforce Conventional Commit titles: + +```yaml title=".github/workflows/semantic-pull-request.yml" +name: Semantic Pull Request + +on: + pull_request_target: + types: [opened, edited, synchronize] + +permissions: + pull-requests: write + +jobs: + main: + uses: hoverkraft-tech/ci-github-common/.github/workflows/semantic-pull-request.yml@ +``` + +- The reusable workflow comments on pull requests that fail the title check. +- Replace `` with the commit you validated (for example the tag SHA for release `0.26.0`). + +## Greet New Contributors + +Create `.github/workflows/greetings.yml` to welcome first-time contributors: + +```yaml title=".github/workflows/greetings.yml" +name: Greetings + +on: + pull_request_target: + types: [opened] + issues: + types: [opened] + +permissions: + issues: write + pull-requests: write + +jobs: + main: + uses: hoverkraft-tech/ci-github-common/.github/workflows/greetings.yml@ + with: + issue-message: "Thanks for opening your first issue!" + pr-message: "Thanks for contributing! A maintainer will review your pull request soon." +``` + +Adjust the messages to match your tone of voice. + +## Triage Stale Issues and Pull Requests + +Create `.github/workflows/stale.yml` to mark inactive threads: + +```yaml title=".github/workflows/stale.yml" +name: Stale issues and PRs + +on: + schedule: + - cron: "0 1 * * *" # Daily at 01:00 UTC + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + main: + uses: hoverkraft-tech/ci-github-common/.github/workflows/stale.yml@ + with: + days-before-stale: 30 + days-before-close: 7 + stale-issue-message: | + This issue has been automatically marked as stale because it has not had + recent activity. Please update if this is still relevant. + stale-pr-message: | + This pull request has been automatically marked as stale. Remove the + stale label or push new commits to keep it open. +``` + +Tune timings, labels, and messages to your process. + +## Track Requested Changes + +Convert "changes requested" reviews into actionable issues with `.github/workflows/need-fix-to-issue.yml`: + +```yaml title=".github/workflows/need-fix-to-issue.yml" +name: Need fix to issue + +on: + push: + branches: + - main + workflow_dispatch: + inputs: + manual-commit-ref: + description: "SHA to inspect when running manually" + required: true + manual-base-ref: + description: "Optional base commit" + required: false + +permissions: + contents: read + issues: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + main: + uses: hoverkraft-tech/ci-github-common/.github/workflows/need-fix-to-issue.yml@ + with: + manual-commit-ref: ${{ inputs.manual-commit-ref }} + manual-base-ref: ${{ inputs.manual-base-ref }} +``` + +- Automatically opens or updates issues when reviews request changes. +- Manual trigger allows auditing past commits. + +## Keep Dependencies Current (Dependabot) + +Create `.github/dependabot.yml` to group updates by ecosystem. Start with placeholders and replace the patterns with the package families you actually use: + +```yaml title=".github/dependabot.yml" +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 20 + groups: + gha-dependencies: + patterns: + - "*" + + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 20 + groups: + devcontainer-dependencies: + patterns: + - "*" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 20 + groups: + docker-dependencies: + patterns: + - "*" + + - package-ecosystem: "npm" + directory: "application/service-a/" + schedule: + interval: "weekly" + versioning-strategy: increase + groups: + app-framework: + patterns: + - "@your-framework/*" + - "your-framework" + app-tooling: + dependency-type: "development" + + - package-ecosystem: "pip" + directory: "application/service-b/" + schedule: + interval: "weekly" + groups: + python-runtime: + patterns: + - "your-python-framework" + - "your-analytics-library" + python-tooling: + dependency-type: "development" +``` + +- Duplicate the last two blocks for every package manager your services rely on (Gradle, Cargo, Go modules, etc.). +- Dependabot groups updates so you handle one PR per package family instead of dozens. + +## Commit and Test + +```bash +git add .github/workflows/semantic-pull-request.yml +git add .github/workflows/greetings.yml +git add .github/workflows/stale.yml +git add .github/workflows/need-fix-to-issue.yml +git add .github/dependabot.yml +git commit -m "Add community management workflows" +git push +``` + +After merging, validate that: + +- The semantic PR workflow blocks non-conforming titles. +- First-time contributors receive greeting comments. +- Stale issues gain labels or close according to your configuration. +- Dependabot PRs show grouped updates that match your ecosystems. + +👉 **Next: [Deployment Setup →](./05-deployment.md)** + +--- + +💡 **Tip**: Review these workflows quarterly—adjust timing, labels, and grouping as your community scales. diff --git a/application/docs/methodology/ci-cd/github/05-deployment.md b/application/docs/methodology/ci-cd/github/05-deployment.md new file mode 100644 index 000000000..2f395ce5f --- /dev/null +++ b/application/docs/methodology/ci-cd/github/05-deployment.md @@ -0,0 +1,222 @@ +--- +sidebar_position: 5 +--- + +# Deployment Setup + +The Hoverkraft landing-page reference uses three GitHub Actions workflows for every deployment action: + +- `.github/workflows/deploy.yml` provisions review, UAT, or production environments. It can be triggered by pull-request comments or called from other workflows. +- `.github/workflows/clean-deploy.yml` removes review environments whenever a pull request closes. +- `.github/workflows/release.yml` is a manual “Release” entry point that creates a GitHub release, then reuses `deploy.yml` to promote to UAT or production. + +Each workflow delegates to reusable pipelines hosted in `hoverkraft-tech/ci-github-publish` (pin to the commit SHA that corresponds to the release you validated, for example `42d50a3461a177557ca3f83b1d927d7c0783c894 # 0.11.2`). The sections below document the configuration so you can replicate it. + +## Step 1: Publish container images in CI + +Ensure your default-branch workflow (`main-ci.yml` in the example) builds and pushes every container image the application needs. The deployment workflows assume those images already exist. + +Checklist: + +- ✅ `packages: write` (or equivalent registry credentials) available to publish images. +- ✅ Deterministic tags (commit SHA, SemVer, etc.) shared across services. +- ✅ Dockerfiles and build arguments tracked in the repository, matching the `images` map used during deploy. +- ✅ Security scan reports/SBOMs produced for traceability. + +## Step 2: `deploy.yml` — provisioning environments + +Triggers: + +- `issue_comment` (`types: [created]`) lets maintainers request deployments via comments such as `/deploy`. Comment validation happens inside the reusable workflow. +- `workflow_call` exposes a reusable interface with required inputs: + - `tag` (string): container image tag to deploy. + - `environment` (string): target environment (`review`, `uat`, or `production`). + +Permissions mirror the example: + +```yaml +permissions: + contents: write + issues: write + packages: write + pull-requests: write + deployments: write + actions: read + id-token: write +``` + +Job definition from the example repository (single deployable `application` image by default): + +```yaml +jobs: + deploy: + name: Deploy + uses: hoverkraft-tech/ci-github-publish/.github/workflows/deploy-chart.yml@ + secrets: + oci-registry-password: ${{ secrets.GITHUB_TOKEN }} + github-app-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }} + with: + url: ${{ (inputs.environment == 'uat' && vars.UAT_URL) || (inputs.environment == 'production' && vars.PRODUCTION_URL) || vars.REVIEW_APPS_URL }} + tag: ${{ inputs.tag }} + environment: ${{ inputs.environment }} + github-app-id: ${{ vars.CI_BOT_APP_ID }} + deploy-parameters: | + { "repository": "${{ github.repository_owner }}/argocd-app-of-apps" } + images: | + [ + { + "name": "application", + "context": ".", + "dockerfile": "./docker/application/Dockerfile", + "build-args": { "APP_PATH": "./application/" }, + "target": "prod", + "platforms": ["linux/amd64"] + } + ] + chart-values: | + [ + { "path": "image", "image": "application" }, + { "path": "application.version", "value": "{{ tag }}" }, + { "path": "deploy.ingress.hosts[0].host", "value": "{{ url }}" } + ] +``` + +What to adapt: + +- Extend the `images` array for every service you build. The output name (for example `application`, `service-a`, `worker`) must match the keys you later reference in deployment workflows (`helm-set`, `chart-values`, etc.). +- Update `chart-values` paths so they align with your umbrella Helm chart. +- Define repository variables: `REVIEW_APPS_URL`, `UAT_URL`, `PRODUCTION_URL`, `CI_BOT_APP_ID`. +- Store the GitHub App private key as `CI_BOT_APP_PRIVATE_KEY` (or adjust the secret name and reference). + +For multi-service repositories, add extra entries to both `images` and `chart-values`. Example: + +```yaml +images: | + [ + { "name": "application", "context": ".", "dockerfile": "./docker/application/Dockerfile", "target": "prod" }, + { "name": "service-b", "context": ".", "dockerfile": "./docker/service-b/Dockerfile", "target": "prod" } + ] +chart-values: | + [ + { "path": "app.image", "image": "application" }, + { "path": "serviceB.image", "image": "service-b" } + ] +``` + +## Step 3: `clean-deploy.yml` — tearing down review apps + +Trigger: + +```yaml +on: + pull_request_target: + types: [closed] +``` + +Job definition: + +```yaml +jobs: + clean-deploy: + uses: hoverkraft-tech/ci-github-publish/.github/workflows/clean-deploy.yml@ + with: + clean-deploy-parameters: | + { "repository": "${{ github.repository_owner }}/argocd-app-of-apps" } + github-app-id: ${{ vars.CI_BOT_APP_ID }} + secrets: + github-app-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }} +``` + +Running as `pull_request_target` grants the workflow repository-level permissions, which ensures cleanup works even when pull requests originate from forks. + +## Step 4: `release.yml` — manual promotion + +Trigger and permissions: + +```yaml +on: + workflow_dispatch: + inputs: + environment: + description: "Environment to deploy to" + required: true + type: choice + options: + - uat + - production +permissions: + checks: write + packages: write + issues: write + pull-requests: write + contents: write + deployments: write + actions: read + id-token: write +``` + +Jobs: + +1. `release` + +- Uses `hoverkraft-tech/ci-github-publish/actions/release/create@`. +- Outputs `tag` (`steps.create-release.outputs.tag`). +- Sets `prerelease: true` when the selected environment is `uat`. + +2. `deploy` + - Depends on `release`. + - Calls the local `deploy.yml` (`uses: ./.github/workflows/deploy.yml`). + - Passes through `tag` and `environment` so the same deployment path runs as for review apps. + - Uses `secrets: inherit` to forward the GitHub App key and other secrets. + +Manual release procedure: + +1. Open **Actions → • 🚀 Release → Run workflow**. +2. Choose `uat` or `production`. +3. Run the workflow. It creates the release and immediately deploys using `deploy.yml`. + +## Step 5: Test the deployment flows + +| Flow | Trigger | Expected outcome | +| --------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------------- | +| Review deployment | Comment `/deploy` on an open PR (after CI finishes). | The reusable deploy workflow updates the GitOps repository and reports back in the PR. | +| Review cleanup | Merge or close the PR. | `clean-deploy.yml` removes the review environment using the reusable cleanup workflow. | +| Release to UAT | Run **• 🚀 Release** with `environment = uat`. | Creates a prerelease tag and deploys with UAT values/URL. | +| Release to production | Run **• 🚀 Release** with `environment = production`. | Creates a production release and deploys with production values/URL. | + +If a run fails, open the job logs and inspect the reusable workflow steps (they surface detailed errors from `hoverkraft-tech/ci-github-publish`). + +## Step 6: Branch protection (recommended) + +1. Go to **Settings → Branches**. +2. Edit your default-branch rule. +3. Require CI status checks before merging. +4. (Optional) Require the release workflow to succeed before tags are published if you enforce gated production deploys. + +## Troubleshooting + +**Deploy workflow not triggered** + +- Confirm `deploy.yml` exists and references the pinned reusable workflow commit. +- Check repository variables (`REVIEW_APPS_URL`, `UAT_URL`, `PRODUCTION_URL`, `CI_BOT_APP_ID`). +- Ensure comment text matches the expected command (`/deploy`) and the commenter has permission. + +**Cleanup workflow skipped** + +- Verify `clean-deploy.yml` still targets the reusable workflow at commit `42d50a3`. +- Re-issue the GitHub App private key if authentication fails. + +**Release workflow failed** + +- Inspect the `release` job for errors from `actions/release/create` (permissions, invalid tag, etc.). +- Check the downstream `deploy` job to see the same logs produced by `deploy.yml`. + +## What's Next? + +Continue with testing to confirm local and CI tooling stay aligned. + +👉 **Next: [Testing Your Setup →](./06-testing.md)** + +--- + +💡 **Tip**: Document the `/deploy` and manual release procedures in your repository’s CONTRIBUTING guide so contributors know how to request environments. diff --git a/application/docs/methodology/ci-cd/github/06-testing.md b/application/docs/methodology/ci-cd/github/06-testing.md new file mode 100644 index 000000000..c45ebf2af --- /dev/null +++ b/application/docs/methodology/ci-cd/github/06-testing.md @@ -0,0 +1,266 @@ +--- +sidebar_position: 6 +--- + +# Testing Your Setup + +Let's verify that everything works correctly by going through a complete development cycle. + +## Test Checklist + +We'll test: + +- ✅ Pull request workflow +- ✅ Main branch workflow +- ✅ Review app deployment (`/deploy`) +- ✅ Release workflow (manual trigger) +- ✅ Community workflows + +## Test 1: Pull Request Workflow + +Let's simulate a normal development workflow: + +### Step 1: Create a Feature Branch + +```bash +git checkout -b test-feature +``` + +### Step 2: Make a Change + +Edit any file in your application. For example: + +```bash +echo "// CI test change" >> application/service-a/src/example.ts +``` + +Choose a file that exists in your stack (`application/service-a/src/App.tsx`, `application/service-b/app/main.py`, etc.). + +### Step 3: Commit and Push + +```bash +git add . +git commit -m "feat: add test change" +git push origin test-feature +``` + +### Step 4: Open a Pull Request + +1. Go to your repository on GitHub +2. Click **Pull requests** → **New pull request** +3. Select your `test-feature` branch +4. Click **Create pull request** + +### Step 5: Watch the Workflow + +1. Go to the **Actions** tab +2. You should see "Pull request - Continuous Integration" running +3. Wait for it to complete (usually 2-5 minutes) + +**Expected result:** ✅ Green checkmark indicating CI passed + +### Step 6: Check the PR + +Back on your PR page, you should see: + +- ✅ CI checks passed +- Comment from the greeting bot (if this is your first PR) + +## Test 2: Review App Deployment (`/deploy`) + +### Step 1: Comment on the PR + +Add a new comment on the open pull request: `/deploy` + +### Step 2: Watch the Review Workflow + +1. Go to **Actions** +2. Locate the workflow that handles review deployments (e.g., "Deploy review app") +3. Confirm it runs with green status + +### Step 3: Verify the Review Environment + +1. Collect the URL from the workflow logs or bot comment +2. Ensure the review app is running the latest changes +3. Optionally test teardown if you support `/undeploy` + +## Test 3: Release Workflow + +### Step 1: Merge the PR + +Click **Merge pull request** → **Confirm merge** + +### Step 2: Run “Release” Manually + +1. Navigate to the **Actions** tab +2. Select the "Release" workflow +3. Click **Run workflow** + +### Step 3: Verify Deployment + +1. Monitor the workflow logs for a successful ArgoCD sync +2. Open ArgoCD and confirm the application is synced and healthy +3. Verify the Kubernetes workload uses the new image (`kubectl get deploy your-app -o yaml | grep image`) +4. Hit the production endpoint to validate the change 🎉 + +## Test 4: Semantic PR Validation + +Let's verify the semantic PR check works: + +### Step 1: Create Another Branch + +```bash +git checkout main +git pull +git checkout -b another-test +``` + +### Step 2: Make a Change and Open PR + +```bash +echo "// Semantic PR check" >> application/service-a/src/example.ts +git add . +git commit -m "some random commit" +git push origin another-test +``` + +Open a PR with title: `random title without prefix` + +### Step 3: Check the Validation + +The "Semantic Pull Request" check should **fail** ❌ because the title doesn't follow the format. + +### Step 4: Fix the Title + +Edit the PR title to: `feat: add another test` + +The check should now **pass** ✅ + +## Test 4: Dependabot (Optional) + +Dependabot runs automatically, but you can verify it's configured: + +1. Go to **Insights** → **Dependency graph** → **Dependabot** +2. You should see it's enabled +3. Within a week, you should get PRs for dependency updates + +## Common Issues and Solutions + +### Issue: CI Workflow Not Running + +**Check:** + +- Are workflow files in `.github/workflows/`? +- Is YAML syntax valid? +- Are you pushing to the correct branch? + +**Solution:** + +```bash +# Verify files exist +ls -la .github/workflows/ + +# Validate YAML (use online validator) +cat .github/workflows/pull-request-ci.yml +``` + +### Issue: Build Failing + +**Check:** + +- Do your `package.json` scripts exist? +- Does `working-directory` match your project structure? + +**Solution:** + +```bash +# Test locally using the same steps as your CI job +make lint +make build +make test +make ci # runs lint + build + test consecutively (adjust if you use different targets) + +# Check workflow logs +# Go to Actions tab → Click failed workflow → Click job → Expand steps +``` + +### Issue: Deployment Failing + +**Check:** + +- Did the review or release workflow run after the trigger? +- Did the CI/CD push the expected image(s), Helm chart(s) to the registry? +- Are registry/ArgoCD secrets configured correctly? + +**Solution:** + +- Inspect the deployment workflow logs for authentication or image errors +- Review ArgoCD application status and event logs to confirm a sync occurred + +### Issue: Tests Failing Locally Work in CI + +**Check:** + +- Are you using the same Node version? +- Are dependencies up to date? + +**Solution:** + +Run the checks from the tooling container so you match the CI image exactly. Reopen the repository in the devcontainer (Visual Studio Code → **Dev Containers: Reopen in Container**) or drop into it via your wrapper (for example `make shell`). Once you are inside the container shell: + +```bash +# Verify the runtime matches CI +node --version # Should match the version in your CI (20.x in the reference project) + +# Clean install within the container (adjust for your package manager/runtime) +cd application +rm -rf node_modules package-lock.json +npm ci +npm run build +``` + +Prefer scripted wrappers when you need to run the commands non-interactively. Important: use the application container (built from your project Dockerfile) for installs, builds and tests. The devcontainer provides the Docker client and editor integration but is not the runtime image for the application. + +Example using the repository `docker-compose.yml` and the application service (which should build from your multi-stage Dockerfile and run the appropriate `dev` stage locally): + +```bash +docker compose -f docker-compose.yml run --rm app bash -lc "cd application && npm ci && npm run build" +``` + +If you prefer to use the devcontainer to provide the Docker CLI, open the devcontainer and run the compose command from inside it. That still runs the application commands inside the application container built from your Dockerfile. + +The reference repository already declares these requirements in `application/package.json` under the `engines` field. For other runtimes, mirror the same idea (e.g., Python version with `.python-version`, Go version via toolchain configuration). + +> ℹ️ **Devcontainer vs. runtime**: the devcontainer (tooling image) keeps your CLIs consistent with CI. Your services still run in their own OCI containers—use the repository `Dockerfile`, `docker-compose.yml`, or Helm chart to build and run the actual application images. Avoid shipping the devcontainer image to production. + +## Verify Everything Works + +You should now have: + +- ✅ Pull requests trigger CI automatically +- ✅ CI runs tests, lint, and build +- ✅ Failed CI prevents merging (if branch protection is enabled) +- ✅ Review app deployment works on `/deploy` +- ✅ Release workflow promotes builds when run manually +- ✅ Semantic PR validation enforces title format +- ✅ New contributors get welcome messages +- ✅ Dependabot creates update PRs + +## View Workflow History + +To see all your workflow runs: + +1. Go to **Actions** tab +2. See list of all workflows and their status +3. Click any workflow to see detailed logs +4. Use filters to find specific runs + +## What's Next? + +Your CI/CD is fully working! Let's learn some best practices to keep it that way. + +👉 **Next: [Best Practices →](./07-best-practices.md)** + +--- + +💡 **Tip**: Keep the Actions tab open while developing. It's satisfying to watch those green checkmarks! ✅ diff --git a/application/docs/methodology/ci-cd/github/07-best-practices.md b/application/docs/methodology/ci-cd/github/07-best-practices.md new file mode 100644 index 000000000..f030fcda8 --- /dev/null +++ b/application/docs/methodology/ci-cd/github/07-best-practices.md @@ -0,0 +1,320 @@ +--- +sidebar_position: 7 +--- + +# Best Practices + +Follow these guidelines to keep your CI/CD pipeline secure, fast, and maintainable. + +## Security Best Practices + +### 1. Always Pin Workflow Versions + +✅ **Do this:** + +```yaml +uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@4f29319e02dd65152386c436e8c3136f380a0e71 # 0.28.0 +``` + +❌ **Not this:** + +```yaml +uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@main +``` + +**Why?** Pinning to a specific version prevents unexpected breaking changes. The workflow you tested will always run the same way. + +**When to update:** Check for new tagged releases (Dependabot will open PRs for you) and bump the SHA after verifying the changelog. + +### 2. Use Minimal Permissions + +Each workflow should only have the permissions it needs: + +```yaml +permissions: + contents: read # Read code only + security-events: write # Only if you need security scanning + id-token: write # Only if you need authentication +``` + +**Why?** Limits damage if a workflow is compromised. + +### 3. Store Secrets Securely + +Never hardcode sensitive data: + +```yaml +# ❌ Bad +env: + API_KEY: "sk-1234567890abcdef" + +# ✅ Good +env: + API_KEY: ${{ secrets.API_KEY }} +``` + +**How to add secrets:** + +1. Go to **Settings** → **Secrets and variables** → **Actions** +2. Click **New repository secret** +3. Add name and value +4. Use in workflows with `${{ secrets.SECRET_NAME }}` + +### 4. Use Deployment Environments + +For production deployments, use environments for extra protection: + +```yaml +environment: + name: production + url: https://your-app.com +``` + +**Benefits:** + +- Require manual approval before deployment +- Limit who can deploy +- Track deployment history + +## Performance Best Practices + +### 1. Cancel Redundant Runs + +Already in your workflows: + +```yaml +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +``` + +**What this does:** If you push new changes while CI is running, it cancels the old run. Saves time and GitHub Actions minutes. + +### 2. Leverage Caching + +The Hoverkraft workflows automatically cache dependencies. You don't need to do anything! + +**What's cached:** + +- Package managers (npm/pnpm/Yarn, pip, poetry, go modules, etc.) +- Docker layers (containers) +- Build artifacts (between jobs) + +### 3. Run Jobs in Parallel + +For multiple independent tasks, run them in parallel: + +```yaml +jobs: + test: + runs-on: ubuntu-latest + # ... test steps + + lint: + runs-on: ubuntu-latest + # ... lint steps + + # These run simultaneously +``` + +The Hoverkraft workflows handle this automatically. + +## Maintainability Best Practices + +### 1. Keep Workflows Simple + +Complex logic belongs in scripts, not YAML: + +```yaml +# ❌ Complex +- run: | + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + if [ "${{ github.event_name }}" == "push" ]; then + # 50 lines of bash... + fi + fi + +# ✅ Simple +- run: ./scripts/deploy.sh + if: github.ref == 'refs/heads/main' +``` + +### 2. Document Custom Workflows + +Add comments for non-obvious parts: + +```yaml +jobs: + deploy: + # Wait for manual approval in production + environment: production + steps: + - name: Deploy to S3 + # Using custom script because we need special S3 bucket policy + run: ./scripts/custom-deploy.sh +``` + +### 3. Reuse Workflows + +Don't copypaste workflow logic. Use the shared workflow pattern we set up: + +```yaml +# This in multiple workflows +jobs: + ci: + uses: ./.github/workflows/__shared-ci.yml +``` + +### 4. Keep Dependencies Updated + +Dependabot helps, but also: + +- Review updates weekly +- Test before merging +- Read changelogs for breaking changes + +### 5. Monitor Workflow Performance + +Check regularly: + +- How long workflows take +- Which steps are slow +- GitHub Actions usage (free tier: 2000 minutes/month) + +Go to **Actions** → Click any workflow → See duration + +## Development Workflow Best Practices + +### 1. Test Locally First + +Before pushing, run the same checks locally and run them inside the application container so they match CI. + +```bash +make lint +make build +make ci +# or the equivalent commands for your stack (poetry run, go test, mvn verify, etc.) +``` + +Catches issues before CI runs (faster feedback). Note: the devcontainer is tooling-only (provides the Docker CLI, DIND helpers and editor extensions); it should not be used as the application runtime image. Use it only to launch the application container or run the compose commands above. + +### 2. Use Semantic Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +- `feat:` New feature +- `fix:` bugfix +- `docs:` Documentation changes +- `chore:` Maintenance tasks +- `refactor:` Code refactoring +- `test:` Test changes + +**Benefits:** + +- Auto-generate changelogs +- Trigger semantic versioning +- Clear Git history + +### 3. Keep PRs Small + +Small PRs are: + +- Easier to review +- Faster to test +- Less likely to have conflicts +- Easier to revert if needed + +**Rule of thumb:** < 400 lines changed + +### 4. Write Good PR Descriptions + +Include: + +- What changed and why +- How to test +- Screenshots for UI changes +- Related issues + +### 5. Review CI Logs + +When CI fails: + +1. Click on the failed check +2. Expand the failed step +3. Read the error message +4. Fix locally and push again + +Don't just re-run – fix the actual issue. + +## Monitoring and Alerts + +### Set Up Notifications + +Get notified about workflow failures: + +1. Go to your GitHub profile → **Settings** +2. Click **Notifications** +3. Enable **Actions** notifications +4. Choose email or web notifications + +### Use Status Badges + +Add a status badge to your readme: + +```markdown +![CI](https://github.com/username/repo/workflows/Pull%20request%20-%20Continuous%20Integration/badge.svg) +``` + +Shows build status to everyone visiting your repository. + +## Regular Maintenance Tasks + +### Weekly + +- ✅ Review and merge Dependabot PRs +- ✅ Check workflow run times +- ✅ Review failed workflow runs + +### Monthly + +- ✅ Update pinned workflow versions +- ✅ Review and close stale issues +- ✅ Check GitHub Actions usage + +### Quarterly + +- ✅ Review and update documentation +- ✅ Evaluate new workflow features +- ✅ Clean up unused workflows + +## Common Mistakes to Avoid + +### 1. ❌ Committing Secrets + +Never commit API keys, passwords, or tokens. Use GitHub Secrets. + +### 2. ❌ Ignoring Dependabot + +Outdated dependencies = security vulnerabilities. Review updates regularly. + +### 3. ❌ Not Testing CI Changes + +Always test workflow changes in a branch first, not on main. + +### 4. ❌ Too Many Workflows + +Start simple. Add complexity only when needed. + +### 5. ❌ Ignoring Failed Checks + +A red X means something's wrong. Fix it before merging. + +## What's Next? + +You now know how to maintain a healthy CI/CD pipeline! Let's cover troubleshooting for when things go wrong. + +👉 **Next: [Troubleshooting →](./08-troubleshooting.md)** + +--- + +💡 **Tip**: Bookmark this page! Come back to it when making CI/CD changes. diff --git a/application/docs/methodology/ci-cd/github/08-troubleshooting.md b/application/docs/methodology/ci-cd/github/08-troubleshooting.md new file mode 100644 index 000000000..6773b263e --- /dev/null +++ b/application/docs/methodology/ci-cd/github/08-troubleshooting.md @@ -0,0 +1,452 @@ +--- +sidebar_position: 8 +--- + +# Troubleshooting + +Running into issues? This guide will help you diagnose and fix common problems. + +## Workflow Not Running + +### Symptoms + +- Workflow doesn't appear in Actions tab +- No checks on pull requests +- Push to main doesn't trigger anything + +### Diagnosis + +**Step 1: Check file location** + +```bash +ls -la .github/workflows/ +``` + +Workflows must be in `.github/workflows/` directory (note the `.` at the start). + +**Step 2: Verify YAML syntax** + +Use [YAML Lint](http://www.yamllint.com/) to check for syntax errors. + +Common YAML mistakes: + +```yaml +# ❌ Wrong indentation +jobs: +ci: + runs-on: ubuntu-latest + +# ✅ Correct +jobs: + ci: + runs-on: ubuntu-latest +``` + +**Step 3: Check workflow triggers** + +```yaml +# Only runs on push to main +on: + push: + branches: [main] +# Does NOT run on: +# - Pull requests +# - Pushes to other branches +# - Tags +``` + +### Solutions + +**Solution 1: Move files to correct location** + +```bash +mkdir -p .github/workflows +mv workflows/*.yml .github/workflows/ +``` + +**Solution 2: Fix YAML syntax** + +- Use 2 spaces for indentation (not tabs) +- Check quotes and brackets match +- Validate with online YAML validator + +**Solution 3: Check you're pushing to the right branch** + +```bash +git branch # Should show * main or your PR branch +git push origin main # Push to main +``` + +## Build Failures + +### Symptoms + +- Red X on CI checks +- "Process completed with exit code 1" +- Tests or builds fail in CI but work locally + +### Diagnosis + +**Step 1: Read the logs** + +1. Go to **Actions** tab +2. Click the failed workflow run +3. Click the failed job +4. Expand the failed step +5. Read the error message + +**Step 2: Check common issues** + +**Missing build/test commands (example for Node.js):** + +```json +// package.json must have: +{ + "scripts": { + "build": "...", + "test": "...", + "lint": "..." + } +} +``` + +For other ecosystems, make sure equivalent commands exist (e.g., `poetry run pytest`, `go test ./...`, `mvn verify`). + +**Wrong working directory:** + +```yaml +# If your app is in ./app not ./application +with: + working-directory: app # Update this +``` + +**Wrong artifact path:** + +```yaml +# If build outputs to ./build not ./dist +with: + build: | + { + "artifact": ["application/build"] # Update this + } +``` + +### Solutions + +**Solution 1: Test locally** + +```bash +# Run the same commands CI runs +make prepare +make lint +make build +make test +make ci +``` + +If these fail locally, fix your code. If they pass locally but fail in CI, continue... + +**Solution 2: Check runtime / toolchain version** + +Ensure your local environment matches the version CI uses: + +```bash +node --version # Reference repo uses Node.js 20.x +python --version # For Python projects +go version # For Go projects +``` + +Declare the requirement in your project configuration (`package.json` engines, `.python-version`, `go.mod`, etc.) so contributors use the same versions. + +**Solution 3: Clean dependencies (run inside the application container)** + +Open the repository in the devcontainer or enter it via your wrapper (`make shell`). The devcontainer is a tooling image (Docker CLI, DIND helpers and editor extensions) and should not be used as the application runtime. Use it to run the application container which executes the install/build/test steps. Example (uses repository `docker-compose.yml` and the `app` service): + +```bash +# Run build/test inside the application container so it matches CI +docker compose -f docker-compose.yml run --rm app bash -lc "cd application && rm -rf node_modules package-lock.json && npm ci && npm run build" +``` + +**Solution 4: Check environment variables** + +If your app needs environment variables: + +```yaml +# In workflow file +env: + NODE_ENV: production + API_URL: ${{ secrets.API_URL }} +``` + +## Deployment Failures + +### Symptoms + +- CI passes but deployment fails +- "Artifact not found" error +- Site shows 404 after deployment + +### Diagnosis + +**Step 1: Check if CI created artifact** + +1. Go to failed deployment workflow +2. Look at the `ci` job +3. Scroll to bottom +4. Should see "Uploading artifact" + +**Step 2: Verify build output exists** + +```bash +# Run build locally +make build + +# Check output directory +ls -la application/dist # or application/build +``` + +**Step 3: Check deployment platform settings** + +- Kubernetes/ArgoCD: Ensure the ArgoCD application watches the branch or manifests you update and that the cluster is reachable +- Container registry: Confirm repository permissions, tokens, and visibility (private/public) allow pushes from CI +- Optional targets (S3, CloudFront, etc.): Verify buckets/distributions exist and credentials are valid +- Workflow triggers: For review apps, confirm the comment text matches `/deploy` and that the commenter has permission; for releases, verify the workflow_dispatch inputs reference a valid image tag + +### Solutions + +**Solution 1: Fix artifact or image or helm chart tag mismatch** + +If you rely on build artifacts: + +```yaml +build: | + { + "artifact": ["application/dist"] + } +``` + +Ensure the same artifact name is used in any `actions/download-artifact@ # v4.x.x` step. + +If you deploy containers, double-check that the image tag you push (for example `${{ github.sha }}`) matches the value ArgoCD expects in your manifests or image updater configuration. + +**Solution 2: Confirm platform-specific manifests** + +- Kubernetes: validate that Deployment/StatefulSet manifests reference the pushed image tag and that ConfigMaps/Secrets exist +- Helm/Kustomize: run a local `helm template` or `kustomize build` to ensure manifests render correctly before ArgoCD applies them +- Other targets (S3, CloudFront, etc.): make sure required config files (`staticwebapp.config.json`, `app.yaml`, etc.) are present in the artifact + +**Solution 3: Review permissions and secrets** + +```yaml +publish-image: + permissions: + contents: read + packages: write +``` + +Add any extra scopes required by cloud providers (e.g., `id-token: write` for OIDC federation). Reissue tokens if they expired or lost scopes. + +**Solution 4: Validate ArgoCD connectivity** + +- Test the ArgoCD credentials locally (`argocd app sync --dry-run`) +- Check the ArgoCD UI for sync or health errors +- Confirm network policies or firewalls allow the cluster to pull images from your registry +- For comment-driven workflows, verify GitHub delivered the `issue_comment` event by checking the workflow run history + +## Semantic PR Check Failing + +### Symptoms + +- "Semantic Pull Request" check fails +- PR title appears correct but still fails + +### Diagnosis + +Check if title follows format: + +``` +type: description + +Where type is one of: +- feat, fix, docs, style, refactor +- perf, test, build, ci, chore, revert +``` + +### Solutions + +**Common mistakes:** + +``` +❌ "Added new feature" +✅ "feat: add new feature" + +❌ "Fix: bug in login" (capital F) +✅ "fix: bug in login" + +❌ "feature: add login" (should be "feat") +✅ "feat: add login" + +❌ "fix bug in login" (missing colon) +✅ "fix: bug in login" +``` + +**Scopes are optional:** + +``` +✅ "feat: add login" +✅ "feat(auth): add login" (both valid) +``` + +## Performance Issues + +### Symptoms + +- Workflows take too long +- Hitting GitHub Actions minutes limit +- Slow feedback on PRs + +### Diagnosis + +Check workflow duration: + +1. Go to **Actions** tab +2. Note how long workflows take +3. Click into a workflow +4. Check which step is slowest + +### Solutions + +**Solution 1: Parallel jobs already enabled** + +The Hoverkraft workflows already run tests, linting, and building in parallel. You're already optimized! + +**Solution 2: Reduce test time** + +```bash +# Run fewer tests in CI +npm test -- --maxWorkers=2 +``` + +**Solution 3: Cache is working** + +Hoverkraft workflows auto-cache. Verify: + +1. Click into workflow +2. Look for "Cache restored" messages +3. Second runs should be faster + +**Solution 4: Skip redundant work** + +Already handled by: + +```yaml +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +``` + +## Permission Errors + +### Symptoms + +- "Resource not accessible by integration" +- "Insufficient permissions" + +### Solutions + +**Solution 1: Check workflow permissions** + +```yaml +permissions: + contents: read # Add needed permissions + security-events: write + id-token: write +``` + +**Solution 2: Check repository settings** + +1. Go to **Settings** → **Actions** → **General** +2. Scroll to "Workflow permissions" +3. Select "Read and write permissions" +4. Save + +**Solution 3: Check branch protection** + +Required checks must match workflow names exactly. + +## Dependabot Issues + +### Symptoms + +- No Dependabot PRs +- Dependabot PRs failing CI + +### Solutions + +**Solution 1: Enable Dependabot** + +1. Go to **Settings** → **Code security and analysis** +2. Enable "Dependabot alerts" +3. Enable "Dependabot security updates" + +**Solution 2: Check dependabot.yml** + +```yaml +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/application" # Must match your structure + schedule: + interval: "weekly" +``` + +**Solution 3: Dependabot PR failures** + +Dependabot PRs must pass CI like any other PR. If they fail: + +1. Check the error logs +2. Usually it's a breaking change +3. Review the update before merging + +## Getting More Help + +### Check the Logs + +Always start here: + +1. **Actions** tab +2. Click failed workflow +3. Read the error message +4. Check the full logs + +### Documentation + +- [GitHub Actions Docs](https://docs.github.com/en/actions) +- [Hoverkraft CI/CD Common](https://hoverkraft-tech.github.io/ci-github-common/) +- [Hoverkraft CI/CD Node.js](https://hoverkraft-tech.github.io/ci-github-nodejs/) + +### Ask for Help + +- [Hoverkraft Discussions](https://github.com/orgs/hoverkraft-tech/discussions) +- GitHub Issues in the relevant repository +- Stack Overflow (tag: GitHub Actions) + +### Debug Mode + +Enable debug logs: + +1. Go to **Settings** → **Secrets and variables** → **Actions** +2. Add `ACTIONS_STEP_DEBUG` = `true` +3. Add `ACTIONS_RUNNER_DEBUG` = `true` +4. Re-run failed workflow +5. Much more detailed logs! + +## What's Next? + +You now have a complete CI/CD setup and know how to fix common issues! For reference, check out the workflow documentation. + +👉 **Next: [Workflow Reference →](./09-reference.md)** + +--- + +💡 **Tip**: Most issues are simple fixes. Read the error message carefully – it usually tells you exactly what's wrong! diff --git a/application/docs/methodology/ci-cd/github/09-reference.md b/application/docs/methodology/ci-cd/github/09-reference.md new file mode 100644 index 000000000..d91267ed5 --- /dev/null +++ b/application/docs/methodology/ci-cd/github/09-reference.md @@ -0,0 +1,292 @@ +--- +sidebar_position: 9 +--- + +# Workflow Reference + +Use this page as a quick reference while wiring Hoverkraft reusable workflows. The defaults target a single deployable app under `application/` with a multi-stage Dockerfile at `docker/application/Dockerfile`. When you run multiple services (microservices, monorepos, workers), expand the same patterns by adding entries per service. + +> **Reminder**: The `.devcontainer` image is tooling only (editor extensions, Docker CLI). Run build, lint, and deploy commands inside the application containers defined in `docker/application/Dockerfile` (and any additional `docker//Dockerfile` you add) so CI and local environments stay aligned. + +## Reusable Workflow Catalog + +### `hoverkraft-tech/ci-github-common` + +| Workflow | Purpose | +| --------------------------- | ---------------------------------------------------- | +| `linter.yml` | Configurable super-linter with SARIF support | +| `semantic-pull-request.yml` | Enforces Conventional Commit pull request titles | +| `greetings.yml` | Welcomes first-time contributors | +| `stale.yml` | Marks inactive issues and pull requests | +| `need-fix-to-issue.yml` | Logs “changes requested” reviews as follow-up issues | + +Pin each workflow to a tested commit SHA (e.g., `@1c379f7f6e0fc850fe5a7111f74d54e159b4dcd2 # 0.26.0`) and monitor [releases](https://github.com/hoverkraft-tech/ci-github-common/releases) for updates. + +### `hoverkraft-tech/ci-github-container` + +| Workflow / Action | Purpose | +| ------------------------------------------------------- | ---------------------------------------------------------------------- | +| `.github/workflows/docker-build-images.yml` | Builds multi-stage images and exposes metadata (`built-images` output) | +| `.github/workflows/prune-pull-requests-images-tags.yml` | Cleans stale images/tags generated by PR builds | +| `actions/helm/test-chart` | Runs `ct lint` and `helm kubeconform` using built image metadata | +| `actions/helm/generate-docs` | Regenerates Helm chart documentation (`helm-docs`) | + +Provide an OCI registry (`GHCR`, `ECR`, etc.) via `vars.OCI_REGISTRY` and pin the workflow to a validated commit (e.g., `@4f29319e02dd65152386c436e8c3136f380a0e71 # 0.28.0`). + +### `hoverkraft-tech/ci-github-publish` + +| Workflow / Action | Purpose | +| --------------------------------------- | ---------------------------------------------- | +| `.github/workflows/deploy-chart.yml` | Deploy Helm charts through GitHub App + GitOps | +| `.github/workflows/clean-deploy.yml` | Tear down review environments | +| `.github/workflows/prepare-release.yml` | Draft release notes, collect change summaries | +| `actions/release/create` | Create GitHub Releases with semantic tagging | + +Requires GitHub App credentials (`CI_BOT_APP_ID`, `CI_BOT_APP_PRIVATE_KEY`). Pin to the release commit you validated (e.g., `@42d50a3461a177557ca3f83b1d927d7c0783c894 # 0.11.2`). + +### Optional: Language-Specific Workflows + +If a service cannot run inside a container (legacy runtimes, SaaS builds), reuse the language-specific workflows (`ci-github-nodejs`, etc.). Prefer the container-first approach when possible to keep the stack agnostic. + +## Blueprint Snippets + +### Shared CI (`__shared-ci.yml`) + +```yaml title=".github/workflows/__shared-ci.yml" +name: Shared – Continuous Integration + +on: + workflow_call: + +jobs: + linter: + uses: hoverkraft-tech/ci-github-common/.github/workflows/linter.yml@ + + build: + uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@ + with: + oci-registry: ${{ vars.OCI_REGISTRY }} + images: | + [ + { + "name": "ci", + "context": ".", + "dockerfile": "./docker/application/Dockerfile", + "build-args": { "APP_PATH": "./application/" }, + "target": "ci", + "platforms": ["linux/amd64"] + }, + { + "name": "application", + "context": ".", + "dockerfile": "./docker/application/Dockerfile", + "build-args": { "APP_PATH": "./application/" }, + "target": "prod", + "platforms": ["linux/amd64"] + } + ] + + sast: + needs: build + container: + image: ${{ fromJSON(needs.build.outputs.built-images).ci.images[0] }} + steps: + - run: ./scripts/run-static-analysis.sh + + report-sast: + if: github.event_name == 'pull_request' + needs: sast + steps: + - uses: actions/download-artifact@ + with: + name: lint-report + - uses: ataylorme/eslint-annotate-action@ + with: + report-json: lint-report.json + + tests-charts: + needs: build + steps: + - uses: hoverkraft-tech/ci-github-container/actions/helm/test-chart@ + with: + helm-set: | + image.registry=${{ fromJSON(needs.build.outputs.built-images).application.registry }} + image.repository=${{ fromJSON(needs.build.outputs.built-images).application.repository }} + image.tag=${{ fromJSON(needs.build.outputs.built-images).application.tags[0] }} + image.digest=${{ fromJSON(needs.build.outputs.built-images).application.digest }} + oci-registry: ${{ vars.OCI_REGISTRY }} + oci-registry-password: ${{ github.token }} +``` + +Extend the `images` array and downstream references (`service-b`, `worker`, etc.) whenever you build more than one artifact. + +### Wrapper Workflows + +```yaml title=".github/workflows/pull-request-ci.yml" +name: Pull request – Continuous Integration + +on: + pull_request: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + ci: + uses: ./.github/workflows/__shared-ci.yml + secrets: inherit +``` + +```yaml title=".github/workflows/main-ci.yml" +name: Main – Continuous Integration + +on: + push: + branches: [main] + +jobs: + clean: + uses: hoverkraft-tech/ci-github-container/.github/workflows/prune-pull-requests-images-tags.yml@ + with: + images: '["ci","application"]' + + ci: + uses: ./.github/workflows/__shared-ci.yml + secrets: inherit + + helm-docs: + needs: ci + steps: + - uses: actions/checkout@ + - uses: hoverkraft-tech/ci-github-container/actions/helm/generate-docs@ + with: + working-directory: ./charts + github-app-id: ${{ vars.CI_BOT_APP_ID }} + github-app-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }} +``` + +### Deployment Entry Points + +```yaml title=".github/workflows/deploy.yml" +name: Deploy chart + +on: + issue_comment: + types: [created] + workflow_call: + inputs: + tag: + description: "Image tag to deploy" + required: true + type: string + environment: + description: "review | uat | production" + required: true + type: string + +permissions: + contents: write + issues: write + packages: write + pull-requests: write + deployments: write + actions: read + id-token: write + +jobs: + deploy: + uses: hoverkraft-tech/ci-github-publish/.github/workflows/deploy-chart.yml@ + secrets: + oci-registry-password: ${{ secrets.GITHUB_TOKEN }} + github-app-key: ${{ secrets.CI_BOT_APP_PRIVATE_KEY }} + with: + url: ${{ (inputs.environment == 'uat' && vars.UAT_URL) || (inputs.environment == 'production' && vars.PRODUCTION_URL) || vars.REVIEW_APPS_URL }} + tag: ${{ inputs.tag }} + environment: ${{ inputs.environment }} + github-app-id: ${{ vars.CI_BOT_APP_ID }} + deploy-parameters: | + { "repository": "${{ github.repository_owner }}/argocd-app-of-apps" } + images: | + [ + { "name": "application", "context": ".", "dockerfile": "./docker/application/Dockerfile", "target": "prod" } + ] + chart-values: | + [ + { "path": "application.image", "image": "application" }, + { "path": "application.version", "value": "{{ tag }}" }, + { "path": "deploy.ingress.hosts[0].host", "value": "{{ url }}" } + ] +``` + +Duplicate the `images` and `chart-values` entries per service (`service-b`, worker queues, etc.). Add `clean-deploy.yml`, `prepare-release.yml`, and `release.yml` pinned to the same commit. + +## Secrets and Variables Cheat Sheet + +| Name | Type | Used by | +| ---------------------------- | -------- | ------------------------------------------ | +| `OCI_REGISTRY` | Variable | Container build + Helm test workflows | +| `CI_BOT_APP_ID` | Variable | Deploy + Helm docs workflows | +| `REVIEW_APPS_URL` | Variable | `deploy.yml` (review environment URL base) | +| `UAT_URL` / `PRODUCTION_URL` | Variable | `deploy.yml`, `release.yml` | +| `CI_BOT_APP_PRIVATE_KEY` | Secret | Deploy, release, Helm docs | +| Registry credentials | Secret | Only when pushing outside GHCR | + +Document runtime versions (`.tool-versions`, `.nvmrc`, `.python-version`, etc.) and include them in Dependabot so upgrades arrive as PRs. + +## Pinning Strategy + +Always pin workflows and actions by commit SHA: + +```yaml +uses: hoverkraft-tech/ci-github-container/.github/workflows/docker-build-images.yml@4f29319e02dd65152386c436e8c3136f380a0e71 # 0.28.0 +``` + +Avoid `@main` or branch names in production pipelines. When Dependabot proposes an update, test the new commit in a branch before merging. + +## Staying Up to Date + +- Enable Dependabot for `github-actions`, `docker`, and every language ecosystem you ship. +- Review release notes for pinned workflows before bumping their SHAs. +- Note version bumps in PR descriptions so reviewers can audit changes quickly. + +## Local Command Reference + +```bash +# Scaffold local tooling (builds containers, installs dependencies) +make prepare + +# Run static analysis +make lint + +# Build application artifacts +make build + +# Execute the same bundle CI runs +make ci + +# Open a shell inside the application container +make shell +``` + +Swap `make` for any task runner (`just`, `task`, `npm scripts`) as long as the commands use the same Docker targets consumed by CI. + +## Quick Checks Before Pushing + +```bash +ls -la .github/workflows/ # Verify workflows exist +yamllint .github/workflows/*.yml # Validate YAML syntax +# act --list # Optional: list workflows if you use act +``` + +## Need More Help? + +- Revisit the [tutorial introduction](./01-getting-started.md) +- Consult [Troubleshooting](./08-troubleshooting.md) +- Join the [Hoverkraft discussions](https://github.com/orgs/hoverkraft-tech/discussions) +- Read the documentation for each reusable workflow linked above + +--- + +🎉 **Congratulations!** Keep this reference handy whenever you modify workflows or onboard a new service. diff --git a/application/docs/methodology/ci-cd/github/index.md b/application/docs/methodology/ci-cd/github/index.md new file mode 100644 index 000000000..1371f37d3 --- /dev/null +++ b/application/docs/methodology/ci-cd/github/index.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +--- + +# GitHub Actions CI/CD Tutorial + +Implement CI/CD using GitHub Actions with Hoverkraft reusable workflows. The steps are stack-agnostic—whether you ship a single application, a monorepo, or container images, you can adapt the same patterns by tuning paths and inputs called out in each section. + +## Tutorial Pages + +1. **[Getting Started](./01-getting-started.md)** - Prerequisites and overview +2. **[Project Structure](./02-project-structure.md)** - Repository layout and build tools +3. **[Core Workflows](./03-core-workflows.md)** - Essential CI/CD workflows +4. **[Community Workflows](./04-community-workflows.md)** - Optional automation +5. **[Deployment Setup](./05-deployment.md)** - On-demand deployment flows +6. **[Testing Your Setup](./06-testing.md)** - Verification walkthrough +7. **[Best Practices](./07-best-practices.md)** - Security and performance tips +8. **[Troubleshooting](./08-troubleshooting.md)** - Common issues and solutions +9. **[Workflow Reference](./09-reference.md)** - Quick reference guide + +## Who This Is For + +- Developers learning Hoverkraft methodology, implementing CI/CD +- Teams standardizing CI/CD across projects +- Anyone needing production-ready GitHub Actions workflows + +## Time Required + +- **Core CI/CD**: 30 minutes +- **Full setup**: 60 minutes +- **With deployment**: 90 minutes + +## 🚀 What You'll Build + +By the end of this tutorial, your project will have: + +✅ Automated testing on every pull request +✅ Automated builds on every commit +✅ On-demand deployments (review apps + releases) +✅ Community management automation +✅ Security scanning +✅ Dependency updates + +## Approach + +**Linear**: Follow pages 1-9 in order +**Selective**: Jump to specific sections as needed + +## Start + +👉 **[Getting Started →](./01-getting-started.md)** + +--- + +Need help? [Hoverkraft Discussions](https://github.com/orgs/hoverkraft-tech/discussions) diff --git a/application/docs/methodology/ci-cd/intro.md b/application/docs/methodology/ci-cd/intro.md new file mode 100644 index 000000000..9f4802d2f --- /dev/null +++ b/application/docs/methodology/ci-cd/intro.md @@ -0,0 +1,164 @@ +--- +sidebar_position: 0 +--- + +# CI/CD Overview + +Continuous Integration and Continuous Deployment (CI/CD) are essential practices for modern software development. This section provides comprehensive guides for implementing CI/CD pipelines following Hoverkraft best practices. + +## What is CI/CD? + +**Continuous Integration (CI)** is the practice of automatically building and testing code changes as they are committed to version control. This ensures that new code integrates smoothly with the existing codebase and meets quality standards. + +**Continuous Deployment (CD)** automatically deploys code that passes all tests to production or staging environments, enabling rapid and reliable releases. + +## Why CI/CD Matters + +### Benefits + +1. **Early Bug Detection**: Automated tests catch issues before they reach production +2. **Faster Release Cycles**: Automated deployment eliminates manual steps +3. **Improved Code Quality**: Consistent checks ensure standards are met +4. **Reduced Risk**: Small, frequent changes are easier to debug and rollback +5. **Developer Productivity**: Automation frees developers to focus on features +6. **Consistent Deployments**: Automated processes eliminate human error + +### Hoverkraft Approach + +The Hoverkraft CI/CD methodology focuses on: + +- **Reusability**: Share workflows across projects +- **Standardization**: Common patterns for similar project types +- **Security**: Built-in scanning and best practices +- **Simplicity**: Easy to understand and maintain +- **Flexibility**: Adaptable to different project needs + +## Platform Guides + +### GitHub Actions + +Our most comprehensive CI/CD guide covers GitHub Actions from basic setup to advanced deployment strategies: + +👉 **[GitHub Actions CI/CD Tutorial](./github/)** + +This step-by-step tutorial includes: + +- Getting started guide for beginners +- Project structure requirements +- Core and community workflows +- Deployment setup +- Testing and troubleshooting +- Best practices and reference documentation + +## Hoverkraft CI/CD Ecosystem + +Hoverkraft provides several repositories with reusable workflows and actions: + +### Core Repositories + +1. **[ci-github-common](https://github.com/hoverkraft-tech/ci-github-common)** - Common workflows for all projects + - Semantic PR validation + - Community management + - Issue automation + +2. **[ci-github-nodejs](https://github.com/hoverkraft-tech/ci-github-nodejs)** - Node.js specific workflows + - Complete CI pipeline + - Build, test, and artifact management + - Security scanning + +3. **[ci-github-container](https://github.com/hoverkraft-tech/ci-github-container)** - Container workflows + - Docker image building + - Multi-platform support + - Registry publishing + +4. **[ci-github-publish](https://github.com/hoverkraft-tech/ci-github-publish)** - Publishing actions + - GitHub Pages deployment + - Artifact publishing + +5. **[compose-action](https://github.com/hoverkraft-tech/compose-action)** - Docker Compose integration + - Service orchestration in CI + - Automatic cleanup + +## Common Workflow Patterns + +### Pull Request Workflow + +``` +PR opened → CI runs → Tests pass → Review → Merge → Deploy +``` + +1. Developer creates a pull request +2. CI workflow automatically triggers +3. Code is built and tested +4. Security scans run +5. Review process begins +6. After approval and merge, trigger the release workflow to deploy + +### Main Branch Workflow + +``` +Commit to main → CI runs → Tests pass → Build artifacts → Deploy +``` + +1. Code is merged to main branch +2. Full CI pipeline executes +3. Build artifacts are created +4. On-demand release workflow pushes to production +5. Monitoring and verification + +## Getting Started + +1. **Review the [GitHub Actions Tutorial](./github/)** for detailed implementation steps +2. **Choose appropriate reusable workflows** for your project type +3. **Customize and implement** in your repository +4. **Test thoroughly** before enabling release workflows + +## Best Practices + +### Security + +- Always pin workflow versions with SHA +- Use minimal required permissions +- Scan dependencies and code for vulnerabilities +- Protect sensitive data with secrets + +### Performance + +- Cache dependencies when possible +- Use concurrency controls to cancel redundant runs +- Run independent jobs in parallel +- Optimize test execution time + +### Maintainability + +- Keep workflows simple and focused +- Use reusable workflows to avoid duplication +- Document custom logic and decisions +- Version pin with comments for tracking + +### Testing + +- Test locally before committing +- Use branch protection rules +- Require status checks before merging +- Implement comprehensive test coverage + +## Support and Resources + +- **Documentation**: Each CI/CD repository has detailed documentation +- **Examples**: Real-world implementations in Hoverkraft projects +- **Community**: [GitHub Discussions](https://github.com/orgs/hoverkraft-tech/discussions) +- **Issues**: Report problems in respective repositories + +## Contributing + +Help improve the Hoverkraft CI/CD ecosystem: + +1. Share feedback on workflows +2. Contribute improvements to reusable workflows +3. Document your use cases and patterns +4. Help other users in discussions + +--- + +Ready to implement CI/CD? Start with the **[GitHub Actions Tutorial](./github/)** → diff --git a/application/docs/methodology/intro.md b/application/docs/methodology/intro.md new file mode 100644 index 000000000..2e8e6cd87 --- /dev/null +++ b/application/docs/methodology/intro.md @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# Hoverkraft Methodology + +Welcome to the Hoverkraft methodology documentation. This section provides comprehensive guides on best practices, standards, and recommended approaches for building and maintaining software projects using the Hoverkraft ecosystem. + +## What is the Hoverkraft Methodology? + +The Hoverkraft methodology is a collection of proven practices, tools, and workflows designed to help teams build high-quality software efficiently. It emphasizes: + +- **Modularity**: Reusable components and workflows +- **Consistency**: Standardized approaches across projects +- **Automation**: Minimize manual tasks through CI/CD +- **Quality**: Built-in checks and best practices +- **Security**: Security-first approach in all aspects +- **Community**: Open-source collaboration and transparency + +## Documentation Sections + +### CI/CD + +Learn how to implement continuous integration and continuous deployment using modern DevOps practices: + +- **[GitHub Actions](./ci-cd/github/)**: Step-by-step tutorial for structuring CI/CD pipelines with GitHub Actions, including comprehensive guides from getting started to deployment and troubleshooting. + +## Key Principles + +### 1. Infrastructure as Code + +All infrastructure and deployment configurations should be version-controlled and reproducible. + +### 2. Automated Testing + +Every project should have automated tests that run on every change, ensuring quality and preventing regressions. + +### 3. Continuous Integration + +All code changes should be integrated frequently and validated automatically through CI pipelines. + +### 4. Continuous Deployment + +Successful builds on the main branch should be automatically deployed to appropriate environments. + +### 5. Security by Default + +Security scanning and best practices should be built into every workflow, not added as an afterthought. + +### 6. Documentation + +All projects should have clear, up-to-date documentation that includes setup instructions, architecture decisions, and contribution guidelines. + +## Getting Started + +1. **Choose Your Technology Stack**: Browse the CI/CD section for guides specific to your project type +2. **Review Examples**: Check out real-world implementations in Hoverkraft repositories +3. **Adapt and Implement**: Customize the templates and workflows for your specific needs +4. **Iterate and Improve**: Continuously refine your processes based on team feedback + +## Contributing + +The Hoverkraft methodology is continuously evolving based on community feedback and industry best practices. If you have suggestions or improvements: + +1. Open a discussion in the [Hoverkraft discussions](https://github.com/orgs/hoverkraft-tech/discussions) +2. Submit a pull request to the documentation repository +3. Share your experience and learnings with the community + +## Support + +For questions or support: + +- Visit [GitHub Discussions](https://github.com/orgs/hoverkraft-tech/discussions) +- Review project-specific documentation in individual repositories +- Check the [Projects page](../projects.md) for relevant repositories diff --git a/application/docusaurus.config.ts b/application/docusaurus.config.ts index 302adc7ec..eb8c3a929 100644 --- a/application/docusaurus.config.ts +++ b/application/docusaurus.config.ts @@ -46,21 +46,6 @@ const config: Config = { editUrl: 'https://github.com/hoverkraft-tech/public-docs/tree/main/', }, - blog: { - showReadingTime: true, - feedOptions: { - type: ['rss', 'atom'], - xslt: true, - }, - // Please change this to your repo. - // Remove this to remove the "edit this page" links. - editUrl: - 'https://github.com/hoverkraft-tech/public-docs/tree/main/', - // Useful options to enforce blogging best practices - onInlineTags: 'warn', - onInlineAuthors: 'warn', - onUntruncatedBlogPosts: 'warn', - }, theme: { customCss: './src/css/custom.css', },