https://github.com/mockzilla/mockzilla-portable-template
Portable OpenAPI mock server template for Mockzilla with GitHub Actions and hosted API simulations
https://github.com/mockzilla/mockzilla-portable-template
api-simulation api-testing contract-testing developer-tools github-actions golang mock-api mock-server open-source openapi openapi-spec portable-template pull-request-preview
Last synced: 6 days ago
JSON representation
Portable OpenAPI mock server template for Mockzilla with GitHub Actions and hosted API simulations
- Host: GitHub
- URL: https://github.com/mockzilla/mockzilla-portable-template
- Owner: mockzilla
- Created: 2026-03-29T15:13:02.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-14T23:26:23.000Z (6 days ago)
- Last Synced: 2026-05-14T23:29:42.311Z (6 days ago)
- Topics: api-simulation, api-testing, contract-testing, developer-tools, github-actions, golang, mock-api, mock-server, open-source, openapi, openapi-spec, portable-template, pull-request-preview
- Homepage: https://mockzilla.org/
- Size: 46.9 KB
- Stars: 6
- Watchers: 1
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Mockzilla Portable Template
A template for declaring mock API services and publishing them to [Mockzilla](https://github.com/mockzilla/mockzilla).
Drop each service into `services//`, push, and get both a hosted simulation and a downloadable `.mockz` package you can run locally.
## Quick start
1. Click [**Use this template**](https://github.com/mockzilla/mockzilla-portable-template/generate) to create your own repository.
2. Add your services under `services//` (see layout below).
3. Push to main. The included GitHub Actions:
- Publish your specs to a hosted simulation at `https://api.mockz.io/gh///`.
- Pack a `.mockz` archive and attach it to the latest GitHub release for offline use.
## Layout
Each service lives in its own folder under `services/`. The folder name **is** the service identity: what you name it is what gets mounted at.
```
services/
petstore/
openapi.yml # OpenAPI spec (any *.{yml,yaml,json} name works)
config.yml # optional: latency, errors, mount, upstream, cache
context.yml # optional: replacement values for mock data
hello-world/
v1/
get/index.json # → GET /hello-world/v1
post/index.json # → POST /hello-world/v1
app.yml # optional: global settings (port, history, etc.)
```
A service folder is in **static mode** as soon as it contains any
`/index.` file. No `static/` wrapper. The verb defaults to
`GET`; wrap in a `/` dir (`get`, `post`, etc.) as the
immediate parent of `index.` to override. The path before that
can be empty, one segment, or many.
If a folder has both a spec file and static endpoints, the two are
merged: spec endpoints register first, static files override matching
`(path, method)` pairs and add any new ones, and the spec file itself
is served at `GET //` as a literal asset for docs.
Routes the example serves:
```
GET /petstore/pets ← from services/petstore/openapi.yml
POST /petstore/pets
GET /petstore/pets/{petId}
GET /hello-world/v1 ← from services/hello-world/v1/get/index.json
POST /hello-world/v1
```
## Per-service config (`services//config.yml`)
```yaml
latency: 100ms # constant latency
# OR percentile latencies
latencies:
p50: 50ms
p95: 200ms
errors: # percentile error injection
p5: 500 # 5% of requests → 500
mount: pets/v2 # override URL prefix (default: )
upstream: # forward to a real backend
url: https://petstore3.swagger.io/api/v3
timeout: 10s
cache:
requests: true # cache GET responses
```
## Per-service context (`services//context.yml`)
Flat replacement values. Keys are used by the mock generator to fill matching fields in responses. **No service-name wrapper.**
```yaml
name: ["Fluffy", "Spot", "Rover"]
tag: ["cat", "dog", "bird"]
```
## Static responses
Drop response files under `services///index.`. The
verb defaults to `GET`; wrap in a `/` dir (`get`, `post`,
`put`, `patch`, `delete`, `head`, `options`, `trace`) as the
immediate parent of `index.` to override.
```
services/api/
index.json → GET /api
users/index.json → GET /api/users (implicit GET)
users/post/index.json → POST /api/users (explicit method)
users/{id}/index.json → GET /api/users/{id}
users/{id}/delete/index.json → DELETE /api/users/{id}
```
Extension determines content-type:
| Extension | Content-Type |
|---|---|
| `.json` | `application/json` |
| `.html` / `.htm` | `text/html` |
| `.xml` | `application/xml` |
| `.yaml` / `.yml` | `application/yaml` |
| `.txt` | `text/plain` |
If a service folder has only static endpoints (no spec), the OpenAPI
document is synthesized from the file tree at startup.
## Release
Every push to main/master packs your service tree into a `.mockz`
archive (a gzipped tarball with a `.mockzilla.json` manifest declaring
the contained services) and publishes it to the `latest` release.
Run it locally with the mockzilla CLI:
```bash
brew tap mockzilla/tap
brew install mockzilla
curl -L "https://github.com///releases/latest/download/.mockz" -o mocks.mockz
mockzilla mocks.mockz
```
To inspect what's inside before running:
```bash
mockzilla info mocks.mockz
```
## Mockzilla workflow
The included GitHub Actions workflow (`.github/workflows/mockzilla.yml`) publishes your specs to [Mockzilla](https://mockzilla.org) automatically:
- **Push to main/master**: publishes the latest specs to your main simulation
- **Pull request with `Mockzilla` label**: deploys a preview simulation for the PR (torn down when the PR is closed)
The `Mockzilla` label is created automatically on first push via the setup workflow.
Your simulation will be available at:
- `https://api.mockzilla.org/gh/{org}/{repo}/`: main branch
- `https://api.mockzilla.org/gh/{org}/{repo}/pr-{n}/`: per pull request
### Action inputs
You can customize the action in `.github/workflows/mockzilla.yml`:
```yaml
- uses: mockzilla/actions/portable@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
region: us-east-1 # optional. Preferred AWS region, used as a hint on first deploy only.
memory-size: 256 # optional. Memory in MB (default: 128).
timeout: 60 # optional. Request timeout in seconds.
environment: '{"ENV":"production","DEBUG":"true"}' # optional
host: api.mockzilla.net # optional. API host for the simulation URL.
services-dir: services # optional. Directory with per-service folders (default: 'services').
timeout-minutes: 5 # optional. Max minutes to wait for simulation to become active (default: 5).
delete: false # optional. Remove this repository from Mockzilla (default: false).
```
| Input | Required | Description |
|---|---|---|
| `token` | yes | `GITHUB_TOKEN`, used to verify repo identity. |
| `region` | no | Preferred AWS region (e.g. `us-east-1`, `ap-southeast-1`). Used as a hint on first deploy. If at capacity, the nearest available region is used. Has no effect after the simulation is deployed. |
| `memory-size` | no | Memory in megabytes (e.g. `128`, `256`, `512`). Defaults to `128`. |
| `timeout` | no | Request timeout for the simulation in seconds (e.g. `30`, `60`). |
| `environment` | no | JSON object of environment variables to set in the simulation (e.g. `'{"ENV":"production"}'`). |
| `host` | no | API host for the simulation URL (`api.mockzilla.org`, `api.mockzilla.de`, or `api.mockzilla.net`). Defaults to org setting or `api.mockzilla.org`. |
| `services-dir` | no | Directory containing per-service folders. Defaults to `services`. |
| `timeout-minutes` | no | Max minutes the action polls for the simulation to become active. Defaults to `5`. |
| `delete` | no | Remove this repository from Mockzilla. When set to `true`, the action skips publishing and deletes all mock APIs for this repo. Useful on the free plan to free up your slot before connecting a different repository. Defaults to `false`. |
### Removing this repository from Mockzilla
On the free plan you can only have one repository connected to Mockzilla at a time. To switch to a different repo, run the action with `delete: true` on the old one first:
```yaml
name: mockzilla-remove
on:
workflow_dispatch:
jobs:
remove:
runs-on: ubuntu-latest
steps:
- uses: mockzilla/actions/portable@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
delete: true
```
Trigger it manually from the **Actions** tab when you're ready.
### Check your simulation URL
After pushing, your URL is deterministic:
```bash
echo "https://api.mockz.io/gh/$(gh repo view --json nameWithOwner -q .nameWithOwner)/$(git branch --show-current)/"
```