Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions docs/projects/app/ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# App CI (Stage 3)

This repo uses GitHub Actions to ensure every PR is validated and every merge to
`main` produces a deployable artifact.

## Goals (Stage 3)

- PRs: fail fast on docs + workflow mistakes, and prove the app still boots.
- main: publish a container image to GHCR.

## Workflows involved

- `.github/workflows/ci.yml`
- Lints GitHub Actions workflows (actionlint)
- Docs quality checks (markdownlint + lychee)
- PR-only: build container + smoke test via Docker Compose

- `.github/workflows/publish-image.yml`
- Builds the app image
- Pushes to GHCR on `main`

## What runs on pull requests

### 1) Workflow lint: actionlint

Purpose: catch invalid inputs, typos, wrong action parameters, invalid contexts,
and similar mistakes before merge.

Where: `ci.yml` job `actionlint`

Expected outcome:

- Workflow YAML is valid
- Incorrect action inputs are rejected (for example, passing `context` to
`docker/setup-buildx-action`, which does not support it)

### 2) Docs quality gates

Where: `ci.yml` job `docs-quality`

- Markdown lint (format consistency)
- Link check (keeps repo clean)

### 3) App container: build + smoke test

Where: `ci.yml` job `app-container-pr`

Steps:

1. Build the app image with Buildx (`docker/build-push-action`) and load it into
the runner Docker daemon.
2. Start the Compose stack from `projects/app/`.
3. Validate the HTTP health endpoint.

Smoke test commands (conceptually):

- `docker compose up -d --wait`
- `docker compose ps`
- `curl http://localhost:8000/healthz`

Notes:

- The curl check can fail if the app container is still starting even though
Compose has started the container. The job should rely on service health and
/or retry the curl check briefly.

## What runs on push to main

### Publish container image to GHCR

Where: `publish-image.yml`

Image name:

- `ghcr.io/<owner>/<repo>/app`

Tags:

- `latest`
- `sha-<git-sha>` (or `sha` tag style produced by metadata-action)

Authentication:

- Uses `GITHUB_TOKEN` with `packages: write`

## Artifacts produced

- GHCR container image:
- `ghcr.io/viprapp/jevops/app:latest`
- `ghcr.io/viprapp/jevops/app:sha-...`

## How to verify quickly

### Check CI on a PR

- Open the PR
- Ensure these checks pass:
- actionlint
- docs-quality
- app - build + smoke test (PR)

### Check publish on main

- Merge PR to `main`
- Confirm `publish-image` workflow run succeeded
- Confirm tags exist in GHCR for the repo

## Common issues and how we catch them

- Wrong paths (for example wrong Dockerfile path):
- Caught by actionlint (workflow validation) and by the container build step
- Wrong action inputs:
- Caught by actionlint (example: invalid inputs to setup-buildx-action)
- Compose starts but app not ready yet (curl reset/refused):
- Fix by waiting for health or adding small curl retry loop