@spotify/backstage-plugin-soundcheck-backend-module-github 0.7.14 → 0.8.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,41 @@
1
1
  # @spotify/backstage-plugin-soundcheck-backend-module-github
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependency `backstage` to `1.44.1`.
8
+ - Updated dependencies
9
+ - Updated dependencies
10
+ - Updated dependencies
11
+ - @spotify/backstage-plugin-soundcheck-common@0.19.2
12
+ - @spotify/backstage-plugin-soundcheck-node@0.10.2
13
+
14
+ ## 0.8.0
15
+
16
+ ### Minor Changes
17
+
18
+ - Updated SCM collectors (SCM, GitHub, GitLab, Azure DevOps) to return collection errors instead of
19
+ undefined facts if entity location URL is unsupported or integration details are not found.
20
+
21
+ ### Patch Changes
22
+
23
+ - Updated dependency `backstage` to `1.42.0`.
24
+ - GitHub Fact Collector will now return an error message as a fact instead of an error state
25
+ if dependabot alerts are not enabled for a repository.
26
+ - Updated dependencies
27
+ - Updated dependencies
28
+ - Updated dependencies
29
+ - Updated dependencies
30
+ - Updated dependencies
31
+ - Updated dependencies
32
+ - Updated dependencies
33
+ - Updated dependencies
34
+ - Updated dependencies
35
+ - Updated dependencies
36
+ - @spotify/backstage-plugin-soundcheck-common@0.19.0
37
+ - @spotify/backstage-plugin-soundcheck-node@0.10.0
38
+
3
39
  ## 0.7.14
4
40
 
5
41
  ### Patch Changes
