Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions cli/api/commands/prune.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function computeIncludedActionNames(

const hasActionSelector = runConfig.actions?.length > 0;
const hasTagSelector = runConfig.tags?.length > 0;
const hasFlterTagsAsIntersectionSelector = runConfig.filterTagsAsIntersection?.valueOf();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of runConfig.filterTagsAsIntersection?.valueOf() I suggest to use !!runConfig.filterTagsAsIntersection

There is also a typo in the word Filter.


// If no selectors, return all actions.
if (!hasActionSelector && !hasTagSelector) {
Expand All @@ -61,9 +62,18 @@ function computeIncludedActionNames(

// Determine actions selected with --tag option and update applicable actions
if (hasTagSelector) {
allActions
.filter(action => action.tags.some(tag => runConfig.tags.includes(tag)))
.forEach(action => includedActionNames.add(targetAsReadableString(action.target)));
// Select actions which match the intersection of the set of tags.
if (hasFlterTagsAsIntersectionSelector) {
allActions
.filter(action => runConfig.tags.every(tag => action.tags.includes(tag)))
.forEach(action => includedActionNames.add(targetAsReadableString(action.target)));
}
// Select actions which match the union of the set of tags.
else {
allActions
.filter(action => action.tags.some(tag => runConfig.tags.includes(tag)))
.forEach(action => includedActionNames.add(targetAsReadableString(action.target)));
}
}

// Compute all transitive dependencies.
Expand Down
14 changes: 13 additions & 1 deletion cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ const tagsOption: INamedOption<yargs.Options> = {
}
};

const flterTagsAsIntersectionSelectorOption: INamedOption<yargs.Options> = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in the word "filter"

name: "filter-tags-as-intersection",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it shorter for the user. Maybe just tags-intersection, WDYT?

option: {
describe: "If set, only actions that include every user-specified tags will be run",
type: "boolean",
default: false
}
}

const includeDepsOption: INamedOption<yargs.Options> = {
name: "include-deps",
option: {
Expand Down Expand Up @@ -469,6 +478,7 @@ export function runCli() {
credentialsOption,
fullRefreshOption,
includeDepsOption,
flterTagsAsIntersectionSelectorOption,
includeDependentsOption,
credentialsOption,
jsonOutputOption,
Expand Down Expand Up @@ -511,7 +521,9 @@ export function runCli() {
actions: argv[actionsOption.name],
includeDependencies: argv[includeDepsOption.name],
includeDependents: argv[includeDependentsOption.name],
tags: argv[tagsOption.name]
tags: argv[tagsOption.name],
flterTagsAsIntersectionSelector: argv[flterTagsAsIntersectionSelectorOption.name]

},
dbadapter
);
Expand Down
1 change: 1 addition & 0 deletions protos/execution.proto
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ option go_package = "github.com/dataform-co/dataform/protos/dataform";
message RunConfig {
repeated string actions = 1;
repeated string tags = 5;
bool filter_tags_as_intersection = 10;
bool include_dependencies = 3;
bool include_dependents = 11;
bool full_refresh = 2;
Expand Down
21 changes: 21 additions & 0 deletions tests/api/api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ suite("@dataform/api", () => {
target: { schema: "schema", name: "op_d" },
tags: ["tag3"],
queries: ["create or replace view schema.someview as select 1 as test"]
},
{
target: { schema: "schema", name: "op_e" },
tags: ["tag1", "tag2"],
queries: ["create or replace view schema.someview as select 1 as test"]
}
],
tables: [
Expand Down Expand Up @@ -362,6 +367,22 @@ suite("@dataform/api", () => {
expect(actionNames).includes("schema.tab_a");
});

test("prune actions with --tags (with include all tags)", () => {
const prunedGraph = prune(TEST_GRAPH_WITH_TAGS, {
tags: ["tag1", "tag2"],
includeAllTags: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filterTagsAsIntersection?

});
const actionNames = [
...prunedGraph.tables.map(action => targetAsReadableString(action.target)),
...prunedGraph.operations.map(action => targetAsReadableString(action.target))
];
expect(actionNames).deep.equals(["schema.op_e", "schema.op_a"]);
expect(actionNames).not.includes("schema.op_a");
expect(actionNames).not.includes("schema.op_b");
expect(actionNames).not.includes("schema.op_c");
expect(actionNames).not.includes("schema.op_d");
Comment on lines +380 to +383
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already made a deep.equals on previous line, we do not need to double check this with not.include

});

test("prune actions with --actions with dependencies", () => {
const prunedGraph = prune(TEST_GRAPH, { actions: ["schema.a"], includeDependencies: true });
const actionNames = [
Expand Down