# CI/CD Pipeline for Ghaymah ## Pipeline overview The workflow builds the API from `q1-deploy-monitor/app`, embeds the Git commit SHA in the image, and publishes immutable SHA and `latest` tags to Docker Hub. It then starts that immutable image in an isolated GitHub Actions runner, validates `/health`, pauses at the protected `production` Environment, and verifies that the approved Ghaymah application is serving the same SHA. ```mermaid flowchart LR A["Commit to main"] --> B["Build image"] B --> C["Push SHA and latest tags
to Docker Hub"] C --> D["Ephemeral staging container
automatic"] D --> E["Health and release check"] E --> F{"Production Environment
required reviewer"} F -->|Approved| G["Ghaymah production"] G --> H["Verify /health
and exact release SHA"] F -->|Rejected| I["Stop promotion"] ``` The free Ghaymah account used for this assessment permits five total resources. The two required deployed applications (`ghaymah-api` and `mithal-monitor`) already consume the available allocation together with their supporting resources. A third Ghaymah application was tested and rejected by the platform with the documented account message `Resource limit exceeded ... maximum 5 resources`. Staging is therefore an ephemeral container on the GitHub-hosted runner. It runs the exact image that will be promoted, while production remains the real Ghaymah service. The workflow runs on a push to `main` and through `workflow_dispatch`. It uses: | Setting | Purpose | |---|---| | Secret `DOCKERHUB_USERNAME` | Docker Hub account and image namespace. | | Secret `DOCKERHUB_TOKEN` | Read/write Docker Hub access token. | | Variable `GHAYMAH_STAGING_APP` | Display name for the ephemeral staging service. | | Variable `GHAYMAH_PRODUCTION_APP` | Name of the deployed Ghaymah application. | | Variable `GHAYMAH_PRODUCTION_URL` | Public base URL used for the production verification. | Images are published as: ```text docker.io/agamy74/ghaymah-api: docker.io/agamy74/ghaymah-api:latest ``` Only the SHA tag is promoted. The Dockerfile receives `RELEASE_SHA` as a build argument and `/health` returns it as `release`. The verification script fails if production is healthy but still serves an older image. ## Manual approval The production gate is implemented through a GitHub Environment named `production`: ```yaml environment: production ``` Required reviewers are configured in **Settings → Environments → production**, not in YAML. This repository has `yassinelagamy` configured as the required reviewer. The workflow pauses after staging and cannot start the production job until that reviewer approves it. Because Ghaymah CLI `0.0.24` does not document non-interactive token authentication or the external-image update field, promotion currently uses this controlled procedure: 1. The workflow builds and verifies the immutable image in staging. 2. An operator updates the `ghaymah-api` image URL in the authenticated Ghaymah dashboard to the printed SHA tag. 3. The required reviewer approves the GitHub `production` Environment. 4. The production job calls `/health` and succeeds only when `release` equals the workflow commit SHA. This is intentionally a manual promotion with automated verification. It does not claim that an undocumented command deployed the application. ## Staging vs Production | Area | Staging | Production | |---|---|---| | Purpose | Validate the exact candidate image before promotion. | Serve the public workload on Ghaymah. | | Data | Synthetic or disposable test data. | Real application data and traffic. | | Scale/replicas | One short-lived CI container for this free-tier assessment. | Ghaymah instance sized for availability and measured demand. | | Secrets | Only build/test credentials; no production secrets. | Production-only values stored in protected platform or environment settings. | | Access control | Reachable only inside the GitHub Actions runner. | Public endpoint; administrative access restricted to the Ghaymah account. | | Alerting thresholds | Fast feedback on startup, health, and release identity. | SLO-based uptime, latency, memory, restart, and OOM alerts. | | Deploy cadence | Automatic on each push to `main`. | Manual promotion after successful staging. | | Who can approve | No reviewer required. | Required reviewer on the GitHub `production` Environment. | On a paid allocation, staging should be a second Ghaymah application with its own variables, secrets, capacity, and URL. The image and release verification steps remain unchanged. ## Ghaymah CLI integration The verified public CLI installation and inspection commands are: ```bash # Ghaymah-specific installation command confirmed from the official documentation. curl -sSL https://cli.ghaymah.systems/install.sh | bash # Ghaymah-specific commands confirmed with CLI 0.0.24. gy version gy auth login --email '' --password '' gy auth status gy resource project get gy resource app init --project-id '' --name '' gy resource app launch . gy resource app logs gy resource app update '' --set '' ``` The workflow installs the CLI and runs `gy version` in both deployment jobs so the integration dependency is continuously checked. It does not place a user password in CI. Public CLI help for version `0.0.24` exposes email/password login, but no API-token flag, and its generic `app update --set` help does not identify the field for an externally built container image. The authenticated dashboard does provide a verified deployment route: enter a container image URL, application name, port, public-access choice, environment variables, and an optional registry pull secret, then deploy or update the application. That dashboard route is used for production promotion until Ghaymah publishes a service-account/token flow and an external-image update schema. `scripts/verify_deployment.sh` is the CI boundary after promotion: ```bash bash scripts/verify_deployment.sh \ --app "$GHAYMAH_APP_NAME" \ --url "$GHAYMAH_PRODUCTION_URL" \ --expected-release "$GITHUB_SHA" ``` It retries `/health`, requires `status=ok`, compares the deployed `release` to the approved SHA, writes evidence to the GitHub job summary, and exits nonzero for an unavailable or stale deployment. Official references: - [Ghaymah CLI documentation](https://ghaymah.systems/docs) - [Ghaymah CLI overview](https://ghaymah.systems/cli) - [Docker login action](https://github.com/docker/login-action) - [Docker build and push action](https://github.com/docker/build-push-action)