@@ -1,2 +1,2 @@
1
- "use strict";var S=require("@backstage/catalog-model"),d=require("@backstage/integration"),F=require("@octokit/rest"),a=require("@spotify/backstage-plugin-soundcheck-common"),m=require("@spotify/backstage-plugin-soundcheck-node"),v=require("git-url-parse"),x=require("zod-to-json-schema"),C=require("../extractors/BranchProtectionsFactExtractor.cjs.js"),b=require("../extractors/BranchRulesFactExtractor.cjs.js"),q=require("../extractors/CodeScanningAlertsFactExtractor.cjs.js"),R=require("../extractors/config/GithubFactCollectorSchema.cjs.js"),A=require("../extractors/DependabotAlertsFactExtractor.cjs.js"),D=require("../extractors/ExtractorService.cjs.js"),T=require("../extractors/helper/BranchHelper.cjs.js"),L=require("../extractors/RepositoryDetailsFactExtractor.cjs.js"),P=require("../extractors/RepositoryLanguagesFactExtractor.cjs.js"),k=require("../extractors/SecretScanningAlertsFactExtractor.cjs.js"),w=require("../extractors/SecurityAdvisoriesFactExtractor.cjs.js"),U=require("../extractors/store/GithubExtractorsStore.cjs.js");function y(n){return n&&typeof n=="object"&&"default"in n?n:{default:n}}var O=y(v),B=y(x);const G=new Set(["DependabotAlerts","SecretScanningAlerts","CodeScanningAlerts"]);class s{static ID="github";static DEFAULT_TTL=7*24*60*60*1e3;#r;#a;#c;#e;#t;static create(r,t,c){return new s(r,t,c)}id=s.ID;name="GitHub";description="Collects facts about your GitHub repositories.";constructor(r,t,c){this.#r=t.child({target:this.id}),this.#a=d.ScmIntegrations.fromConfig(r),this.#c=d.DefaultGithubCredentialsProvider.fromIntegrations(this.#a),this.#e=D.ExtractorService.create({logger:t,cache:c.withOptions({defaultTtl:s.DEFAULT_TTL}),branchHelper:T.BranchHelper.create(this.#r,c.withOptions({defaultTtl:s.DEFAULT_TTL})),factories:[C.BranchProtectionsFactExtractor.factory,b.BranchRulesFactExtractor.factory,q.CodeScanningAlertsFactExtractor.factory,A.DependabotAlertsFactExtractor.factory,L.RepositoryDetailsFactExtractor.factory,P.RepositoryLanguagesFactExtractor.factory,k.SecretScanningAlertsFactExtractor.factory,w.SecurityAdvisoriesFactExtractor.factory]}),this.#t=U.GithubExtractorsStore.create(this.#r)}async collect(r,t){const c=t?.factRefs??this.#t.getExtractorConfigs().map(e=>a.getFactRef(this.id,e));return Promise.all(r.filter(e=>a.isScmEntity(e)).map(async e=>{const o=S.stringifyEntityRef(e),l=a.getEntityScmUrl(e),p=O.default(l),f=await this.getOctokit(l);return f?Promise.all(c.map(async u=>{const g=a.parseFactRef(u,{defaultSource:this.id,defaultScope:a.DEFAULT_SCOPE}),h=this.#t.getExtractorConfig(g.name),E=!!t?.refresh?.map(i=>a.stringifyFactRef(i))?.includes(a.stringifyFactRef(u));return this.#e.extract(h,g.scope,p,f,E).then(i=>{if(i!==void 0)return a.buildFact(o,u,i,G.has(h.type))}).catch(i=>{if(i instanceof m.RateLimitError)throw i;return this.#r.error(`Failed to collect ${a.stringifyFactRef(u)} fact data for ${o} entity: ${i.message??i}`),a.buildCollectionError(o,u,i)})})):Promise.resolve()})).then(e=>e.flat().filter(o=>!!o))}async getOctokit(r){try{const{token:t}=await this.#c.getCredentials({url:r}),c=this.#a.github.byUrl(r);return new F.Octokit({auth:t,baseUrl:c?.config.apiBaseUrl})}catch(t){this.#r.warn(`Skipping Github fact collection for url ${r}: ${t}`);return}}async getCollectionConfigs(){return a.buildCollectionConfigs(this.id,this.#t.getExtractorConfigs())}async getFactNames(){const r=this.#e.listFactTypes(),t=this.#t.getExtractorConfigs();return r.flatMap(c=>t.filter(e=>e.type===c).map(e=>e.factName??e.type)??c)}async getDataSchema(r){const t=a.parseFactRef(r,{defaultSource:this.id,defaultScope:a.DEFAULT_SCOPE}),c=this.#t.getExtractorConfigs().find(e=>{const o=a.parseFactRef(a.getFactRef(this.id,e));return t.source===o.source&&t.name===o.name});if(c)return this.#e.getDataSchema(c)}async getConfig(){return this.#t.getConfig()}async setConfig(r){this.#t.setConfig(r)}async getConfigSchema(){return JSON.stringify(B.default(R.GithubFactCollectorSchema))}}exports.GithubFactCollector=s;
1
+ "use strict";var F=require("@backstage/catalog-model"),d=require("@backstage/integration"),S=require("@octokit/rest"),t=require("@spotify/backstage-plugin-soundcheck-common"),m=require("@spotify/backstage-plugin-soundcheck-node"),v=require("git-url-parse"),C=require("zod-to-json-schema"),x=require("../extractors/BranchProtectionsFactExtractor.cjs.js"),b=require("../extractors/BranchRulesFactExtractor.cjs.js"),R=require("../extractors/CodeScanningAlertsFactExtractor.cjs.js"),q=require("../extractors/config/GithubFactCollectorSchema.cjs.js"),A=require("../extractors/DependabotAlertsFactExtractor.cjs.js"),D=require("../extractors/ExtractorService.cjs.js"),T=require("../extractors/helper/BranchHelper.cjs.js"),L=require("../extractors/RepositoryDetailsFactExtractor.cjs.js"),P=require("../extractors/RepositoryLanguagesFactExtractor.cjs.js"),U=require("../extractors/SecretScanningAlertsFactExtractor.cjs.js"),k=require("../extractors/SecurityAdvisoriesFactExtractor.cjs.js"),w=require("../extractors/store/GithubExtractorsStore.cjs.js");function y(u){return u&&typeof u=="object"&&"default"in u?u:{default:u}}var O=y(v),B=y(C);const H=new Set(["DependabotAlerts","SecretScanningAlerts","CodeScanningAlerts"]);class n{static ID="github";static DEFAULT_TTL=7*24*60*60*1e3;#r;#a;#i;#e;#t;static create(e,a,r){return new n(e,a,r)}id=n.ID;name="GitHub";description="Collects facts about your GitHub repositories.";constructor(e,a,r){this.#r=a.child({target:this.id}),this.#a=d.ScmIntegrations.fromConfig(e),this.#i=d.DefaultGithubCredentialsProvider.fromIntegrations(this.#a),this.#e=D.ExtractorService.create({logger:a,cache:r.withOptions({defaultTtl:n.DEFAULT_TTL}),branchHelper:T.BranchHelper.create(this.#r,r.withOptions({defaultTtl:n.DEFAULT_TTL})),factories:[x.BranchProtectionsFactExtractor.factory,b.BranchRulesFactExtractor.factory,R.CodeScanningAlertsFactExtractor.factory,A.DependabotAlertsFactExtractor.factory,L.RepositoryDetailsFactExtractor.factory,P.RepositoryLanguagesFactExtractor.factory,U.SecretScanningAlertsFactExtractor.factory,k.SecurityAdvisoriesFactExtractor.factory]}),this.#t=w.GithubExtractorsStore.create(this.#r)}async collect(e,a){const r=a?.factRefs??this.#t.getExtractorConfigs().map(i=>t.getFactRef(this.id,i));return Promise.all(e.map(async i=>{const c=F.stringifyEntityRef(i);try{const s=t.getEntityScmUrl(i),f=O.default(s),E=await this.getOctokit(s);return Promise.all(r.map(async l=>{const g=t.parseFactRef(l,{defaultSource:this.id,defaultScope:t.DEFAULT_SCOPE}),h=this.#t.getExtractorConfig(g.name),p=!!a?.refresh?.map(o=>t.stringifyFactRef(o))?.includes(t.stringifyFactRef(l));return this.#e.extract(h,g.scope,f,E,p).then(o=>{if(o!==void 0)return t.buildFact(c,l,o,H.has(h.type))}).catch(o=>{if(o instanceof m.RateLimitError)throw o;return this.#r.error(`Failed to collect ${t.stringifyFactRef(l)} fact data for ${c} entity: ${o.message??o}`),t.buildCollectionError(c,l,o)})}))}catch(s){return r.map(f=>(this.#r.error(`Failed to collect ${t.stringifyFactRef(f)} fact data for ${c} entity: ${s.message??s}`),t.buildCollectionError(c,f,s)))}})).then(i=>i.flat().filter(c=>!!c))}async getOctokit(e){const{token:a}=await this.#i.getCredentials({url:e}),r=this.#a.github.byUrl(e);return new S.Octokit({auth:a,baseUrl:r?.config.apiBaseUrl})}async getCollectionConfigs(){return t.buildCollectionConfigs(this.id,this.#t.getExtractorConfigs())}async getFactNames(){const e=this.#e.listFactTypes(),a=this.#t.getExtractorConfigs();return e.flatMap(r=>a.filter(i=>i.type===r).map(i=>i.factName??i.type)??r)}async getDataSchema(e){const a=t.parseFactRef(e,{defaultSource:this.id,defaultScope:t.DEFAULT_SCOPE}),r=this.#t.getExtractorConfigs().find(i=>{const c=t.parseFactRef(t.getFactRef(this.id,i));return a.source===c.source&&a.name===c.name});if(r)return this.#e.getDataSchema(r)}async getConfig(){return this.#t.getConfig()}async setConfig(e){this.#t.setConfig(e)}async getConfigSchema(){return JSON.stringify(B.default(q.GithubFactCollectorSchema))}}exports.GithubFactCollector=n;
2
2
  //# sourceMappingURL=GithubFactCollector.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var c=require("./helper/util.cjs.js"),y=require("./schema/dependabot_alerts.json.cjs.js"),g=require("./utils.cjs.js");class d{static TYPE="DependabotAlerts";#t;#e;type=d.TYPE;static factory=({logger:t,cache:s})=>{const a=new d(t,s);return{predicate:h=>h.type===a.type,extractor:a}};constructor(t,s){this.#t=t,this.#e=s}async extract(t,s,a,h,f){const l=[],u={owner:a.owner,repo:a.name,state:t.states?.join(","),severity:t.severities?.join(",")},w=100;let p=0,i=!0;for(;i;){const o=g.getCacheKey("github:dependabot_alerts",u,++p);try{const e=await h.rest.dependabot.listAlertsForRepo({...u,per_page:w,page:p,headers:f?void 0:await g.getCacheHeader(this.#e,o)});e.headers?.link?.includes('rel="next"')||(i=!1);const r=e.data;await this.#e.set(o,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:i,data:r}),l.push(...r)}catch(e){if(c.isNotModifiedError(e)){const n=await this.#e.get(o);if(n){l.push(...n.data),i=n.hasNext,await this.#e.set(o,n);continue}else return}if(c.isNotFoundError(e))return{alerts:[]};const r=`[DependabotAlerts] fact extraction failed with: ${c.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw c.handleRateLimitError(e,r),this.#t.error(r),new Error(r)}}return{alerts:l}}getDataSchema(t){return JSON.stringify(y.default)}}exports.DependabotAlertsFactExtractor=d;
1
+ "use strict";var s=require("./helper/util.cjs.js"),y=require("./schema/dependabot_alerts.json.cjs.js"),g=require("./utils.cjs.js");class c{static TYPE="DependabotAlerts";#t;#e;type=c.TYPE;static factory=({logger:t,cache:i})=>{const a=new c(t,i);return{predicate:h=>h.type===a.type,extractor:a}};constructor(t,i){this.#t=t,this.#e=i}async extract(t,i,a,h,f){const l=[],u={owner:a.owner,repo:a.name,state:t.states?.join(","),severity:t.severities?.join(",")},w=100;let p=0,o=!0;for(;o;){const n=g.getCacheKey("github:dependabot_alerts",u,++p);try{const e=await h.rest.dependabot.listAlertsForRepo({...u,per_page:w,page:p,headers:f?void 0:await g.getCacheHeader(this.#e,n)});e.headers?.link?.includes('rel="next"')||(o=!1);const r=e.data;await this.#e.set(n,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:o,data:r}),l.push(...r)}catch(e){if(s.isNotModifiedError(e)){const d=await this.#e.get(n);if(d){l.push(...d.data),o=d.hasNext,await this.#e.set(n,d);continue}else return}if(s.isNotFoundError(e))return{alerts:[]};if(s.isForbiddenError(e))return e.response.data;const r=`[DependabotAlerts] fact extraction failed with: ${s.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw s.handleRateLimitError(e,r),this.#t.error(r),new Error(r)}}return{alerts:l}}getDataSchema(t){return JSON.stringify(y.default)}}exports.DependabotAlertsFactExtractor=c;
2
2
  //# sourceMappingURL=DependabotAlertsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var t=require("@octokit/request-error"),u=require("@spotify/backstage-plugin-soundcheck-node");function d(r){return r instanceof t.RequestError?r.response?`${r.name} ${r.response.status}: ${JSON.stringify(r.response.data)}`:`${r.name} ${r.status}: ${r.message}`:JSON.stringify(r)}function i(r){return r instanceof t.RequestError&&(r.status===429||r.status===403&&(r.response?.headers["retry-after"]!==void 0||r.response?.headers["x-ratelimit-remaining"]==="0"))}function c(r){return"status"in r&&r.status===304}function f(r){return"status"in r&&r.status===404}function E(r,o){if(i(r)){const s=r;let e=s.response?.headers["retry-after"];if(!e&&s.response?.headers["x-ratelimit-reset"])try{const n=Number.parseInt(s.response.headers["x-ratelimit-reset"],10),a=Math.floor(Date.now()/1e3);e=(n-a+5)*1e3}catch{}throw u.RateLimitError.create(o,r,e?parseInt(e.toString(),10)*1e3:60*1e3)}}exports.buildOctokitErrorMessage=d,exports.handleRateLimitError=E,exports.isNotFoundError=f,exports.isNotModifiedError=c,exports.isRateLimitError=i;
1
+ "use strict";var s=require("@octokit/request-error"),u=require("@spotify/backstage-plugin-soundcheck-node");function d(r){return r instanceof s.RequestError?r.response?`${r.name} ${r.response.status}: ${JSON.stringify(r.response.data)}`:`${r.name} ${r.status}: ${r.message}`:JSON.stringify(r)}function i(r){return r instanceof s.RequestError&&(r.status===429||r.status===403&&(r.response?.headers["retry-after"]!==void 0||r.response?.headers["x-ratelimit-remaining"]==="0"))}function c(r){return r instanceof s.RequestError&&r.status===403&&r.response?.headers["retry-after"]===void 0&&(r.response?.headers["x-ratelimit-remaining"]===void 0||r.response?.headers["x-ratelimit-remaining"]!=="0")}function f(r){return"status"in r&&r.status===304}function m(r){return"status"in r&&r.status===404}function E(r,o){if(i(r)){const e=r;let t=e.response?.headers["retry-after"];if(!t&&e.response?.headers["x-ratelimit-reset"])try{const n=Number.parseInt(e.response.headers["x-ratelimit-reset"],10),a=Math.floor(Date.now()/1e3);t=(n-a+5)*1e3}catch{}throw u.RateLimitError.create(o,r,t?parseInt(t.toString(),10)*1e3:60*1e3)}}exports.buildOctokitErrorMessage=d,exports.handleRateLimitError=E,exports.isForbiddenError=c,exports.isNotFoundError=m,exports.isNotModifiedError=f,exports.isRateLimitError=i;
2
2
  //# sourceMappingURL=util.cjs.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spotify/backstage-plugin-soundcheck-backend-module-github",
3
3
  "description": "Soundcheck 3rd party integration with Github",
4
- "version": "0.7.14",
4
+ "version": "0.8.1",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "homepage": "https://backstage.spotify.com",
7
7
  "main": "dist/index.cjs.js",
@@ -27,24 +27,24 @@
27
27
  "postpack": "backstage-cli package postpack"
28
28
  },
29
29
  "devDependencies": {
30
- "@backstage/backend-test-utils": "^1.7.0",
31
- "@backstage/cli": "^0.33.1",
32
- "@spotify/backstage-plugin-soundcheck-backend": "^0.21.1",
30
+ "@backstage/backend-test-utils": "^1.9.1",
31
+ "@backstage/cli": "^0.34.4",
32
+ "@spotify/backstage-plugin-soundcheck-backend": "^0.22.4",
33
33
  "@types/git-url-parse": "^16.0.0",
34
34
  "@types/luxon": "^3.0.1",
35
35
  "supertest": "^7.0.0"
36
36
  },
37
37
  "dependencies": {
38
- "@backstage/backend-plugin-api": "^1.4.1",
38
+ "@backstage/backend-plugin-api": "^1.4.4",
39
39
  "@backstage/catalog-model": "^1.7.5",
40
- "@backstage/config": "^1.3.3",
40
+ "@backstage/config": "^1.3.5",
41
41
  "@backstage/errors": "^1.2.7",
42
- "@backstage/integration": "^1.17.1",
43
- "@backstage/types": "^1.2.1",
42
+ "@backstage/integration": "^1.18.1",
43
+ "@backstage/types": "^1.2.2",
44
44
  "@octokit/request-error": "^5.0.0",
45
45
  "@octokit/rest": "^20.0.0",
46
- "@spotify/backstage-plugin-soundcheck-common": "^0.18.2",
47
- "@spotify/backstage-plugin-soundcheck-node": "^0.9.11",
46
+ "@spotify/backstage-plugin-soundcheck-common": "^0.19.2",
47
+ "@spotify/backstage-plugin-soundcheck-node": "^0.10.2",
48
48
  "git-url-parse": "^16.0.0",
49
49
  "lodash": "^4.17.21",
50
50
  "luxon": "^3.1.1",