@spotify/backstage-plugin-soundcheck-backend-module-github 0.7.11 → 0.7.13

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,31 @@
1
1
  # @spotify/backstage-plugin-soundcheck-backend-module-github
2
2
 
3
+ ## 0.7.13
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved rate limits handling by GitHub Fact Collector.
8
+ - Updated dependencies
9
+ - @spotify/backstage-plugin-soundcheck-common@0.18.2
10
+
11
+ ## 0.7.12
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependency `@types/git-url-parse` to `^16.0.0`.
16
+ - Updated dependency `backstage` to `1.41.1`.
17
+ - Updates rate limit error handling in Soundcheck to attempt to wait until the server-provided rate-limit-reset time to retry rate-limited requests.
18
+ - Updates to how long eTags are saved in cache.
19
+ - Updates configs for some collectors for Portal compatibility.
20
+ - Updated dependencies
21
+ - Updated dependencies
22
+ - Updated dependencies
23
+ - Updated dependencies
24
+ - Updated dependencies
25
+ - Updated dependencies
26
+ - @spotify/backstage-plugin-soundcheck-common@0.18.1
27
+ - @spotify/backstage-plugin-soundcheck-node@0.9.11
28
+
3
29
  ## 0.7.11
4
30
 
5
31
  ### 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"),C=require("zod-to-json-schema"),x=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"),G=require("../extractors/helper/BranchHelper.cjs.js"),P=require("../extractors/RepositoryDetailsFactExtractor.cjs.js"),k=require("../extractors/RepositoryLanguagesFactExtractor.cjs.js"),w=require("../extractors/SecretScanningAlertsFactExtractor.cjs.js"),B=require("../extractors/SecurityAdvisoriesFactExtractor.cjs.js"),O=require("../extractors/store/GithubExtractorsStore.cjs.js");function y(s){return s&&typeof s=="object"&&"default"in s?s:{default:s}}var U=y(v),H=y(C);const L=new Set(["DependabotAlerts","SecretScanningAlerts","CodeScanningAlerts"]);class u{static ID="github";#r;#a;#c;#e;#t;static create(r,t,c){return new u(r,t,c)}id=u.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,branchHelper:G.BranchHelper.create(this.#r,c.withOptions({defaultTtl:60*60*1e3})),factories:[x.BranchProtectionsFactExtractor.factory,b.BranchRulesFactExtractor.factory,q.CodeScanningAlertsFactExtractor.factory,A.DependabotAlertsFactExtractor.factory,P.RepositoryDetailsFactExtractor.factory,k.RepositoryLanguagesFactExtractor.factory,w.SecretScanningAlertsFactExtractor.factory,B.SecurityAdvisoriesFactExtractor.factory]}),this.#t=O.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=U.default(l),f=await this.getOctokit(l);return f?Promise.all(c.map(async n=>{const g=a.parseFactRef(n,{defaultSource:this.id,defaultScope:a.DEFAULT_SCOPE}),h=this.#t.getExtractorConfig(g.name),E=!!t?.refresh?.map(i=>a.stringifyFactRef(i))?.includes(a.stringifyFactRef(n));return this.#e.extract(h,g.scope,p,f,E).then(i=>{if(i!==void 0)return a.buildFact(o,n,i,L.has(h.type))}).catch(i=>{if(i instanceof m.RateLimitError)throw i;return this.#r.error(`Failed to collect ${a.stringifyFactRef(n)} fact data for ${o} entity: ${i}`),a.buildCollectionError(o,n,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(H.default(R.GithubFactCollectorSchema))}}exports.GithubFactCollector=u;
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=31*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;
2
2
  //# sourceMappingURL=GithubFactCollector.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var l=require("@spotify/backstage-plugin-soundcheck-common"),n=require("./helper/util.cjs.js"),w=require("./schema/branch_protections.json.cjs.js"),f=require("./utils.cjs.js");class o{static TYPE="BranchProtections";#e;#t;#r;type=o.TYPE;static factory=({logger:r,cache:a,branchHelper:t})=>{const i=new o(r,a,t);return{predicate:s=>s.type===i.type,extractor:i}};constructor(r,a,t){this.#e=r,this.#t=a,this.#r=t}async extract(r,a,t,i,s){const c=`github:branch_protections:${t.owner}:${t.name}:${a}`,g=s?void 0:await f.getCacheHeader(this.#t,c),u={owner:t.owner,repo:t.name,branch:await this.#a(a,t,i),headers:g};try{const e=await i.rest.repos.getBranchProtection(u);return await this.#t.set(c,{etag:e.headers?.etag,lastModified:e.headers?.date,data:e.data}),e.data}catch(e){if(n.isNotModifiedError(e)){const d=await this.#t.get(c);return!d||!("data"in d)?void 0:d.data}if(n.isNotFoundError(e))return{};const h=`[BranchProtections] fact extraction failed with: ${n.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw n.handleRateLimitError(e,h),this.#e.error(h),new Error(h)}}async#a(r,a,t){return r!==l.DEFAULT_SCOPE?r:this.#r.getDefaultBranch(a,t)}getDataSchema(r){return JSON.stringify(w.default)}}exports.BranchProtectionsFactExtractor=o;
