Skip to content

Commit f640dbf

Browse files
committed
chore: update readme
1 parent 3344a67 commit f640dbf

1 file changed

Lines changed: 149 additions & 164 deletions

File tree

README.md

Lines changed: 149 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,170 @@
11
# checkout-cloud-sync
22

3-
A CLI tool for migrating [commercetools Checkout](https://docs.commercetools.com/checkout) resources between projects — for example when moving from one cloud provider or region to another.
3+
[![CI](https://github.com/commercetools/checkout-cloud-sync/actions/workflows/ci.yml/badge.svg)](https://github.com/commercetools/checkout-cloud-sync/actions)
4+
[![codecov](https://codecov.io/gh/commercetools/checkout-cloud-sync/branch/main/graph/badge.svg)](https://codecov.io/gh/commercetools/checkout-cloud-sync)
5+
[![Docker Pulls](https://img.shields.io/docker/pulls/commercetools/checkout-cloud-sync)](https://hub.docker.com/r/commercetools/checkout-cloud-sync)
6+
7+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
8+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
9+
10+
- [What is this?](#what-is-this)
11+
- [Prerequisites](#prerequisites)
12+
- [Usage](#usage)
13+
- [Running the Docker Image](#running-the-docker-image)
14+
- [Build](#build)
15+
- [Run](#run)
16+
- [Examples](#examples)
17+
- [Sync Behaviour](#sync-behaviour)
18+
- [Applications](#applications)
19+
- [Payment Integrations](#payment-integrations)
20+
- [Scopes](#scopes)
21+
22+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
23+
24+
### What is this?
25+
26+
A Dockerized CLI application which migrates [commercetools Checkout](https://docs.commercetools.com/checkout) resources between projects — for example when moving between cloud providers or regions.
27+
28+
The following resource types are supported, synced in this order:
29+
30+
- **Applications**
31+
- **Payment Integrations**
32+
33+
Applications are synced first because Payment Integrations reference them by ID. The tool builds a `sourceAppID → targetAppID` map during the application phase and uses it to rewrite references before touching payment integrations.
34+
35+
### Prerequisites
36+
37+
- Docker (to run the image) or Go 1.21+ (to build from source)
38+
- A commercetools API client with Checkout permissions on both source and target projects
39+
- A `config.yml` file — copy the example and fill in your credentials:
40+
41+
```bash
42+
cp config.example.yml config.yml
43+
```
44+
45+
```yaml
46+
source:
47+
project_key: "source-project-key"
48+
client_id: "sourceClientId"
49+
client_secret: "sourceClientSecret"
50+
# OAuth token endpoint (Composable Commerce), not the Checkout API host.
51+
auth_url: "https://auth.europe-west1.gcp.commercetools.com/oauth/token"
52+
checkout_api_url: "https://checkout.europe-west1.gcp.commercetools.com"
53+
# Optional: space-separated OAuth scopes. Omit to use the API client's default scopes.
54+
scopes: "manage_project"
55+
56+
target:
57+
project_key: "target-project-key"
58+
client_id: "targetClientId"
59+
client_secret: "targetClientSecret"
60+
auth_url: "https://auth.eu-central-1.aws.commercetools.com/oauth/token"
61+
checkout_api_url: "https://checkout.eu-central-1.aws.commercetools.com"
62+
scopes: ""
63+
64+
# Map source connector deployment UUIDs to target deployment UUIDs.
65+
# Required for every Payment Integration that has a connectorDeployment.
66+
# Connector deployment IDs are environment-specific and will not resolve
67+
# across cloud providers without an explicit mapping.
68+
deployment_mapping:
69+
"source-deployment-uuid": "target-deployment-uuid"
70+
```
71+
72+
> **Note:** `auth_url` and `checkout_api_url` must not have a trailing slash.
73+
74+
- The following fields are **required** to be set on resources that will be synced:
75+
76+
| Resource | Required Fields |
77+
|---|---|
78+
| Application | `key` |
79+
| Payment Integration | `key` (derived from source ID + name if absent — see [Sync Behaviour](#payment-integrations)) |
80+
81+
### Usage
482

5-
Migrates the following resource types, in order:
6-
7-
1. **Applications** — matched by `key`
8-
2. **Payment Integrations** — matched by `key`, with name-based fallback to detect key renames
9-
10-
---
11-
12-
## Requirements
13-
14-
- Go 1.21+
15-
- A commercetools API client with Checkout permissions on both projects
16-
17-
---
18-
19-
## Installation
20-
21-
### Build from source
22-
23-
```bash
24-
git clone https://github.com/commercetools/checkout-cloud-sync
25-
cd checkout-cloud-sync
26-
go build -o checkout-cloud-sync .
2783
```
28-
29-
### Docker
30-
31-
```bash
32-
docker build -t checkout-cloud-sync .
84+
usage: checkout-cloud-sync
85+
-c, --config <path> Path to config file (default: config.yml)
86+
-f, --full Execute the migration. Omit to perform a dry-run
87+
instead (shows what would be created or updated,
88+
without making any changes).
3389
```
3490
35-
---
36-
37-
## Configuration
38-
39-
Copy the example config and fill in your credentials:
40-
41-
```bash
42-
cp config.example.yml config.yml
43-
```
44-
45-
```yaml
46-
source:
47-
project_key: "source-project-key"
48-
client_id: "sourceClientId"
49-
client_secret: "sourceClientSecret"
50-
# OAuth token endpoint (Composable Commerce), not the Checkout API host.
51-
auth_url: "https://auth.europe-west1.gcp.commercetools.com/oauth/token"
52-
checkout_api_url: "https://checkout.europe-west1.gcp.commercetools.com"
53-
# Optional: space-separated OAuth scopes. Omit to use the API client's default scopes.
54-
scopes: "manage_project"
55-
56-
target:
57-
project_key: "target-project-key"
58-
client_id: "targetClientId"
59-
client_secret: "targetClientSecret"
60-
auth_url: "https://auth.eu-central-1.aws.commercetools.com/oauth/token"
61-
checkout_api_url: "https://checkout.eu-central-1.aws.commercetools.com"
62-
scopes: ""
63-
64-
# Map source connector deployment UUIDs to target deployment UUIDs.
65-
# Required for every Payment Integration that has a connectorDeployment.
66-
# Connector deployment IDs are environment-specific and will not resolve
67-
# across cloud providers without an explicit mapping.
68-
deployment_mapping:
69-
"source-deployment-uuid": "target-deployment-uuid"
70-
```
71-
72-
### Recommended OAuth scopes
73-
74-
For least-privilege access, use the following scopes instead of `manage_project`:
75-
76-
| Operation | Source scope | Target scope |
77-
|-----------|-------------|--------------|
78-
| Read applications | `view_checkout_applications:{projectKey}` | — |
79-
| Write applications | — | `manage_checkout_applications:{projectKey}` |
80-
| Read payment integrations | `view_checkout_payment_integrations:{projectKey}` | — |
81-
| Write payment integrations | — | `manage_checkout_payment_integrations:{projectKey}` |
82-
83-
---
84-
85-
## Usage
91+
By default the tool runs in **dry-run** mode: it compares source and target resources and prints a plan without writing anything. Pass `-f` to execute the migration.
8692
87-
### Dry-run (default)
93+
#### Running the Docker Image
8894
89-
Shows exactly what would be created or updated — no changes are made:
95+
##### Build
9096
9197
```bash
92-
./checkout-cloud-sync -c config.yml
98+
docker build -t checkout-cloud-sync .
9399
```
94100

95-
#### Docker
101+
##### Run
96102

97103
Mount your `config.yml` at `/app/config.yml` via a volume — credentials must never be baked into the image.
98104

99105
```bash
100-
# Dry-run (default)
101-
docker run --rm -v $(pwd)/config.yml:/app/config.yml checkout-cloud-sync
102-
103-
# Execute migration
104-
docker run --rm -v $(pwd)/config.yml:/app/config.yml checkout-cloud-sync -f
106+
docker run --rm \
107+
-v $(pwd)/config.yml:/app/config.yml \
108+
checkout-cloud-sync
105109
```
106110

107-
Example output:
108-
109-
```
110-
=== DRY RUN — pass -f to execute ===
111+
### Examples
111112

112-
--- Applications ---
113-
Found 2 application(s) in source project "source-project-key"
113+
- To perform a dry-run (default):
114+
```bash
115+
docker run --rm -v $(pwd)/config.yml:/app/config.yml checkout-cloud-sync
116+
```
114117

115-
[CREATE] application "my-application"
116-
[SKIP] application "existing-app" — already up to date
118+
Example output:
119+
```
120+
=== DRY RUN — pass -f to execute ===
117121
118-
Applications: 1 to create, 0 to update, 1 skipped/errors
122+
--- Applications ---
123+
Found 2 application(s) in source project "source-project-key"
119124
120-
--- Payment Integrations ---
121-
Found 3 payment integration(s) in source project "source-project-key"
125+
[CREATE] application "my-application"
126+
[SKIP] application "existing-app" — already up to date
122127
123-
[CREATE] payment integration "credit-card-via-adyen"
124-
[UPDATE] payment integration "paypal" (target id: abc123, version: 2)
125-
• action: setStatus
126-
[SKIP] payment integration "apple-pay" — already up to date
128+
Applications: 1 to create, 0 to update, 1 skipped/errors
127129
128-
Payment integrations: 1 to create, 1 to update, 1 skipped/errors
129-
```
130+
--- Payment Integrations ---
131+
Found 3 payment integration(s) in source project "source-project-key"
130132
131-
### Execute migration
133+
[CREATE] payment integration "credit-card-via-adyen"
134+
[UPDATE] payment integration "paypal" (target id: abc123, version: 2)
135+
• action: setStatus
136+
[SKIP] payment integration "apple-pay" — already up to date
132137
133-
```bash
134-
./checkout-cloud-sync -c config.yml -f
135-
```
138+
Payment integrations: 1 to create, 1 to update, 1 skipped/errors
139+
```
136140

137-
### Flags
141+
- To execute the migration:
142+
```bash
143+
docker run --rm -v $(pwd)/config.yml:/app/config.yml checkout-cloud-sync -f
144+
```
138145

139-
| Flag | Short | Default | Description |
140-
|------|-------|---------|-------------|
141-
| `--config` | `-c` | `config.yml` | Path to config file |
142-
| `--full` | `-f` | `false` | Execute migration (omit for dry-run) |
146+
- To use a config file at a custom path:
147+
```bash
148+
docker run --rm \
149+
-v $(pwd)/staging.yml:/app/staging.yml \
150+
checkout-cloud-sync -c /app/staging.yml -f
151+
```
143152

144-
---
153+
- To build and run without Docker:
154+
```bash
155+
go build -o checkout-cloud-sync .
156+
./checkout-cloud-sync -c config.yml # dry-run
157+
./checkout-cloud-sync -c config.yml -f # execute
158+
```
145159

146-
## Sync behaviour
160+
### Sync Behaviour
147161

148-
### Applications
162+
#### Applications
149163

150164
Applications are matched between source and target by their `key`.
151165

152166
| Condition | Action |
153-
|-----------|--------|
167+
|---|---|
154168
| Key not found in target | `CREATE` |
155169
| Key found, no fields differ | `SKIP` |
156170
| Key found, fields differ | `UPDATE` |
@@ -160,34 +174,34 @@ The following update actions are used: `setName`, `setStatus`, `setDescription`,
160174
Agreements within an application are synced by `name`:
161175

162176
| Condition | Action |
163-
|-----------|--------|
177+
|---|---|
164178
| Agreement name not in target | `addAgreement` |
165179
| Agreement name not in source | `removeAgreement` |
166180
| Agreement exists but differs | `setAgreementName` / `setAgreementType` / `setAgreementStatus` / `setAgreementText` |
167181

168-
### Payment Integrations
182+
#### Payment Integrations
169183

170184
Payment integrations are matched against target resources using a two-step lookup:
171185

172186
1. **Exact key match** — looks up the source key in the target index.
173-
2. **Name fallback** — if no key match, looks up by `name`. When a name match is found with a different key, the target key is considered stale and a `setKey` action is prepended to the update. This handles the case where a payment integration's key is changed in the source project.
187+
2. **Name fallback** — if no key match, looks up by `name`. When a name match is found with a different key, the target key is considered stale and a `setKey` action is prepended to the update. This handles key renames in the source project.
174188

175-
> **Note:** If multiple target payment integrations share the same name, the name index entry is removed to prevent ambiguous matching. In that case, a missing key match results in a new resource being created.
189+
> **Note:** If multiple target payment integrations share the same name, the name index entry is removed to prevent ambiguous matching. A missing key match in that case results in a new resource being created.
176190
177191
| Condition | Action |
178-
|-----------|--------|
192+
|---|---|
179193
| No match by key or name | `CREATE` |
180194
| Key match, no fields differ | `SKIP` |
181195
| Key match, fields differ | `UPDATE` |
182196
| Name match, key differs | `UPDATE` with `setKey` prepended |
183197

184198
The following update actions are used: `setKey`, `setName`, `setStatus`, `setComponentType`, `setPredicate`, `setDisplayInfo`, `setSortingInfo`, `setAutomatedReversalConfiguration`, `setConnectorDeployment`.
185199

186-
#### Application ID translation
200+
**Key derivation for keyless integrations**
187201

188-
Payment integrations reference their parent application by ID. Since application IDs differ between projects, the tool builds a `sourceAppID → targetAppID` map during the application sync phase and uses it to rewrite references before creating or updating payment integrations in the target.
202+
When a payment integration has no `key`, one is derived from the combination of its source **ID** and **name**: `{sanitised-id}-{sanitised-name}`. Using the source ID as a prefix guarantees that two integrations sharing the same display name receive distinct keys.
189203

190-
#### Connector deployment mapping
204+
**Connector deployment mapping**
191205

192206
Connector deployment IDs are environment-specific. Any payment integration that has a `connectorDeployment` **must** have its source deployment UUID listed in `deployment_mapping`. Without a mapping entry the integration is skipped with a clear error:
193207

@@ -196,46 +210,17 @@ payment integration "credit-card-via-adyen": connectorDeployment "src-uuid" has
196210
in deployment_mapping — add it under deployment_mapping in config.yml and retry
197211
```
198212

199-
---
200-
201-
## Error handling
213+
**Error handling**
202214

203215
Errors on individual resources are non-fatal. The tool logs each failure, continues processing the remaining resources, and exits with a non-zero status when any error occurred. This means a single bad resource never blocks the rest of the migration.
204216

205-
---
206-
207-
## Development
217+
## Scopes
208218

209-
```bash
210-
# Run tests
211-
go test ./...
212-
213-
# Run tests with race detector
214-
go test -race ./...
215-
216-
# Run with coverage
217-
go test -cover ./...
218-
219-
# Build
220-
go build -o checkout-cloud-sync .
221-
```
222-
223-
### Project structure
219+
For least-privilege access, use the following scopes instead of `manage_project`:
224220

225-
```
226-
checkout-cloud-sync/
227-
├── main.go
228-
├── config.example.yml
229-
├── cmd/
230-
│ └── root.go # CLI flags and entry point
231-
└── internal/
232-
├── config/
233-
│ └── config.go # YAML config loading and validation
234-
├── client/
235-
│ └── client.go # OAuth2 client-credentials HTTP client
236-
└── sync/
237-
├── types.go # API types (Application, PaymentIntegration, …)
238-
├── applications.go # Application CRUD + update-action builders
239-
├── payment_integrations.go # Payment integration CRUD + key derivation
240-
└── syncer.go # Orchestration, dry-run plan, ID mapping
241-
```
221+
| Operation | Source scope | Target scope |
222+
|---|---|---|
223+
| Read applications | `view_checkout_applications:{projectKey}` ||
224+
| Write applications || `manage_checkout_applications:{projectKey}` |
225+
| Read payment integrations | `view_checkout_payment_integrations:{projectKey}` ||
226+
| Write payment integrations || `manage_checkout_payment_integrations:{projectKey}` |

0 commit comments

Comments
 (0)