Skip to content

Commit 80343d2

Browse files
authored
Release: CLI 1.36.3 (#1428)
* Another fix to sync (#1426) * fix endpoint argument tracing and a little refactor to the v2 pull proxy * changeset * remove log * version * fix endpoint tracing on deploy * changeset * add tests * tidy logging * remove log code * Fix deploy new (#1427) * fix new deploy * changeset * types * versions
1 parent 4d9e6fd commit 80343d2

7 files changed

Lines changed: 139 additions & 41 deletions

File tree

packages/cli/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @openfn/cli
22

3+
## 1.36.3
4+
5+
### Patch Changes
6+
7+
- 393b324: sync v2: fix an issue deploying a new project
8+
- d405328: Fix endpoint tracing on deploy command
9+
310
## 1.36.2
411

512
### Patch Changes

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@openfn/cli",
3-
"version": "1.36.2",
3+
"version": "1.36.3",
44
"description": "CLI devtools for the OpenFn toolchain",
55
"engines": {
66
"node": ">=18",

packages/cli/src/deploy/command.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import * as o2 from '../projects/options';
88
export type DeployOptions = Required<
99
Pick<
1010
Opts & POpts,
11+
| 'endpoint'
12+
| 'apiKey'
1113
| 'beta'
1214
| 'command'
1315
| 'configPath'

packages/cli/src/deploy/handler.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,27 @@ import { yamlToJson } from '@openfn/project';
1414
import fs from 'node:fs/promises';
1515

1616
export type DeployFn = typeof deploy;
17+
export type BetaHandlerFn = typeof beta.handler;
1718

1819
const actualDeploy: DeployFn = deploy;
20+
const actualBetaHandler: BetaHandlerFn = beta.handler;
1921

20-
// Flexible `deployFn` interface for testing.
22+
// Flexible `deployFn` / `betaHandler` interfaces for testing.
2123
async function deployHandler<F extends (...args: any) => any>(
2224
options: DeployOptions,
2325
logger: Logger,
24-
deployFn: F
26+
deployFn: F,
27+
betaHandler?: BetaHandlerFn
2528
): Promise<ReturnType<typeof deployFn>>;
2629

2730
async function deployHandler(
2831
options: DeployOptions,
2932
logger: Logger,
30-
deployFn = actualDeploy
33+
deployFn = actualDeploy,
34+
betaHandler: BetaHandlerFn = actualBetaHandler
3135
) {
3236
if (options.beta) {
33-
return beta.handler(options as any, logger);
37+
return betaHandler(options as any, logger);
3438
}
3539

3640
try {
@@ -41,7 +45,7 @@ async function deployHandler(
4145
'openfn.yaml'
4246
);
4347
if (!process.env.PREFER_LEGACY_SYNC && (await fileExists(v2ConfigPath))) {
44-
return redirectTov2(v2ConfigPath, options, config, logger);
48+
return redirectTov2(v2ConfigPath, options, config, logger, betaHandler);
4549
}
4650

4751
if (options.confirm === false) {
@@ -110,24 +114,24 @@ const redirectTov2 = async (
110114
v2ConfigPath: string,
111115
options: DeployOptions,
112116
config: DeployConfig,
113-
logger: Logger
117+
logger: Logger,
118+
betaHandler: BetaHandlerFn = actualBetaHandler
114119
) => {
115120
logger.always(
116121
'Detected openfn.yaml file - switching to v2 deploy (openfn project deploy). Set PREFER_LEGACY_SYNC to disable this.'
117122
);
118123

119124
// default endpoint to one from openfn.yaml
120125
const v2config = yamlToJson(await fs.readFile(v2ConfigPath, 'utf-8'));
121-
if (!config.endpoint && v2config?.project?.endpoint) {
122-
config.endpoint = v2config.project.endpoint;
123-
}
126+
const endpoint =
127+
options.endpoint ?? v2config?.project?.endpoint ?? config.endpoint;
124128

125-
return beta.handler(
129+
return betaHandler(
126130
{
127131
...options,
128132
force: true,
129-
endpoint: config.endpoint,
130-
apiKey: config.apiKey ?? undefined,
133+
endpoint,
134+
apiKey: options.apiKey ?? config.apiKey ?? undefined,
131135
},
132136
logger
133137
);

packages/cli/src/projects/deploy.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ const syncProjects = async (
148148
// TODO should we prefer endpoint over alias?
149149
// maybe if it's explicitly passed?
150150
const endpoint = trackedProject.openfn?.endpoint ?? config.endpoint;
151-
152151
const { data } = await fetchProject(
153152
endpoint,
154153
config.apiKey,
@@ -162,7 +161,7 @@ const syncProjects = async (
162161

163162
logger.info('Downloaded latest version of project at ', endpoint);
164163
} catch (e) {
165-
console.log(e);
164+
logger.error(e);
166165
throw e;
167166
// If fetch failed because of compatiblity with the local project, what do we do?
168167
// Well, actually I don't think I want this fetch to write to disk yet
@@ -266,23 +265,32 @@ export async function handler(options: DeployOptions, logger: Logger) {
266265
// Track the remote we want to target
267266
// If the user passed a project alias, we need to use that
268267
// Otherwise just sync with the local project
269-
const tracker = ws.get(options.project ?? localProject.uuid!);
270-
271-
if (!tracker) {
272-
// Is this really an error? Unlikely to happen I thuink
273-
console.log(
274-
`ERROR: Failed to find tracked remote project ${
275-
options.project ?? localProject.uuid!
276-
} locally`
277-
);
278-
console.log('To deploy a new project, add --new to the command');
279-
// TODO can we automate the fetch bit?
280-
// If it's a UUID it should be ok?
281-
console.log(
282-
'You may need to fetch the project before you can safely deploy'
283-
);
268+
let tracker;
269+
if (!options.new) {
270+
tracker = ws.get(options.project ?? localProject.uuid!);
271+
if (!tracker) {
272+
console.log('FOUND TRACKER');
273+
console.log(options.project ?? localProject.uuid);
274+
// Is this really an error? Unlikely to happen I thuink
275+
console.log(
276+
`ERROR: Failed to find tracked remote project ${
277+
options.project ?? localProject.uuid!
278+
} locally`
279+
);
280+
console.log('To deploy a new project, add --new to the command');
281+
// TODO can we automate the fetch bit?
282+
// If it's a UUID it should be ok?
283+
console.log(
284+
'You may need to fetch the project before you can safely deploy'
285+
);
284286

285-
throw new Error('Failed to find remote project locally');
287+
throw new Error('Failed to find remote project locally');
288+
}
289+
} else {
290+
// reset all metadata
291+
localProject.openfn = {
292+
endpoint: config.endpoint,
293+
};
286294
}
287295

288296
// Choose the target endpoint we want to deploy to
@@ -291,17 +299,10 @@ export async function handler(options: DeployOptions, logger: Logger) {
291299
// Otherwise fallback to to the auto-loaded config (probably coming from env)
292300
let endpoint: string =
293301
options.endpoint ??
294-
tracker.openfn?.endpoint ??
302+
tracker?.openfn?.endpoint ??
295303
config.endpoint ??
296304
DEFAULT_ENDPOINT;
297305

298-
if (options.new) {
299-
// reset all metadata
300-
localProject.openfn = {
301-
endpoint: config.endpoint,
302-
};
303-
}
304-
305306
// generate a credential map
306307
localProject.credentials = localProject.buildCredentialMap();
307308

@@ -321,7 +322,7 @@ export async function handler(options: DeployOptions, logger: Logger) {
321322
config,
322323
ws,
323324
localProject,
324-
tracker,
325+
tracker!,
325326
logger
326327
);
327328
if (!syncResult) {

packages/cli/src/projects/util.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ export async function fetchProject(
121121
): Promise<{ data: Provisioner.Project | null }> {
122122
const url = getLightningUrl(endpoint, projectId, snapshots);
123123
logger?.info(`Checking ${url} for existing project`);
124-
125124
try {
126125
const response = await fetch(url, {
127126
headers: {

packages/cli/test/deploy/deploy.test.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,91 @@ test.serial('sets the exit code to 1', async (t) => {
8888
process.exitCode = origExitCode;
8989
});
9090

91+
test.serial(
92+
'redirects to beta handler when openfn.yaml exists in cwd',
93+
async (t) => {
94+
t.plan(3);
95+
mockfs({
96+
['./config.json']: `{"apiKey": "123"}`,
97+
['./project.yaml']: `{"apiKey": "123"}`,
98+
['./openfn.yaml']: 'project:\n endpoint: https://from-yaml.org',
99+
});
100+
101+
await deployHandler(options, logger, mockDeploy, async (args: any) => {
102+
t.is(args.force, true);
103+
t.is(args.endpoint, 'https://from-yaml.org');
104+
t.truthy(logger._find('always', /Detected openfn.yaml file/i));
105+
});
106+
}
107+
);
108+
109+
test.serial('does not redirect when PREFER_LEGACY_SYNC is set', async (t) => {
110+
t.plan(1);
111+
mockfs({
112+
['./config.json']: `{"apiKey": "123", "endpoint": "https://api.example.com"}`,
113+
['./project.yaml']: `{"apiKey": "123"}`,
114+
['./openfn.yaml']: 'project:\n endpoint: https://from-yaml.org',
115+
});
116+
process.env.PREFER_LEGACY_SYNC = '1';
117+
118+
await deployHandler(options, logger, mockDeploy, async (args: any) => {
119+
t.fail('called beta handler');
120+
});
121+
122+
delete process.env.PREFER_LEGACY_SYNC;
123+
t.pass();
124+
});
125+
126+
test.serial('CLI endpoint preferred over openfn.yaml endpoint', async (t) => {
127+
t.plan(1);
128+
mockfs({
129+
['./config.json']: `{"apiKey": "123"}`,
130+
['./project.yaml']: `{"apiKey": "123"}`,
131+
['./openfn.yaml']: 'project:\n endpoint: https://from-yaml.org',
132+
});
133+
134+
await deployHandler(
135+
{ ...options, endpoint: 'https://from-cli.org' } as any,
136+
logger,
137+
mockDeploy,
138+
async (args: any) => {
139+
t.is(args.endpoint, 'https://from-cli.org');
140+
}
141+
);
142+
});
143+
144+
test.serial(
145+
'openfn.yaml endpoint preferred over config.json endpoint',
146+
async (t) => {
147+
mockfs({
148+
['./config.json']: `{"apiKey": "123", "endpoint": "https://from-config.org"}`,
149+
['./project.yaml']: `{"apiKey": "123"}`,
150+
['./openfn.yaml']: 'project:\n endpoint: https://from-yaml.org',
151+
});
152+
153+
await deployHandler(options, logger, mockDeploy, async (args: any) => {
154+
t.is(args.endpoint, 'https://from-yaml.org');
155+
});
156+
}
157+
);
158+
159+
test.serial('CLI apiKey preferred over config.json apiKey', async (t) => {
160+
mockfs({
161+
['./config.json']: `{"apiKey": "from-config"}`,
162+
['./project.yaml']: `{"apiKey": "from-config"}`,
163+
['./openfn.yaml']: 'project:\n endpoint: https://from-yaml.org',
164+
});
165+
166+
await deployHandler(
167+
{ ...options, apiKey: 'from-cli' } as any,
168+
logger,
169+
mockDeploy,
170+
async (args: any) => {
171+
t.is(args.apiKey, 'from-cli');
172+
}
173+
);
174+
});
175+
91176
test.serial('catches DeployErrors', async (t) => {
92177
const origExitCode = process.exitCode;
93178

0 commit comments

Comments
 (0)