@backstage/plugin-catalog-backend 1.13.0-next.3 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,68 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 1.13.1
4
+
5
+ ### Patch Changes
6
+
7
+ - e77bbde41b99: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to.
8
+
9
+ ## 1.13.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 62f448edb0b5: Allow configuring the processing interval in your app-config, under the `catalog.processingInterval` key.
14
+ - 09cfc3cf467d: set azure annotation `dev.azure.com/project-repo` in `AnnotateScmSlugEntityProcessor` to find the project and repo information for the repos that contains `dev.azure.com` in the url
15
+
16
+ ### Patch Changes
17
+
18
+ - 149361e81622: Fix to the `limit` parameter on entity queries.
19
+ - 1fd2109739c1: Changed the processing loop task pipeline implementation from recursive to iterative
20
+ - 71114ac50e02: The export for the new backend system has been moved to be the `default` export.
21
+
22
+ For example, if you are currently importing the plugin using the following pattern:
23
+
24
+ ```ts
25
+ import { examplePlugin } from '@backstage/plugin-example-backend';
26
+
27
+ backend.add(examplePlugin);
28
+ ```
29
+
30
+ It should be migrated to this:
31
+
32
+ ```ts
33
+ backend.add(import('@backstage/plugin-example-backend'));
34
+ ```
35
+
36
+ - 0f8a97777489: Update OpenAPI schema to relax the encoding validation of all request parameters.
37
+ - 0198aa596fd9: Fixed a link to the frontend Backstage plugin that had pointed to itself.
38
+ - 2d32d8a611e3: Fixed validation of the `fullTextFilterFields` query parameter.
39
+ - acffa17027b6: Added some examples to the catalog OpenAPI definition
40
+ - 45947d3b2759: Fixes an issue where `order` was not a recognized parameter for the `/entities` endpoint.
41
+ - 41d1b2d628ea: Fix OpenAPI schema for the facets endpoint
42
+ - 618257f3e413: Fix issue with `catalogFileName` not being a required property for `/analyze-location`
43
+ - cfc3ca6ce060: Changes needed to support MySQL
44
+ - 814feeed7343: Update to handle invalid luxon values
45
+ - Updated dependencies
46
+ - @backstage/plugin-search-backend-module-catalog@0.1.7
47
+ - @backstage/backend-tasks@0.5.8
48
+ - @backstage/backend-common@0.19.5
49
+ - @backstage/plugin-auth-node@0.3.0
50
+ - @backstage/config@1.1.0
51
+ - @backstage/catalog-client@1.4.4
52
+ - @backstage/catalog-model@1.4.2
53
+ - @backstage/errors@1.2.2
54
+ - @backstage/integration@1.7.0
55
+ - @backstage/plugin-catalog-common@1.0.16
56
+ - @backstage/plugin-permission-common@0.7.8
57
+ - @backstage/plugin-scaffolder-common@1.4.1
58
+ - @backstage/plugin-search-common@1.2.6
59
+ - @backstage/types@1.1.1
60
+ - @backstage/plugin-permission-node@0.7.14
61
+ - @backstage/backend-plugin-api@0.6.3
62
+ - @backstage/plugin-catalog-node@1.4.4
63
+ - @backstage/backend-openapi-utils@0.0.4
64
+ - @backstage/plugin-events-node@0.2.12
65
+
3
66
  ## 1.13.0-next.3
4
67
 
5
68
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend",
3
- "version": "1.13.0-next.3",
3
+ "version": "1.13.1",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/alpha.cjs.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var alpha = require('@backstage/plugin-catalog-common/alpha');
6
6
  var pluginPermissionNode = require('@backstage/plugin-permission-node');
7
- var CatalogBuilder = require('./cjs/CatalogBuilder-c40214f8.cjs.js');
7
+ var CatalogBuilder = require('./cjs/CatalogBuilder-60d67596.cjs.js');
8
8
  var backendPluginApi = require('@backstage/backend-plugin-api');
9
9
  var alpha$1 = require('@backstage/plugin-catalog-node/alpha');
10
10
  var backendCommon = require('@backstage/backend-common');
