Skip to main content

Profiles

Profiles are overlays on top of your base gws.json. One config file, many ways to deploy it — ci, staging, e2e, minimal, whatever you need.

A profile can:

  • Disable services entirely (enabled: false)
  • Turn off live file sync and watchers
  • Swap in different Dockerfiles or manifest folders
  • Point at a remote registry instead of the local one
  • Override any service field, individually or via a * wildcard

The base config keeps its dev-friendly defaults. Profiles only describe what's different.

Define profiles

Add a profiles block to gws.json:

{
"name": "my-project",
"services": [
{ "name": "api", "path": "./api", "fileSync": true, "port": 3000 },
{ "name": "web", "path": "./frontend", "fileSync": true, "port": 80 },
{ "name": "docs", "path": "./docs", "fileSync": true, "port": 8080 }
],

"profiles": {
"ci": {
"description": "CI pipeline — no sync, no docs",
"services": [
{ "name": "*", "fileSync": false },
{ "name": "docs", "enabled": false }
]
},

"minimal": {
"description": "Just the essentials for fast iteration",
"services": [
{ "name": "docs", "enabled": false }
]
},

"staging": {
"description": "Staging — pull images from the remote registry",
"registry": { "mode": "remote", "url": "gcr.io/my-project" },
"services": [
{ "name": "*", "fileSync": false }
]
}
}
}

Use a profile

gws up --profile ci         # one-off
gws status # active profile is shown here

GWS_PROFILE=ci gws up # pin via env var (handy in CI scripts)
gws up --profile staging # CLI flag overrides GWS_PROFILE

To switch profiles, stop first:

gws down
gws up --profile staging

What you can override

Top-level fieldEffect
descriptionFree-form text shown in gws status
registryReplace the registry block (e.g. switch from local to remote)
servicesArray of service overrides — see below
provision.environmentsOverride per-environment provisioning settings

Inside services, each entry is matched by name (or "*" for all services). You can override any field of a service, including:

  • fileSync, fileSyncIgnore — disable bidirectional sync
  • watch — disable or replace watch rules
  • dockerfile — point at a different image build (e.g. Dockerfile.e2e)
  • manifests — point at a different manifest folder
  • expose, port — reshape runtime
  • enabled: false — don't deploy this service at all

Environment values come from gws secret (or your manifests/ envFrom), not from gws.json — so there's no env field to override here. To inject different values per profile, scope the secret with gws secret set NAME --profile <name>.

Override rules

  1. Wildcard first. { "name": "*", … } is applied to every service before specific overrides.
  2. Specific wins. A { "name": "api", … } entry overrides whatever the wildcard set.
  3. null deletes a property. Use "expose": null or "watch": null to remove a field from the base config.
  4. enabled: false filters the service out entirely — it isn't built, deployed, or synced.
  5. Profiles do not cascade. Each profile is independent of the others; there is no extends.

Common patterns

CI

"ci": {
"description": "CI — no sync, no dev tools",
"services": [
{ "name": "*", "fileSync": false },
{ "name": "docs", "enabled": false },
{ "name": "storybook", "enabled": false }
]
}

End-to-end testing

Disable sync and watchers, swap to prod-like images. See the full recipe in End-to-end testing.

"e2e": {
"description": "E2E — no sync, no watchers, prod-like images",
"services": [
{ "name": "*", "fileSync": false, "watch": null },
{ "name": "api", "dockerfile": "./api/Dockerfile.e2e", "manifests": "./api/k8s/e2e" },
{ "name": "web", "dockerfile": "./frontend/Dockerfile.e2e", "manifests": "./frontend/k8s/e2e" },
{ "name": "docs", "enabled": false }
]
}

Staging with remote registry

"staging": {
"description": "Staging — remote registry, no sync",
"registry": { "mode": "remote", "url": "gcr.io/my-project" },
"services": [
{ "name": "*", "fileSync": false }
]
}

Low-resource laptop

"low-resource": {
"description": "Skip heavy services on constrained machines",
"services": [
{ "name": "*", "fileSync": false },
{ "name": "heavy-service", "enabled": false }
]
}

Deploy a single subset

In a multi-repo project, profiles still target every service in the centralized gws.json regardless of which child repo it lives in:

"api-only": {
"description": "Only the API services",
"services": [
{ "name": "web", "enabled": false },
{ "name": "ssr", "enabled": false }
]
}

Validate

gws config validate

Common errors:

  • Profile "<name>" not found — typo, or the profile isn't defined in gws.json
  • Profile override for service "<name>" targets non-existent service — the service was renamed or deleted from the base config
  • Profile conflict detected. Current deployment uses "<other>" profile. — you forgot to gws down before switching

See also