1
+ "use strict";var w=require("@spotify/backstage-plugin-soundcheck-common"),o=require("./helper/util.cjs.js"),l=require("./schema/branch_protections.json.cjs.js"),f=require("./utils.cjs.js");class c{static TYPE="BranchProtections";#e;#t;#r;type=c.TYPE;static factory=({logger:r,cache:a,branchHelper:t})=>{const i=new c(r,a,t);return{predicate:h=>h.type===i.type,extractor:i}};constructor(r,a,t){this.#e=r,this.#t=a,this.#r=t}async extract(r,a,t,i,h){const s=`github:branch_protections:${t.owner}:${t.name}:${a}`,g=h?void 0:await f.getCacheHeader(this.#t,s),u={owner:t.owner,repo:t.name,branch:await this.#a(a,t,i),headers:g};try{const e=await i.rest.repos.getBranchProtection(u);return await this.#t.set(s,{etag:e.headers?.etag,lastModified:e.headers?.date,data:e.data}),e.data}catch(e){if(o.isNotModifiedError(e)){const n=await this.#t.get(s);return!n||!("data"in n)?void 0:(await this.#t.set(s,n),n.data)}if(o.isNotFoundError(e))return{};const d=`[BranchProtections] fact extraction failed with: ${o.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw o.handleRateLimitError(e,d),this.#e.error(d),new Error(d)}}async#a(r,a,t){return r!==w.DEFAULT_SCOPE?r:this.#r.getDefaultBranch(a,t)}getDataSchema(r){return JSON.stringify(l.default)}}exports.BranchProtectionsFactExtractor=c;
2
2
  //# sourceMappingURL=BranchProtectionsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var y=require("@spotify/backstage-plugin-soundcheck-common"),c=require("./helper/util.cjs.js"),E=require("./schema/branch_rules.json.cjs.js"),p=require("./utils.cjs.js");class n{static TYPE="BranchRules";#t;#e;#r;type=n.TYPE;static factory=({logger:r,cache:a,branchHelper:t})=>{const s=new n(r,a,t);return{predicate:h=>h.type===s.type,extractor:s}};constructor(r,a,t){this.#t=r,this.#e=a,this.#r=t}async extract(r,a,t,s,h){const o=[],u={owner:t.owner,repo:t.name,branch:await this.#a(a,t,s)},w=100;let f=0,i=!0;for(;i;){const l=p.getCacheKey("github:branch_rules",u,++f);try{const e=await s.rest.repos.getBranchRules({...u,per_page:w,page:f,headers:h?void 0:await p.getCacheHeader(this.#e,l)});e.headers?.link?.includes('rel="next"')||(i=!1),await this.#e.set(l,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:i,data:e.data}),o.push(...e.data)}catch(e){if(c.isNotModifiedError(e)){const g=await this.#e.get(l);if(g){o.push(...g.data),i=g.hasNext;continue}else return}if(c.isNotFoundError(e))return{rules:[]};const d=`[BranchRules] fact extraction failed with: ${c.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw c.handleRateLimitError(e,d),this.#t.error(d),new Error(d)}}return{rules:o}}async#a(r,a,t){return r!==y.DEFAULT_SCOPE?r:this.#r.getDefaultBranch(a,t)}getDataSchema(r){return JSON.stringify(E.default)}}exports.BranchRulesFactExtractor=n;
1
+ "use strict";var y=require("@spotify/backstage-plugin-soundcheck-common"),h=require("./helper/util.cjs.js"),E=require("./schema/branch_rules.json.cjs.js"),p=require("./utils.cjs.js");class o{static TYPE="BranchRules";#t;#e;#r;type=o.TYPE;static factory=({logger:r,cache:a,branchHelper:t})=>{const s=new o(r,a,t);return{predicate:u=>u.type===s.type,extractor:s}};constructor(r,a,t){this.#t=r,this.#e=a,this.#r=t}async extract(r,a,t,s,u){const l=[],d={owner:t.owner,repo:t.name,branch:await this.#a(a,t,s)},w=100;let f=0,i=!0;for(;i;){const c=p.getCacheKey("github:branch_rules",d,++f);try{const e=await s.rest.repos.getBranchRules({...d,per_page:w,page:f,headers:u?void 0:await p.getCacheHeader(this.#e,c)});e.headers?.link?.includes('rel="next"')||(i=!1),await this.#e.set(c,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:i,data:e.data}),l.push(...e.data)}catch(e){if(h.isNotModifiedError(e)){const n=await this.#e.get(c);if(n){l.push(...n.data),i=n.hasNext,await this.#e.set(c,n);continue}else return}if(h.isNotFoundError(e))return{rules:[]};const g=`[BranchRules] fact extraction failed with: ${h.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(d)}`;throw h.handleRateLimitError(e,g),this.#t.error(g),new Error(g)}}return{rules:l}}async#a(r,a,t){return r!==y.DEFAULT_SCOPE?r:this.#r.getDefaultBranch(a,t)}getDataSchema(r){return JSON.stringify(E.default)}}exports.BranchRulesFactExtractor=o;
2
2
  //# sourceMappingURL=BranchRulesFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var w=require("@spotify/backstage-plugin-soundcheck-common"),i=require("./helper/util.cjs.js"),E=require("./schema/code_scanning_alerts.json.cjs.js"),f=require("./utils.cjs.js");class n{static TYPE="CodeScanningAlerts";#t;#e;type=n.TYPE;static factory=({logger:t,cache:r})=>{const a=new n(t,r);return{predicate:o=>o.type===a.type,extractor:a}};constructor(t,r){this.#t=t,this.#e=r}async extract(t,r,a,o,p){const c=[],d={owner:a.owner,repo:a.name,ref:r!==w.DEFAULT_SCOPE?r:void 0,tool_name:t.toolName,state:t.state,severity:t.severity},y=100;let g=0,s=!0;for(;s;){const h=f.getCacheKey("github:code_scanning",d,++g);try{const e=await o.rest.codeScanning.listAlertsForRepo({...d,per_page:y,page:g,headers:p?void 0:await f.getCacheHeader(this.#e,h)});e.headers?.link?.includes('rel="next"')||(s=!1),await this.#e.set(h,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:s,data:e.data}),c.push(...e.data)}catch(e){if(i.isNotModifiedError(e)){const u=await this.#e.get(h);if(u){c.push(...u.data),s=u.hasNext;continue}else return}if(i.isNotFoundError(e))return{alerts:[]};const l=`[CodeScanningAlerts] fact extraction failed with: ${i.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(d)}`;throw i.handleRateLimitError(e,l),this.#t.error(l),new Error(l)}}return{alerts:c}}getDataSchema(t){return JSON.stringify(E.default)}}exports.CodeScanningAlertsFactExtractor=n;
1
+ "use strict";var y=require("@spotify/backstage-plugin-soundcheck-common"),o=require("./helper/util.cjs.js"),E=require("./schema/code_scanning_alerts.json.cjs.js"),f=require("./utils.cjs.js");class c{static TYPE="CodeScanningAlerts";#t;#e;type=c.TYPE;static factory=({logger:t,cache:r})=>{const a=new c(t,r);return{predicate:d=>d.type===a.type,extractor:a}};constructor(t,r){this.#t=t,this.#e=r}async extract(t,r,a,d,p){const h=[],l={owner:a.owner,repo:a.name,ref:r!==y.DEFAULT_SCOPE?r:void 0,tool_name:t.toolName,state:t.state,severity:t.severity},w=100;let g=0,s=!0;for(;s;){const i=f.getCacheKey("github:code_scanning",l,++g);try{const e=await d.rest.codeScanning.listAlertsForRepo({...l,per_page:w,page:g,headers:p?void 0:await f.getCacheHeader(this.#e,i)});e.headers?.link?.includes('rel="next"')||(s=!1),await this.#e.set(i,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:s,data:e.data}),h.push(...e.data)}catch(e){if(o.isNotModifiedError(e)){const n=await this.#e.get(i);if(n){h.push(...n.data),s=n.hasNext,await this.#e.set(i,n);continue}else return}if(o.isNotFoundError(e))return{alerts:[]};const u=`[CodeScanningAlerts] fact extraction failed with: ${o.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(l)}`;throw o.handleRateLimitError(e,u),this.#t.error(u),new Error(u)}}return{alerts:h}}getDataSchema(t){return JSON.stringify(E.default)}}exports.CodeScanningAlertsFactExtractor=c;
2
2
  //# sourceMappingURL=CodeScanningAlertsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var o=require("./helper/util.cjs.js"),y=require("./schema/dependabot_alerts.json.cjs.js"),g=require("./utils.cjs.js");class n{static TYPE="DependabotAlerts";#t;#e;type=n.TYPE;static factory=({logger:t,cache:s})=>{const a=new n(t,s);return{predicate:c=>c.type===a.type,extractor:a}};constructor(t,s){this.#t=t,this.#e=s}async extract(t,s,a,c,f){const d=[],h={owner:a.owner,repo:a.name,state:t.states?.join(","),severity:t.severities?.join(",")},w=100;let p=0,i=!0;for(;i;){const l=g.getCacheKey("github:dependabot_alerts",h,++p);try{const e=await c.rest.dependabot.listAlertsForRepo({...h,per_page:w,page:p,headers:f?void 0:await g.getCacheHeader(this.#e,l)});e.headers?.link?.includes('rel="next"')||(i=!1);const r=e.data;await this.#e.set(l,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:i,data:r}),d.push(...r)}catch(e){if(o.isNotModifiedError(e)){const u=await this.#e.get(l);if(u){d.push(...u.data),i=u.hasNext;continue}else return}if(o.isNotFoundError(e))return{alerts:[]};const r=`[DependabotAlerts] fact extraction failed with: ${o.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(h)}`;throw o.handleRateLimitError(e,r),this.#t.error(r),new Error(r)}}return{alerts:d}}getDataSchema(t){return JSON.stringify(y.default)}}exports.DependabotAlertsFactExtractor=n;
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;
2
2
  //# sourceMappingURL=DependabotAlertsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var i=require("./helper/util.cjs.js"),g=require("./schema/repository_details.json.cjs.js"),y=require("./utils.cjs.js");class s{static TYPE="RepositoryDetails";#e;#t;type=s.TYPE;static factory=({logger:r,cache:a})=>{const e=new s(r,a);return{predicate:o=>o.type===e.type,extractor:e}};constructor(r,a){this.#e=r,this.#t=a}async extract(r,a,e,o,u){const c=`github:repository_details:${e.owner}:${e.name}`,l=u?void 0:await y.getCacheHeader(this.#t,c),h={owner:e.owner,repo:e.name,headers:l};try{const t=await o.rest.repos.get(h);return await this.#t.set(c,{etag:t.headers?.etag,lastModified:t.headers?.date,data:t.data}),t.data}catch(t){if(i.isNotModifiedError(t)){const n=await this.#t.get(c);return!n||!("data"in n)?void 0:n.data}if(i.isNotFoundError(t))return{};const d=`[RepositoryDetails] fact extraction failed with: ${i.buildOctokitErrorMessage(t)}. Request parameters: ${JSON.stringify(h)}`;throw i.handleRateLimitError(t,d),this.#e.error(d),new Error(d)}}getDataSchema(r){return JSON.stringify(g.default)}}exports.RepositoryDetailsFactExtractor=s;
1
+ "use strict";var o=require("./helper/util.cjs.js"),g=require("./schema/repository_details.json.cjs.js"),w=require("./utils.cjs.js");class c{static TYPE="RepositoryDetails";#e;#t;type=c.TYPE;static factory=({logger:r,cache:a})=>{const e=new c(r,a);return{predicate:d=>d.type===e.type,extractor:e}};constructor(r,a){this.#e=r,this.#t=a}async extract(r,a,e,d,u){const i=`github:repository_details:${e.owner}:${e.name}`,l=u?void 0:await w.getCacheHeader(this.#t,i),h={owner:e.owner,repo:e.name,headers:l};try{const t=await d.rest.repos.get(h);return await this.#t.set(i,{etag:t.headers?.etag,lastModified:t.headers?.date,data:t.data}),t.data}catch(t){if(o.isNotModifiedError(t)){const s=await this.#t.get(i);return!s||!("data"in s)?void 0:(await this.#t.set(i,s),s.data)}if(o.isNotFoundError(t))return{};const n=`[RepositoryDetails] fact extraction failed with: ${o.buildOctokitErrorMessage(t)}. Request parameters: ${JSON.stringify(h)}`;throw o.handleRateLimitError(t,n),this.#e.error(n),new Error(n)}}getDataSchema(r){return JSON.stringify(g.default)}}exports.RepositoryDetailsFactExtractor=c;
2
2
  //# sourceMappingURL=RepositoryDetailsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var i=require("./helper/util.cjs.js"),l=require("./schema/repository_languages.json.cjs.js"),y=require("./utils.cjs.js");class s{static TYPE="RepositoryLanguages";#e;#t;type=s.TYPE;static factory=({logger:r,cache:a})=>{const e=new s(r,a);return{predicate:o=>o.type===e.type,extractor:e}};constructor(r,a){this.#e=r,this.#t=a}async extract(r,a,e,o,g){const n=`github:repository_languages:${e.owner}:${e.name}`,h=g?void 0:await y.getCacheHeader(this.#t,n),u={owner:e.owner,repo:e.name,headers:h};try{const t=await o.rest.repos.listLanguages(u);return await this.#t.set(n,{etag:t.headers?.etag,lastModified:t.headers?.date,data:t.data}),t.data}catch(t){if(i.isNotModifiedError(t)){const d=await this.#t.get(n);return!d||!("data"in d)?void 0:d.data}if(i.isNotFoundError(t))return{};const c=`[RepositoryLanguages] fact extraction failed with: ${i.buildOctokitErrorMessage(t)}. Request parameters: ${JSON.stringify(u)}`;throw i.handleRateLimitError(t,c),this.#e.error(c),new Error(c)}}getDataSchema(r){return JSON.stringify(l.default)}}exports.RepositoryLanguagesFactExtractor=s;
1
+ "use strict";var o=require("./helper/util.cjs.js"),l=require("./schema/repository_languages.json.cjs.js"),w=require("./utils.cjs.js");class n{static TYPE="RepositoryLanguages";#e;#t;type=n.TYPE;static factory=({logger:r,cache:a})=>{const e=new n(r,a);return{predicate:c=>c.type===e.type,extractor:e}};constructor(r,a){this.#e=r,this.#t=a}async extract(r,a,e,c,g){const i=`github:repository_languages:${e.owner}:${e.name}`,h=g?void 0:await w.getCacheHeader(this.#t,i),u={owner:e.owner,repo:e.name,headers:h};try{const t=await c.rest.repos.listLanguages(u);return await this.#t.set(i,{etag:t.headers?.etag,lastModified:t.headers?.date,data:t.data}),t.data}catch(t){if(o.isNotModifiedError(t)){const s=await this.#t.get(i);return!s||!("data"in s)?void 0:(await this.#t.set(i,s),s.data)}if(o.isNotFoundError(t))return{};const d=`[RepositoryLanguages] fact extraction failed with: ${o.buildOctokitErrorMessage(t)}. Request parameters: ${JSON.stringify(u)}`;throw o.handleRateLimitError(t,d),this.#e.error(d),new Error(d)}}getDataSchema(r){return JSON.stringify(l.default)}}exports.RepositoryLanguagesFactExtractor=n;
2
2
  //# sourceMappingURL=RepositoryLanguagesFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var i=require("./helper/util.cjs.js"),y=require("./schema/secret_scanning_alerts.json.cjs.js"),p=require("./utils.cjs.js");class n{static TYPE="SecretScanningAlerts";#t;#e;type=n.TYPE;static factory=({logger:t,cache:a})=>{const r=new n(t,a);return{predicate:c=>c.type===r.type,extractor:r}};constructor(t,a){this.#t=t,this.#e=a}async extract(t,a,r,c,f){const o=[],d={owner:r.owner,repo:r.name,state:t.state,validity:t.validities?.join(",")},w=100;let g=0,s=!0;for(;s;){const h=p.getCacheKey("github:secret_scanning",d,++g);try{const e=await c.rest.secretScanning.listAlertsForRepo({...d,per_page:w,page:g,headers:f?void 0:await p.getCacheHeader(this.#e,h)});e.headers?.link?.includes('rel="next"')||(s=!1),await this.#e.set(h,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:s,data:e.data}),o.push(...e.data)}catch(e){if(i.isNotModifiedError(e)){const u=await this.#e.get(h);if(u){o.push(...u.data),s=u.hasNext;continue}else return}if(i.isNotFoundError(e))return{alerts:[]};const l=`[SecretScanningAlerts] fact extraction failed with: ${i.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(d)}`;throw i.handleRateLimitError(e,l),this.#t.error(l),new Error(l)}}return{alerts:o}}getDataSchema(t){return JSON.stringify(y.default)}}exports.SecretScanningAlertsFactExtractor=n;
1
+ "use strict";var c=require("./helper/util.cjs.js"),y=require("./schema/secret_scanning_alerts.json.cjs.js"),p=require("./utils.cjs.js");class o{static TYPE="SecretScanningAlerts";#e;#t;type=o.TYPE;static factory=({logger:e,cache:a})=>{const r=new o(e,a);return{predicate:d=>d.type===r.type,extractor:r}};constructor(e,a){this.#e=e,this.#t=a}async extract(e,a,r,d,f){const h=[],l={owner:r.owner,repo:r.name,state:e.state,validity:e.validities?.join(",")},w=100;let g=0,s=!0;for(;s;){const i=p.getCacheKey("github:secret_scanning",l,++g);try{const t=await d.rest.secretScanning.listAlertsForRepo({...l,per_page:w,page:g,headers:f?void 0:await p.getCacheHeader(this.#t,i)});t.headers?.link?.includes('rel="next"')||(s=!1),await this.#t.set(i,{etag:t.headers?.etag,lastModified:t.headers?.date,hasNext:s,data:t.data}),h.push(...t.data)}catch(t){if(c.isNotModifiedError(t)){const n=await this.#t.get(i);if(n){h.push(...n.data),s=n.hasNext,await this.#t.set(i,n);continue}else return}if(c.isNotFoundError(t))return{alerts:[]};const u=`[SecretScanningAlerts] fact extraction failed with: ${c.buildOctokitErrorMessage(t)}. Request parameters: ${JSON.stringify(l)}`;throw c.handleRateLimitError(t,u),this.#e.error(u),new Error(u)}}return{alerts:h}}getDataSchema(e){return JSON.stringify(y.default)}}exports.SecretScanningAlertsFactExtractor=o;
2
2
  //# sourceMappingURL=SecretScanningAlertsFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var o=require("./helper/util.cjs.js"),v=require("./schema/security_advisories.json.cjs.js"),y=require("./utils.cjs.js");class c{static TYPE="SecurityAdvisories";#t;#e;type=c.TYPE;static factory=({logger:t,cache:s})=>{const i=new c(t,s);return{predicate:d=>d.type===i.type,extractor:i}};constructor(t,s){this.#t=t,this.#e=s}async extract(t,s,i,d,p){const n=[],u={owner:i.owner,repo:i.name,state:t.state},f=100;let l=0,a=!0;for(;a;){const h=y.getCacheKey("github:security_advisories",u,++l);try{const e=await d.rest.securityAdvisories.listRepositoryAdvisories({...u,per_page:f,page:l,headers:p?void 0:await y.getCacheHeader(this.#e,h)});e.headers?.link?.includes('rel="next"')||(a=!1);const r=e.data;await this.#e.set(h,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:a,data:r}),n.push(...r)}catch(e){if(o.isNotModifiedError(e)){const g=await this.#e.get(h);if(g){n.push(...g.data),a=g.hasNext;continue}else return}if(o.isNotFoundError(e))return{advisories:[]};const r=`[SecurityAdvisories] fact extraction failed with: ${o.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(u)}`;throw o.handleRateLimitError(e,r),this.#t.error(r),new Error(r)}}return{advisories:n}}getDataSchema(t){return JSON.stringify(v.default)}}exports.SecurityAdvisoriesFactExtractor=c;
1
+ "use strict";var d=require("./helper/util.cjs.js"),v=require("./schema/security_advisories.json.cjs.js"),y=require("./utils.cjs.js");class n{static TYPE="SecurityAdvisories";#t;#e;type=n.TYPE;static factory=({logger:t,cache:s})=>{const i=new n(t,s);return{predicate:u=>u.type===i.type,extractor:i}};constructor(t,s){this.#t=t,this.#e=s}async extract(t,s,i,u,f){const h=[],g={owner:i.owner,repo:i.name,state:t.state},p=100;let l=0,a=!0;for(;a;){const o=y.getCacheKey("github:security_advisories",g,++l);try{const e=await u.rest.securityAdvisories.listRepositoryAdvisories({...g,per_page:p,page:l,headers:f?void 0:await y.getCacheHeader(this.#e,o)});e.headers?.link?.includes('rel="next"')||(a=!1);const r=e.data;await this.#e.set(o,{etag:e.headers?.etag,lastModified:e.headers?.date,hasNext:a,data:r}),h.push(...r)}catch(e){if(d.isNotModifiedError(e)){const c=await this.#e.get(o);if(c){h.push(...c.data),a=c.hasNext,await this.#e.set(o,c);continue}else return}if(d.isNotFoundError(e))return{advisories:[]};const r=`[SecurityAdvisories] fact extraction failed with: ${d.buildOctokitErrorMessage(e)}. Request parameters: ${JSON.stringify(g)}`;throw d.handleRateLimitError(e,r),this.#t.error(r),new Error(r)}}return{advisories:h}}getDataSchema(t){return JSON.stringify(v.default)}}exports.SecurityAdvisoriesFactExtractor=n;
2
2
  //# sourceMappingURL=SecurityAdvisoriesFactExtractor.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var c=require("./util.cjs.js");class e{#r;#t;static create(t,a){return new e(t,a)}constructor(t,a){this.#r=t,this.#t=a}async getDefaultBranch(t,a){let r=await this.#t.get(t.full_name);if(r!==void 0)return r;const i={owner:t.owner,repo:t.name};try{r=(await a.rest.repos.get(i)).data.default_branch,await this.#t.set(t.full_name,r)}catch(n){t.ref?r=t.ref:r="main";const s=`Failed to get default branch name with: ${c.buildOctokitErrorMessage(n)}. Request parameters: ${JSON.stringify(i)}. Falling back to using [${r}] as default branch`;c.handleRateLimitError(n,s),this.#r.error(s)}return r}}exports.BranchHelper=e;
1
+ "use strict";var u=require("../utils.cjs.js"),n=require("./util.cjs.js");class o{#a;#t;static create(t,e){return new o(t,e)}constructor(t,e){this.#a=t,this.#t=e}async getDefaultBranch(t,e){let r;const i=`github:repository_details:${t.owner}:${t.name}`,h=await u.getCacheHeader(this.#t,i),c={owner:t.owner,repo:t.name,headers:h};try{const a=await e.rest.repos.get(c);r=a.data.default_branch,await this.#t.set(i,{etag:a.headers?.etag,lastModified:a.headers?.date,data:a.data})}catch(a){if(n.isNotModifiedError(a)){const s=await this.#t.get(i);if(s&&"data"in s)return await this.#t.set(i,s),s.data.default_branch}t.ref?r=t.ref:r="main";const d=`Failed to get default branch name with: ${n.buildOctokitErrorMessage(a)}. Request parameters: ${JSON.stringify(c)}. Falling back to using [${r}] as default branch`;n.handleRateLimitError(a,d),this.#a.error(d)}return r}}exports.BranchHelper=o;
2
2
  //# sourceMappingURL=BranchHelper.cjs.js.map
@@ -1,2 +1,2 @@
1
- "use strict";var s=require("@octokit/request-error"),o=require("@spotify/backstage-plugin-soundcheck-node");function n(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 t(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 a(r){return"status"in r&&r.status===304}function u(r){return"status"in r&&r.status===404}function d(r,i){if(t(r)){const e=r.response?.headers["retry-after"];throw new o.RateLimitError(i,r,e?parseInt(e.toString(),10)*1e3:60*1e3)}}exports.buildOctokitErrorMessage=n,exports.handleRateLimitError=d,exports.isNotFoundError=u,exports.isNotModifiedError=a,exports.isRateLimitError=t;
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;
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.11",
4
+ "version": "0.7.13",
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.6.0",
31
- "@backstage/cli": "^0.33.0",
32
- "@spotify/backstage-plugin-soundcheck-backend": "^0.21.0",
33
- "@types/git-url-parse": "^9.0.0",
30
+ "@backstage/backend-test-utils": "^1.7.0",
31
+ "@backstage/cli": "^0.33.1",
32
+ "@spotify/backstage-plugin-soundcheck-backend": "^0.21.1",
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.0",
39
- "@backstage/catalog-model": "^1.7.4",
40
- "@backstage/config": "^1.3.2",
38
+ "@backstage/backend-plugin-api": "^1.4.1",
39
+ "@backstage/catalog-model": "^1.7.5",
40
+ "@backstage/config": "^1.3.3",
41
41
  "@backstage/errors": "^1.2.7",
42
- "@backstage/integration": "^1.17.0",
42
+ "@backstage/integration": "^1.17.1",
43
43
  "@backstage/types": "^1.2.1",
44
44
  "@octokit/request-error": "^5.0.0",
45
45
  "@octokit/rest": "^20.0.0",
46
- "@spotify/backstage-plugin-soundcheck-common": "^0.18.0",
47
- "@spotify/backstage-plugin-soundcheck-node": "^0.9.10",
46
+ "@spotify/backstage-plugin-soundcheck-common": "^0.18.2",
47
+ "@spotify/backstage-plugin-soundcheck-node": "^0.9.11",
48
48
  "git-url-parse": "^16.0.0",
49
49
  "lodash": "^4.17.21",
50
50
  "luxon": "^3.1.1",