package/dist/alpha.d.ts CHANGED
@@ -68,7 +68,7 @@ declare const catalogConditions: _backstage_plugin_permission_node.Conditions<{
68
68
  *
69
69
  * @alpha
70
70
  */
71
- declare const createCatalogConditionalDecision: (permission: _backstage_plugin_permission_common.ResourcePermission<"catalog-entity">, conditions: _backstage_plugin_permission_common.PermissionCriteria<_backstage_plugin_permission_common.PermissionCondition<"catalog-entity", _backstage_plugin_permission_common.PermissionRuleParams>>) => _backstage_plugin_permission_common.ConditionalPolicyDecision;
71
+ declare const createCatalogConditionalDecision: (permission: _backstage_plugin_permission_common.ResourcePermission<"catalog-entity">, conditions: _backstage_plugin_permission_common.PermissionCriteria<_backstage_plugin_permission_common.PermissionCondition<"catalog-entity">>) => _backstage_plugin_permission_common.ConditionalPolicyDecision;
72
72
 
73
73
  /**
74
74
  * Convenience type for {@link @backstage/plugin-permission-node#PermissionRule}
@@ -5891,57 +5891,113 @@ async function deleteWithEagerPruningOfChildren(options) {
5891
5891
  const { knex, entityRefs, sourceKey } = options;
5892
5892
  let removedCount = 0;
5893
5893
  for (const refs of lodash__default["default"].chunk(entityRefs, 1e3)) {
5894
- removedCount += await knex.delete().from("refresh_state").whereIn(
5895
- "entity_ref",
5896
- (orphans) => orphans.withRecursive(
5897
- "descendants",
5898
- ["entity_ref"],
5899
- (initial) => initial.select("target_entity_ref").from("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).union(
5900
- (recursive) => recursive.select("refresh_state_references.target_entity_ref").from("descendants").join(
5901
- "refresh_state_references",
5902
- "descendants.entity_ref",
5903
- "refresh_state_references.source_entity_ref"
5904
- )
5894
+ const { orphanEntityRefs } = await findDescendantsThatWouldHaveBeenOrphanedByDeletion({
5895
+ knex: options.knex,
5896
+ refs,
5897
+ sourceKey
5898
+ });
5899
+ for (const refsToDelete of lodash__default["default"].chunk(orphanEntityRefs, 1e3)) {
5900
+ await markEntitiesAffectedByDeletionForStitching({
5901
+ knex: options.knex,
5902
+ entityRefs: refsToDelete
5903
+ });
5904
+ await knex.delete().from("refresh_state").whereIn("entity_ref", refsToDelete);
5905
+ }
5906
+ await knex("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).delete();
5907
+ removedCount += orphanEntityRefs.length;
5908
+ }
5909
+ return removedCount;
5910
+ }
5911
+ async function findDescendantsThatWouldHaveBeenOrphanedByDeletion(options) {
5912
+ const { knex, refs, sourceKey } = options;
5913
+ const orphans = (
5914
+ // First find all nodes that can be reached downwards from the roots
5915
+ // (deletion targets), including the roots themselves, by traversing
5916
+ // down the refresh_state_references table. Note that this query
5917
+ // starts with a condition that source_key = our source key, and
5918
+ // target_entity_ref is one of the deletion targets. This has two
5919
+ // effects: it won't match attempts at deleting something that didn't
5920
+ // originate from us in the first place, and also won't match non-root
5921
+ // entities (source_key would be null for those).
5922
+ //
5923
+ // KeyA - R1 - R2 Legend:
5924
+ // \ -----------------------------------------
5925
+ // R3 Key* Source key
5926
+ // / R* Entity ref
5927
+ // KeyA - R4 - R5 lines Individual references; sources to
5928
+ // / the left and targets to the right
5929
+ // KeyB --- R6
5930
+ //
5931
+ // The scenario is that KeyA wants to delete R1.
5932
+ //
5933
+ // The query starts with the KeyA-R1 reference, and then traverses
5934
+ // down to also find R2 and R3. It uses union instead of union all,
5935
+ // because it wants to find the set of unique descendants even if
5936
+ // the tree has unexpected loops etc.
5937
+ await knex.withRecursive(
5938
+ "descendants",
5939
+ ["entity_ref"],
5940
+ (initial) => initial.select("target_entity_ref").from("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).union(
5941
+ (recursive) => recursive.select("refresh_state_references.target_entity_ref").from("descendants").join(
5942
+ "refresh_state_references",
5943
+ "descendants.entity_ref",
5944
+ "refresh_state_references.source_entity_ref"
5905
5945
  )
5906
- ).withRecursive(
5907
- "ancestors",
5908
- ["source_key", "source_entity_ref", "target_entity_ref", "subject"],
5909
- (initial) => initial.select(
5946
+ )
5947
+ ).withRecursive(
5948
+ "ancestors",
5949
+ ["source_key", "source_entity_ref", "target_entity_ref", "subject"],
5950
+ (initial) => initial.select(
5951
+ "refresh_state_references.source_key",
5952
+ "refresh_state_references.source_entity_ref",
5953
+ "refresh_state_references.target_entity_ref",
5954
+ "descendants.entity_ref"
5955
+ ).from("descendants").join(
5956
+ "refresh_state_references",
5957
+ "refresh_state_references.target_entity_ref",
5958
+ "descendants.entity_ref"
5959
+ ).union(
5960
+ (recursive) => recursive.select(
5910
5961
  "refresh_state_references.source_key",
5911
5962
  "refresh_state_references.source_entity_ref",
5912
5963
  "refresh_state_references.target_entity_ref",
5913
- "descendants.entity_ref"
5914
- ).from("descendants").join(
5964
+ "ancestors.subject"
5965
+ ).from("ancestors").join(
5915
5966
  "refresh_state_references",
5916
5967
  "refresh_state_references.target_entity_ref",
5917
- "descendants.entity_ref"
5918
- ).union(
5919
- (recursive) => recursive.select(
5920
- "refresh_state_references.source_key",
5921
- "refresh_state_references.source_entity_ref",
5922
- "refresh_state_references.target_entity_ref",
5923
- "ancestors.subject"
5924
- ).from("ancestors").join(
5925
- "refresh_state_references",
5926
- "refresh_state_references.target_entity_ref",
5927
- "ancestors.source_entity_ref"
5928
- )
5929
- )
5930
- ).with(
5931
- "retained",
5932
- ["entity_ref"],
5933
- (notPartOfDeletion) => notPartOfDeletion.select("subject").from("ancestors").whereNotNull("ancestors.source_key").where(
5934
- (foreignKeyOrRef) => foreignKeyOrRef.where("ancestors.source_key", "!=", sourceKey).orWhereNotIn("ancestors.target_entity_ref", refs)
5968
+ "ancestors.source_entity_ref"
5935
5969
  )
5936
- ).select("descendants.entity_ref").from("descendants").leftOuterJoin(
5937
- "retained",
5938
- "retained.entity_ref",
5939
- "descendants.entity_ref"
5940
- ).whereNull("retained.entity_ref")
5941
- );
5942
- await knex("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).delete();
5970
+ )
5971
+ ).with(
5972
+ "retained",
5973
+ ["entity_ref"],
5974
+ (notPartOfDeletion) => notPartOfDeletion.select("subject").from("ancestors").whereNotNull("ancestors.source_key").where(
5975
+ (foreignKeyOrRef) => foreignKeyOrRef.where("ancestors.source_key", "!=", sourceKey).orWhereNotIn("ancestors.target_entity_ref", refs)
5976
+ )
5977
+ ).select("descendants.entity_ref AS entity_ref").from("descendants").leftOuterJoin(
5978
+ "retained",
5979
+ "retained.entity_ref",
5980
+ "descendants.entity_ref"
5981
+ ).whereNull("retained.entity_ref").then((rows) => rows.map((row) => row.entity_ref))
5982
+ );
5983
+ return { orphanEntityRefs: orphans };
5984
+ }
5985
+ async function markEntitiesAffectedByDeletionForStitching(options) {
5986
+ const { knex, entityRefs } = options;
5987
+ const affectedIds = await knex.select("refresh_state.entity_id AS entity_id").from("relations").join(
5988
+ "refresh_state",
5989
+ "relations.source_entity_ref",
5990
+ "refresh_state.entity_ref"
5991
+ ).whereIn("relations.target_entity_ref", entityRefs).then((rows) => rows.map((row) => row.entity_id));
5992
+ for (const ids of lodash__default["default"].chunk(affectedIds, 1e3)) {
5993
+ await knex.table("final_entities").update({
5994
+ hash: "force-stitching"
5995
+ }).whereIn("entity_id", ids);
5996
+ await knex.table("refresh_state").update({
5997
+ result_hash: "force-stitching",
5998
+ next_update_at: knex.fn.now()
5999
+ }).whereIn("entity_id", ids);
5943
6000
  }
5944
- return removedCount;
5945
6001
  }
5946
6002
 
5947
6003
  async function refreshByRefreshKeys(options) {
@@ -6750,4 +6806,4 @@ exports.createCatalogPermissionRule = createCatalogPermissionRule;
6750
6806
  exports.createRandomProcessingInterval = createRandomProcessingInterval;
6751
6807
  exports.parseEntityYaml = parseEntityYaml;
6752
6808
  exports.permissionRules = permissionRules;
6753
- //# sourceMappingURL=CatalogBuilder-c40214f8.cjs.js.map
6809
+ //# sourceMappingURL=CatalogBuilder-60d67596.cjs.js.map