-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: replace adaptors in plan with resolved adaptors at install (#857)
* fix: replace adaptors in plan to what they resolved to This mostly effects adaptors specified with aliases like common@latest which will be replaced to the what they resolved to like [email protected] * test: override plan test * test: check for resolved with number to be sure linking stage passed * test: a workflow using different versions of the same adaptor * version: [email protected] --------- Co-authored-by: Joe Clark <[email protected]>
- Loading branch information
1 parent
a1a071b
commit 0337621
Showing
8 changed files
with
224 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
integration-tests/cli/test/fixtures/different-adaptor-versions.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"options": {}, | ||
"workflow": { | ||
"name": "Steps with different adaptor versions", | ||
"steps": [ | ||
{ | ||
"id": "lesser", | ||
"adaptor": "[email protected]", | ||
"state": { | ||
"x": 1 | ||
}, | ||
"expression": "fn(state=> ({y: state.x}))", | ||
"next": { | ||
"latest-again": true | ||
} | ||
}, | ||
{ | ||
"id": "latest-again", | ||
"adaptor": "[email protected]", | ||
"expression": "fn(state=> ({z: state.y}))" | ||
} | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { ExecutionPlan, Job, Step } from '@openfn/lexicon'; | ||
|
||
function overridePlanAdaptors( | ||
plan: ExecutionPlan, | ||
resolutions: Record<string, string> | ||
): ExecutionPlan { | ||
const hasRes = Object.entries(resolutions).some( | ||
([key, value]) => key !== value | ||
); | ||
|
||
// there's nothing to override when resolutions have the same values | ||
if (!hasRes) return plan; | ||
return { | ||
...plan, | ||
workflow: { | ||
...plan.workflow, | ||
steps: plan.workflow.steps.map((step) => { | ||
if (isJob(step)) | ||
return { | ||
...step, | ||
adaptors: step.adaptors?.map((a) => resolutions[a] || a), | ||
}; | ||
else return step; | ||
}), | ||
}, | ||
}; | ||
} | ||
|
||
export function isJob(step: Step): step is Job { | ||
// @ts-ignore | ||
return step && typeof step.expression === 'string'; | ||
} | ||
|
||
export default overridePlanAdaptors; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { ExecutionPlan } from '@openfn/lexicon'; | ||
import test from 'ava'; | ||
import overridePlanAdaptors, { | ||
isJob, | ||
} from '../../src/util/override-plan-adaptors'; | ||
|
||
// validates adaptors in a plan against an array. | ||
function getAdaptors(plan: ExecutionPlan) { | ||
// check for a given id whether the | ||
const steps = plan.workflow.steps; | ||
|
||
const adaptors = steps.map((step) => { | ||
if (isJob(step)) return step.adaptors; | ||
return undefined; | ||
}); | ||
return adaptors; | ||
} | ||
|
||
test('replace adaptors in plan using provided resolutions', (t) => { | ||
const plan: ExecutionPlan = { | ||
workflow: { | ||
steps: [ | ||
{ | ||
id: 'one', | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/language-http@latest'], | ||
}, | ||
{ | ||
id: 'two', | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/language-common@next'], | ||
}, | ||
{ | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/[email protected]'], | ||
}, | ||
], | ||
}, | ||
}; | ||
|
||
const resolutions = { | ||
'@openfn/language-http@latest': '@openfn/[email protected]', | ||
'@openfn/language-common@next': '@openfn/[email protected]', | ||
}; | ||
const finalPlan = overridePlanAdaptors(plan, resolutions); | ||
|
||
t.deepEqual(getAdaptors(finalPlan), [ | ||
['@openfn/[email protected]'], | ||
['@openfn/[email protected]'], | ||
['@openfn/[email protected]'], | ||
]); | ||
}); | ||
|
||
test("ignore override when there's nothing to override", (t) => { | ||
const plan: ExecutionPlan = { | ||
workflow: { | ||
steps: [ | ||
{ | ||
id: 'one', | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/language-http@latest'], | ||
}, | ||
{ | ||
id: 'two', | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/language-common@next'], | ||
}, | ||
{ | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/[email protected]'], | ||
}, | ||
], | ||
}, | ||
}; | ||
|
||
const resolutions = { | ||
'@openfn/[email protected]': '@openfn/[email protected]', | ||
'@openfn/[email protected]': '@openfn/[email protected]', | ||
}; | ||
|
||
const finalPlan = overridePlanAdaptors(plan, resolutions); | ||
t.is(plan, finalPlan); | ||
}); | ||
|
||
test('replace adaptors on only job steps', (t) => { | ||
const plan: ExecutionPlan = { | ||
workflow: { | ||
steps: [ | ||
{ | ||
id: 'x', | ||
next: 'two', | ||
}, | ||
{ | ||
id: 'two', | ||
expression: 'fn(state=> state)', | ||
adaptors: ['@openfn/language-common@next'], | ||
}, | ||
], | ||
}, | ||
}; | ||
const resolutions = { | ||
'@openfn/language-common@next': '@openfn/[email protected]', | ||
}; | ||
|
||
const finalPlan = overridePlanAdaptors(plan, resolutions); | ||
t.deepEqual(getAdaptors(finalPlan), [ | ||
undefined, | ||
['@openfn/[email protected]'], | ||
]); | ||
}); |