Skip to content

Commit d33535d

Browse files
add ability to deploy only service config changes (no sync config)
1 parent 80560f9 commit d33535d

4 files changed

Lines changed: 119 additions & 2 deletions

File tree

cli/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ See [docs/usage.md](../docs/usage.md) for full usage and resolution order (flags
231231
- [`powersync autocomplete [SHELL]`](#powersync-autocomplete-shell)
232232
- [`powersync commands`](#powersync-commands)
233233
- [`powersync deploy`](#powersync-deploy)
234+
- [`powersync deploy service-config`](#powersync-deploy-service-config)
234235
- [`powersync deploy sync-config`](#powersync-deploy-sync-config)
235236
- [`powersync destroy`](#powersync-destroy)
236237
- [`powersync docker configure`](#powersync-docker-configure)
@@ -354,6 +355,7 @@ DESCRIPTION
354355
Deploy local config (service.yaml, sync config) to the linked PowerSync Cloud instance.
355356
Validates connections and sync config before deploying.
356357
See also powersync deploy sync-config to deploy only sync config changes.
358+
See also powersync deploy service-config to deploy only service config changes.
357359

358360
EXAMPLES
359361
$ powersync deploy
@@ -363,6 +365,43 @@ EXAMPLES
363365
364366
_See code: [src/commands/deploy/index.ts](https://github.com/powersync-ja/powersync-js/blob/v0.0.0/src/commands/deploy/index.ts)_
365367
368+
## `powersync deploy service-config`
369+
370+
[Cloud only] Deploy only local service config to the linked Cloud instance.
371+
372+
```
373+
USAGE
374+
$ powersync deploy service-config [--deploy-timeout <value>] [--directory <value>] [--instance-id <value> --project-id
375+
<value>] [--org-id <value>]
376+
377+
FLAGS
378+
--deploy-timeout=<value> [default: 300] Seconds to wait after scheduling a deploy before timing out while polling
379+
status (default 300 seconds).
380+
381+
PROJECT FLAGS
382+
--directory=<value> [default: powersync] Directory containing PowerSync config. Defaults to "powersync". This is
383+
required if multiple powersync config files are present in subdirectories of the current working
384+
directory.
385+
386+
CLOUD_PROJECT FLAGS
387+
--instance-id=<value> PowerSync Cloud instance ID. Manually passed if the current context has not been linked.
388+
--org-id=<value> Organization ID (optional). Defaults to the token’s single org when only one is available; pass
389+
explicitly if the token has multiple orgs.
390+
--project-id=<value> Project ID. Manually passed if the current context has not been linked.
391+
392+
DESCRIPTION
393+
[Cloud only] Deploy only local service config to the linked Cloud instance.
394+
395+
Deploy only service config changes (without sync config updates).
396+
397+
EXAMPLES
398+
$ powersync deploy service-config
399+
400+
$ powersync deploy service-config --instance-id=<id> --project-id=<id>
401+
```
402+
403+
_See code: [src/commands/deploy/service-config.ts](https://github.com/powersync-ja/powersync-js/blob/v0.0.0/src/commands/deploy/service-config.ts)_
404+
366405
## `powersync deploy sync-config`
367406
368407
[Cloud only] Deploy only local sync config to the linked Cloud instance.

cli/src/commands/deploy/index.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Flags, ux } from '@oclif/core';
22
import { CloudInstanceCommand, SERVICE_FILENAME } from '@powersync/cli-core';
3+
import { ServiceCloudConfigDecoded } from '@powersync/cli-schemas';
34
import { routes } from '@powersync/management-types';
45
import ora from 'ora';
56

@@ -13,7 +14,8 @@ export default class DeployAll extends CloudInstanceCommand {
1314
static description = [
1415
'Deploy local config (service.yaml, sync config) to the linked PowerSync Cloud instance.',
1516
'Validates connections and sync config before deploying.',
16-
`See also ${ux.colorize('blue', 'powersync deploy sync-config')} to deploy only sync config changes.`
17+
`See also ${ux.colorize('blue', 'powersync deploy sync-config')} to deploy only sync config changes.`,
18+
`See also ${ux.colorize('blue', 'powersync deploy service-config')} to deploy only service config changes.`
1719
].join('\n');
1820
static examples = [
1921
'<%= config.bin %> <%= command.id %>',
@@ -87,6 +89,23 @@ export default class DeployAll extends CloudInstanceCommand {
8789
});
8890
}
8991

92+
override parseConfig(projectDirectory: string): ServiceCloudConfigDecoded {
93+
const config = super.parseConfig(projectDirectory);
94+
95+
/**
96+
* This is a temporary hack to maintain compatibilty with the PowerSync Dashboard.
97+
* The dashboard requires replication connections to have a name field set.
98+
* This is not enforced by the management service.
99+
*/
100+
for (const [index, connection] of config.replication?.connections?.entries() ?? []) {
101+
if (!connection.name) {
102+
connection.name = `Default${index > 0 ? `_${index}` : ''}`;
103+
}
104+
}
105+
106+
return config;
107+
}
108+
90109
async run(): Promise<void> {
91110
const { flags } = await this.parse(DeployAll);
92111

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { DEFAULT_DEPLOY_TIMEOUT_MS } from '../../api/cloud/wait-for-operation.js';
2+
import DeployAll from './index.js';
3+
4+
export default class DeployServiceConfig extends DeployAll {
5+
static description = 'Deploy only service config changes (without sync config updates).';
6+
static examples = [
7+
'<%= config.bin %> <%= command.id %>',
8+
'<%= config.bin %> <%= command.id %> --instance-id=<id> --project-id=<id>'
9+
];
10+
static flags = {
11+
...DeployAll.flags
12+
};
13+
static summary = '[Cloud only] Deploy only local service config to the linked Cloud instance.';
14+
15+
async run(): Promise<void> {
16+
const { flags } = await this.parse(DeployServiceConfig);
17+
18+
const project = await this.loadProject(flags, {
19+
// local service config is required for this command
20+
configFileRequired: true
21+
});
22+
23+
const deployTimeoutMs = (flags['deploy-timeout'] ?? DEFAULT_DEPLOY_TIMEOUT_MS / 1000) * 1000;
24+
25+
// Parse and store for later
26+
this.parseConfig(project.projectDirectory);
27+
28+
// The existing config is required to deploy changes. The instance should have been created already.
29+
const cloudConfigState = await this.loadCloudConfigState();
30+
31+
this.log('Performing validations before deploy...');
32+
await this.validateServiceConfig({ cloudConfigState });
33+
await this.testConnections();
34+
35+
this.log('Validations completed successfully.\n');
36+
37+
await this.deployAll({ cloudConfigState, deployTimeoutMs, updateSyncConfig: false });
38+
}
39+
}

docs/usage.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ Use separate config directories (e.g. `powersync`, `powersync-dev`, `powersync-s
3737
powersync deploy --directory=powersync # production (linked in powersync/cli.yaml)
3838
powersync deploy --directory=powersync-dev # dev (linked in powersync-dev/cli.yaml)
3939
powersync deploy --directory=powersync-staging # staging (linked in powersync-staging/cli.yaml)
40+
41+
# Optional targeted deploys:
42+
powersync deploy service-config --directory=powersync # service.yaml only (keeps cloud sync config)
43+
powersync deploy sync-config --directory=powersync # sync-config.yaml only
4044
```
4145

4246
**Single directory and link file, with `!env` substitution**
@@ -90,8 +94,18 @@ powersync link cloud --create --project-id=<project-id>
9094
# If your token has multiple orgs: add --org-id=<org-id>
9195
powersync validate
9296
powersync deploy
97+
98+
# Optional targeted deploys:
99+
powersync deploy service-config
100+
powersync deploy sync-config
93101
```
94102

103+
Deploy command modes:
104+
105+
- `powersync deploy` — deploy both service config and sync config.
106+
- `powersync deploy service-config` — deploy only service config changes, without updating sync config.
107+
- `powersync deploy sync-config` — deploy only sync config changes.
108+
95109
The instance **name** and **region** are taken from your local `service.yaml`; set them before running `powersync link cloud --create` if you want a specific display name and region.
96110

97111
## Using an existing Cloud instance
@@ -108,8 +122,14 @@ powersync pull instance --project-id=<project-id> --instance-id=<instance-id>
108122
# Edit the YAML files in powersync/ as needed
109123
powersync validate
110124
powersync deploy
125+
126+
# Optional targeted deploys:
127+
powersync deploy service-config
128+
powersync deploy sync-config
111129
```
112130

131+
When you only changed one file, prefer a targeted deploy command to reduce unnecessary updates.
132+
113133
If the config directory already exists and is linked, you can run **`powersync pull instance`** without passing IDs to refresh the local config from the cloud.
114134

115135
## Executing commands on an instance (no local config management)
@@ -202,7 +222,7 @@ If you decline this prompt, login exits without storing a token. Use `TOKEN` in
202222

203223
# Supplying Linking Information for Cloud and Self-Hosted Commands
204224

205-
Cloud and self-hosted commands need instance (and for Cloud, org and project) identifiers. **Cloud only:** `powersync deploy`, `powersync destroy`, `powersync stop`, `powersync fetch config`, `powersync pull instance`. **Both:** `powersync fetch status`, `powersync generate schema`, `powersync generate token`, `powersync validate`. The same three methods apply: the CLI uses the first that is available for each field (flags override environment variables, environment variables override link file). For Cloud, **org_id is optional**: when not set via flags, env, or link file, the CLI fetches the token’s organizations and uses the single org if there is exactly one; if the token has multiple orgs, the command errors and you must pass `--org-id` (or set `ORG_ID`).
225+
Cloud and self-hosted commands need instance (and for Cloud, org and project) identifiers. **Cloud only:** `powersync deploy`, `powersync deploy service-config`, `powersync deploy sync-config`, `powersync destroy`, `powersync stop`, `powersync fetch config`, `powersync pull instance`. **Both:** `powersync fetch status`, `powersync generate schema`, `powersync generate token`, `powersync validate`. The same three methods apply: the CLI uses the first that is available for each field (flags override environment variables, environment variables override link file). For Cloud, **org_id is optional**: when not set via flags, env, or link file, the CLI fetches the token’s organizations and uses the single org if there is exactly one; if the token has multiple orgs, the command errors and you must pass `--org-id` (or set `ORG_ID`).
206226

207227
1. **Flags**
208228
- **Cloud:** `--instance-id`, `--project-id` (required when using instance-id), `--org-id` (optional; defaults to token’s single org)

0 commit comments

Comments
 (0)