From 07995f2ea042bb05879948148c6edd4b21390a87 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 19 Nov 2020 04:09:02 +0100 Subject: [PATCH 01/80] chore(git): messing around with git libraries --- plugins/scaffolder-backend/package.json | 7 +- .../src/scaffolder/stages/prepare/github.ts | 48 ++++++++----- yarn.lock | 72 ++++++++++++++++--- 3 files changed, 94 insertions(+), 33 deletions(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 4bed7ea60c..09c4e0cd87 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -32,6 +32,7 @@ "command-exists-promise": "^2.0.2", "compression": "^1.7.4", "cors": "^2.8.5", + "cross-fetch": "^3.0.6", "dockerode": "^3.2.0", "express": "^4.17.1", "express-promise-router": "^3.0.3", @@ -39,20 +40,18 @@ "git-url-parse": "^11.4.0", "globby": "^11.0.0", "helmet": "^4.0.0", + "isomorphic-git": "^1.8.0", "jsonschema": "^1.2.6", "morgan": "^1.10.0", - "nodegit": "0.27.0", "uuid": "^8.2.0", "winston": "^3.2.1", - "yaml": "^1.10.0", - "cross-fetch": "^3.0.6" + "yaml": "^1.10.0" }, "devDependencies": { "@backstage/cli": "^0.2.0", "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", - "@types/nodegit": "0.26.11", "@types/supertest": "^2.0.8", "supertest": "^4.0.2", "yaml": "^1.10.0" diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index e6b41907be..a4ad4afe32 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -21,7 +21,8 @@ import { parseLocationAnnotation } from '../helpers'; import { InputError } from '@backstage/backend-common'; import { PreparerBase, PreparerOptions } from './types'; import GitUriParser from 'git-url-parse'; -import { Clone, CloneOptions, Cred } from 'nodegit'; +import git from 'isomorphic-git'; +import http from 'isomorphic-git/http/node'; export class GithubPreparer implements PreparerBase { token?: string; @@ -56,25 +57,36 @@ export class GithubPreparer implements PreparerBase { template.spec.path ?? '.', ); - let cloneOptions: CloneOptions = { - checkoutBranch: parsedGitLocation.ref, - }; - - if (token) { - cloneOptions = { - ...cloneOptions, - fetchOpts: { - callbacks: { - credentials() { - return Cred.userpassPlaintextNew(token, 'x-oauth-basic'); - }, - }, + console.warn(repositoryCheckoutUrl); + const finalplace = path.resolve(tempDir, templateDirectory); + try { + await git.clone({ + fs: require('fs'), + http, + url: repositoryCheckoutUrl, + dir: finalplace, + // corsProxy: 'https://cors.isomorphic-git.org', + singleBranch: true, + // need this header + headers: { + 'user-agent': 'git/@isomorphic-git/cors-proxy', }, - }; + depth: 1, + }); + // onAuth: () => ({ username: token, password: 'x-oauth-basic' }), + } catch (ex) { + console.warn(ex.data.url); + console.warn({ + fs: require('fs'), + http, + url: repositoryCheckoutUrl, + dir: templateDirectory, + depth: 1, + onAuth: () => ({ username: token, password: 'x-oauth-basic' }), + }); + throw ex; } - await Clone.clone(repositoryCheckoutUrl, tempDir, cloneOptions); - - return path.resolve(tempDir, templateDirectory); + return finalplace; } } diff --git a/yarn.lock b/yarn.lock index feacd32d97..3450a410c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5550,13 +5550,6 @@ resolved "https://registry.npmjs.org/@types/node/-/node-13.13.15.tgz#fe1cc3aa465a3ea6858b793fd380b66c39919766" integrity sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw== -"@types/nodegit@0.26.11": - version "0.26.11" - resolved "https://registry.npmjs.org/@types/nodegit/-/nodegit-0.26.11.tgz#0cbc5e929f23e5ffc536920e3a887e0b3f46d1a4" - integrity sha512-BGrY9F8lBtfU+Ne1Pjb9k/PUsfSCUAqPXgKkTkM6mc5213H5VAoM12zG/sz/cr3jI3AXcngNbAYWlqSrXsWJug== - dependencies: - "@types/node" "*" - "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -7134,6 +7127,11 @@ async-limiter@~1.0.0: resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-lock@^1.1.0: + version "1.2.4" + resolved "https://registry.npmjs.org/async-lock/-/async-lock-1.2.4.tgz#80d0d612383045dd0c30eb5aad08510c1397cb91" + integrity sha512-UBQJC2pbeyGutIfYmErGc9RaJYnpZ1FHaxuKwb0ahvGiiCkPUf3p67Io+YLPmmv3RHY+mF6JEtNW8FlHsraAaA== + async-retry@^1.2.1: version "1.3.1" resolved "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz#139f31f8ddce50c0870b0ba558a6079684aaed55" @@ -8534,6 +8532,11 @@ clean-css@^4.2.3: dependencies: source-map "~0.6.0" +clean-git-ref@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz#dcc0ca093b90e527e67adb5a5e55b1af6816dcd9" + integrity sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -9284,6 +9287,14 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + create-ecdh@^4.0.0: version "4.0.3" resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" @@ -10330,6 +10341,11 @@ diff-sequences@^26.5.0: resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz#ef766cf09d43ed40406611f11c6d8d9dd8b2fefd" integrity sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q== +diff3@0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz#d4e5c3a4cdf4e5fe1211ab42e693fcb4321580fc" + integrity sha1-1OXDpM305f4SEatC5pP8tDIVgPw= + diff@^4.0.1, diff@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -11407,6 +11423,11 @@ exit-hook@^1.0.0: resolved "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -14360,6 +14381,23 @@ isomorphic-form-data@~2.0.0: dependencies: form-data "^2.3.2" +isomorphic-git@^1.8.0: + version "1.8.0" + resolved "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.8.0.tgz#50440650a64706a321cbea1af955c1cf1110b238" + integrity sha512-TWJvQh+++eFrEG0IFS/jLhMwsBoCOX1/Dsw9q8no59Mp1K0jEjSHXFWv2P04PwkxcIpePkXVBI5YFcFT2nkuQg== + dependencies: + async-lock "^1.1.0" + clean-git-ref "^2.0.1" + crc-32 "^1.2.0" + diff3 "0.0.3" + ignore "^5.1.4" + minimisted "^2.0.0" + pako "^1.0.10" + pify "^4.0.1" + readable-stream "^3.4.0" + sha.js "^2.4.9" + simple-get "^3.0.2" + isomorphic-ws@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" @@ -16629,6 +16667,13 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimisted@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz#d059fb905beecf0774bc3b308468699709805cb1" + integrity sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA== + dependencies: + minimist "^1.2.5" + minipass-collect@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" @@ -17203,7 +17248,7 @@ node-request-interceptor@^0.5.1: debug "^4.1.1" headers-utils "^1.2.0" -nodegit@0.27.0, nodegit@^0.27.0: +nodegit@^0.27.0: version "0.27.0" resolved "https://registry.npmjs.org/nodegit/-/nodegit-0.27.0.tgz#4e8cc236f60e1c97324a5acff99056fe116a6ebe" integrity sha512-E9K4gPjWiA0b3Tx5lfWCzG7Cvodi2idl3V5UD2fZrOrHikIfrN7Fc2kWLtMUqqomyoToYJLeIC8IV7xb1CYRLA== @@ -17950,7 +17995,7 @@ packet-reader@1.0.0: resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== -pako@~1.0.5: +pako@^1.0.10, pako@~1.0.5: version "1.0.11" resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -19111,6 +19156,11 @@ pretty-hrtime@^1.0.3: resolved "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + prismjs@^1.21.0, prismjs@^1.8.4, prismjs@~1.21.0: version "1.21.0" resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" @@ -21270,7 +21320,7 @@ setprototypeof@1.2.0: resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: +sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8, sha.js@^2.4.9: version "2.4.11" resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -21382,7 +21432,7 @@ simple-concat@^1.0.0: resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^3.0.3: +simple-get@^3.0.2, simple-get@^3.0.3: version "3.1.0" resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== From 572b61825989fc42c4013beb7f9077f3ddf4092e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 1 Dec 2020 13:44:32 +0100 Subject: [PATCH 02/80] chore(scaffolder): remove extra logging stuff --- .../src/scaffolder/stages/prepare/github.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index a4ad4afe32..1eef5397de 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -57,24 +57,23 @@ export class GithubPreparer implements PreparerBase { template.spec.path ?? '.', ); - console.warn(repositoryCheckoutUrl); - const finalplace = path.resolve(tempDir, templateDirectory); + const checkoutLocation = path.resolve(tempDir, templateDirectory); + try { await git.clone({ fs: require('fs'), http, url: repositoryCheckoutUrl, - dir: finalplace, - // corsProxy: 'https://cors.isomorphic-git.org', + dir: checkoutLocation, singleBranch: true, - // need this header - headers: { - 'user-agent': 'git/@isomorphic-git/cors-proxy', - }, depth: 1, + onAuth: () => ({ username: token, password: 'x-oauth-basic' }), }); - // onAuth: () => ({ username: token, password: 'x-oauth-basic' }), } catch (ex) { + opts.logger.error( + `Failed checking out repository:${repositoryCheckoutUrl}`, + ); + opts.logger.error(ex.message); console.warn(ex.data.url); console.warn({ fs: require('fs'), @@ -87,6 +86,6 @@ export class GithubPreparer implements PreparerBase { throw ex; } - return finalplace; + return checkoutLocation; } } From f393f300e565a50fc20fca8c9cf2ac2abe14e978 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 1 Dec 2020 20:04:36 +0100 Subject: [PATCH 03/80] chore: refactiring the on progress callback so we can see more ata and failures --- .../src/scaffolder/stages/prepare/github.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 1eef5397de..ff814c20ba 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -67,22 +67,22 @@ export class GithubPreparer implements PreparerBase { dir: checkoutLocation, singleBranch: true, depth: 1, + onProgress: event => { + const total = event.total + ? `${event.loaded / event.total}%` + : event.loaded; + opts.logger.info({ status: event.phase, total }); + }, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, onAuth: () => ({ username: token, password: 'x-oauth-basic' }), }); } catch (ex) { opts.logger.error( - `Failed checking out repository:${repositoryCheckoutUrl}`, + `Failed checking out repository: ${repositoryCheckoutUrl}`, ); opts.logger.error(ex.message); - console.warn(ex.data.url); - console.warn({ - fs: require('fs'), - http, - url: repositoryCheckoutUrl, - dir: templateDirectory, - depth: 1, - onAuth: () => ({ username: token, password: 'x-oauth-basic' }), - }); throw ex; } From a5414403bd15232a231fd44ba67c233852d9b05c Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 1 Dec 2020 21:07:20 +0100 Subject: [PATCH 04/80] chore: reworking more of the github flow so that we can move to isomorphic git instead of nodegit :() --- .../src/scaffolder/stages/prepare/github.ts | 2 +- .../src/scaffolder/stages/publish/github.ts | 12 ++-- .../src/scaffolder/stages/publish/helpers.ts | 68 ++++++++++--------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index ff814c20ba..f202c609cc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -61,7 +61,7 @@ export class GithubPreparer implements PreparerBase { try { await git.clone({ - fs: require('fs'), + fs, http, url: repositoryCheckoutUrl, dir: checkoutLocation, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index d5542e8800..0306bb72e9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -16,7 +16,7 @@ import { PublisherBase } from './types'; import { Octokit } from '@octokit/rest'; -import { pushToRemoteUserPass } from './helpers'; +import { pushToRemoteCred } from './helpers'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; @@ -51,12 +51,10 @@ export class GithubPublisher implements PublisherBase { directory: string; }): Promise<{ remoteUrl: string }> { const remoteUrl = await this.createRemote(values); - await pushToRemoteUserPass( - directory, - remoteUrl, - this.token, - 'x-oauth-basic', - ); + await pushToRemoteCred(directory, remoteUrl, { + username: this.token, + password: 'x-auth-basic', + }); return { remoteUrl }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index 51f5a4c854..61e76a31be 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -13,43 +13,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Repository, Remote, Signature, Cred } from 'nodegit'; + +import git from 'isomorphic-git'; +import globby from 'globby'; +import fs from 'fs'; +import http from 'isomorphic-git/http/node'; export async function pushToRemoteCred( - directory: string, + dir: string, remote: string, - credentialsProvider: () => Cred, + auth?: { username: string; password: string }, ): Promise { - const repo = await Repository.init(directory, 0); - const index = await repo.refreshIndex(); - await index.addAll(); - await index.write(); - const oid = await index.writeTree(); - await repo.createCommit( - 'HEAD', - Signature.now('Scaffolder', 'scaffolder@backstage.io'), - Signature.now('Scaffolder', 'scaffolder@backstage.io'), - 'initial commit', - oid, - [], - ); + await git.init({ + fs, + dir, + }); - const remoteRepo = await Remote.create(repo, 'origin', remote); + const paths = await globby(['./**', './**/.*'], { gitignore: true }); + for (const filepath of paths) { + await git.add({ fs, dir, filepath }); + } - await remoteRepo.push(['refs/heads/master:refs/heads/master'], { - callbacks: { - credentials: credentialsProvider, - }, + await git.commit({ + fs, + dir, + message: 'Initial commit', + author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + }); + + await git.addRemote({ + fs, + dir, + remote: 'origin', + url: remote, + }); + + await git.push({ + fs, + dir, + http, + remote: 'origin', + onAuth: () => auth, }); } - -export async function pushToRemoteUserPass( - directory: string, - remote: string, - username: string, - password: string, -): Promise { - return pushToRemoteCred(directory, remote, () => - Cred.userpassPlaintextNew(username, password), - ); -} From d1f588a38b956128339b8833fa5b05dc2d9c17e1 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 1 Dec 2020 21:36:35 +0100 Subject: [PATCH 05/80] chore: pushing works with github! --- .../src/scaffolder/stages/publish/github.ts | 1 + .../src/scaffolder/stages/publish/helpers.ts | 21 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index 0306bb72e9..1b7852adcc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -54,6 +54,7 @@ export class GithubPublisher implements PublisherBase { await pushToRemoteCred(directory, remoteUrl, { username: this.token, password: 'x-auth-basic', + token: this.token, }); return { remoteUrl }; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index 61e76a31be..8e76649989 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -19,17 +19,28 @@ import globby from 'globby'; import fs from 'fs'; import http from 'isomorphic-git/http/node'; +/* +username password +GitHub | token 'x-oauth-basic' +GitHub App | token 'x-access-token' +BitBucket | 'x-token-auth' token +GitLab | 'oauth2' token +From : https://isomorphic-git.org/docs/en/onAuth +*/ export async function pushToRemoteCred( dir: string, remote: string, - auth?: { username: string; password: string }, + auth?: { username: string; password: string; token: string }, ): Promise { await git.init({ fs, dir, }); - const paths = await globby(['./**', './**/.*'], { gitignore: true }); + const paths = await globby(['./**', './**/.*'], { + cwd: dir, + gitignore: true, + }); for (const filepath of paths) { await git.add({ fs, dir, filepath }); } @@ -49,11 +60,15 @@ export async function pushToRemoteCred( url: remote, }); + console.warn({ username: auth.token, password: 'x-oauth-basic' }); await git.push({ fs, dir, http, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, remote: 'origin', - onAuth: () => auth, + onAuth: () => ({ username: auth.token, password: 'x-oauth-basic' }), }); } From f9f4846a58876d9b2f9bdc99497713309d140296 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 4 Dec 2020 18:10:39 +0100 Subject: [PATCH 06/80] chore: add back nodegit for testing --- plugins/scaffolder-backend/package.json | 2 ++ yarn.lock | 23 ++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 09c4e0cd87..ce740f0ec2 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -43,6 +43,7 @@ "isomorphic-git": "^1.8.0", "jsonschema": "^1.2.6", "morgan": "^1.10.0", + "nodegit": "^0.27.0", "uuid": "^8.2.0", "winston": "^3.2.1", "yaml": "^1.10.0" @@ -52,6 +53,7 @@ "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", + "@types/nodegit": "^0.26.12", "@types/supertest": "^2.0.8", "supertest": "^4.0.2", "yaml": "^1.10.0" diff --git a/yarn.lock b/yarn.lock index 3450a410c2..26bf43335c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1290,40 +1290,34 @@ to-fast-properties "^2.0.0" "@backstage/core@^0.2.0": - version "0.3.0" + version "0.2.0" + resolved "https://registry.npmjs.org/@backstage/core/-/core-0.2.0.tgz#543246b2d87563c9aa4d9fb96e40fdfc7e827520" + integrity sha512-75m2u3FoUngBOvt9l65xZcYTzzB+49OXpY1A9VNFUR1+jMs3cL/0HDfByQV2H0xXaHzMngQ8C5u/sWhkQsij1w== dependencies: "@backstage/config" "^0.1.1" - "@backstage/core-api" "^0.2.1" - "@backstage/theme" "^0.2.1" + "@backstage/core-api" "^0.2.0" + "@backstage/theme" "^0.2.0" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" - "@types/dagre" "^0.7.44" "@types/react" "^16.9" "@types/react-sparklines" "^1.7.0" classnames "^2.2.6" clsx "^1.1.0" - d3-selection "^2.0.0" - d3-shape "^2.0.0" - d3-zoom "^2.0.0" - dagre "^0.8.5" immer "^7.0.9" lodash "^4.17.15" material-table "^1.69.1" prop-types "^15.7.2" - qs "^6.9.4" rc-progress "^3.0.0" react "^16.12.0" react-dom "^16.12.0" react-helmet "6.1.0" react-hook-form "^6.6.0" - react-markdown "^5.0.2" react-router "6.0.0-beta.0" react-router-dom "6.0.0-beta.0" react-sparklines "^1.7.0" react-syntax-highlighter "^13.5.1" react-use "^15.3.3" - remark-gfm "^1.0.0" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -5550,6 +5544,13 @@ resolved "https://registry.npmjs.org/@types/node/-/node-13.13.15.tgz#fe1cc3aa465a3ea6858b793fd380b66c39919766" integrity sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw== +"@types/nodegit@^0.26.12": + version "0.26.12" + resolved "https://registry.npmjs.org/@types/nodegit/-/nodegit-0.26.12.tgz#93afb4cb85d3a48d392c3232699c9c07d8251a36" + integrity sha512-4YpeTImFZNJ1cve4lEueHFVS8rAs8XpZqlmx+Bm9bMc+XMiCrcwaUf6peN7pod7Rl3esVlGP1zdBB7Z12eMVAA== + dependencies: + "@types/node" "*" + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" From 15e5d6a76398eb414b8d41e533eb1aa1f392c710 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 7 Dec 2020 13:26:02 +0100 Subject: [PATCH 07/80] feat: use better logging for the publish step and the new helper with isomorphic-git --- .../src/scaffolder/stages/prepare/github.ts | 4 ++-- .../src/scaffolder/stages/publish/github.ts | 6 +++--- .../src/scaffolder/stages/publish/helpers.ts | 19 +++++++++++++++---- .../src/scaffolder/stages/publish/types.ts | 2 ++ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index f202c609cc..8e5581d63d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -69,9 +69,9 @@ export class GithubPreparer implements PreparerBase { depth: 1, onProgress: event => { const total = event.total - ? `${event.loaded / event.total}%` + ? `${Math.round((event.loaded / event.total) * 100)}%` : event.loaded; - opts.logger.info({ status: event.phase, total }); + opts.logger.info(`status={${event.phase},total={${total}}}`); }, headers: { 'user-agent': 'git/@isomorphic-git', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index 612e676207..e262c59274 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -46,13 +46,13 @@ export class GithubPublisher implements PublisherBase { async publish({ values, directory, + logger, }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - await pushToRemoteCred(directory, remoteUrl, { + await pushToRemoteCred(directory, remoteUrl, logger, { username: this.token, - password: 'x-auth-basic', - token: this.token, + password: 'x-oauth-basic', }); const catalogInfoUrl = remoteUrl.replace( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index 8e76649989..39b1513d2e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -18,7 +18,7 @@ import git from 'isomorphic-git'; import globby from 'globby'; import fs from 'fs'; import http from 'isomorphic-git/http/node'; - +import { Logger } from 'winston'; /* username password GitHub | token 'x-oauth-basic' @@ -30,8 +30,10 @@ From : https://isomorphic-git.org/docs/en/onAuth export async function pushToRemoteCred( dir: string, remote: string, - auth?: { username: string; password: string; token: string }, + logger: Logger, + auth: { username: string; password: string }, ): Promise { + logger.info('Initializing Git Repo', dir); await git.init({ fs, dir, @@ -41,10 +43,13 @@ export async function pushToRemoteCred( cwd: dir, gitignore: true, }); + + logger.info('Adding files to repository', dir); for (const filepath of paths) { await git.add({ fs, dir, filepath }); } + logger.info('Creating commit', dir); await git.commit({ fs, dir, @@ -60,7 +65,7 @@ export async function pushToRemoteCred( url: remote, }); - console.warn({ username: auth.token, password: 'x-oauth-basic' }); + logger.info('Pushing code to remote', remote); await git.push({ fs, dir, @@ -68,7 +73,13 @@ export async function pushToRemoteCred( headers: { 'user-agent': 'git/@isomorphic-git', }, + onProgress: event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + logger.info(`status={${event.phase},total={${total}}}`); + }, remote: 'origin', - onAuth: () => ({ username: auth.token, password: 'x-oauth-basic' }), + onAuth: () => auth, }); } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts index f3bc59e19d..bc6b63cc57 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts @@ -17,6 +17,7 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { RequiredTemplateValues } from '../templater'; import { JsonValue } from '@backstage/config'; import { RemoteProtocol } from '../types'; +import { Logger } from 'winston'; /** * Publisher is in charge of taking a folder created by @@ -34,6 +35,7 @@ export type PublisherBase = { export type PublisherOptions = { values: RequiredTemplateValues & Record; + logger: Logger; directory: string; }; From e2beaf5940a2a453844d70817d7eecfff53e0bdf Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 17 Dec 2020 10:18:52 +0100 Subject: [PATCH 08/80] chore: create scm from auth --- packages/backend-common/src/scm/git.ts | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 5bd721acd5..acfe53c1f8 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -15,3 +15,47 @@ */ import git from 'isomorphic-git'; import http from 'isomorphic-git/http/node'; +import fs from 'fs-extra'; + +class SCM { + constructor( + private readonly config: { username: string; password: string }, + private readonly logger: Logger, + ) {} + + async clone({ url, dir }) { + return git.clone({ + fs, + http, + url, + dir, + singleBranch: true, + depth: 1, + onProgress: event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + this.logger.info(`status={${event.phase},total={${total}}}`); + }, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onAuth: () => ({ + username: this.config.username, + password: this.config.password, + }), + }); + } +} + +export const fromAuth = ({ + username, + password, + logger, +}: { + username: string; + password: string; + logger: Logger; +}) => { + return new SCM({ username, password }); +}; From 359f9d2d8cbe82e9c03230cc3915c35e2e248703 Mon Sep 17 00:00:00 2001 From: keshan Date: Mon, 21 Dec 2020 12:44:02 +0530 Subject: [PATCH 09/80] Introduced config schema for techdocs plugins --- .changeset/modern-timers-obey.md | 6 ++ plugins/techdocs-backend/config.d.ts | 46 ++++++++++++++ plugins/techdocs-backend/package.json | 6 +- plugins/techdocs/config.d.ts | 91 +++++++++++++++++++++++++++ plugins/techdocs/package.json | 83 +----------------------- 5 files changed, 150 insertions(+), 82 deletions(-) create mode 100644 .changeset/modern-timers-obey.md create mode 100644 plugins/techdocs-backend/config.d.ts create mode 100644 plugins/techdocs/config.d.ts diff --git a/.changeset/modern-timers-obey.md b/.changeset/modern-timers-obey.md new file mode 100644 index 0000000000..7268d4961d --- /dev/null +++ b/.changeset/modern-timers-obey.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Added configuration schema for the commonly used properties of techdocs and techdocs-backend plugins diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts new file mode 100644 index 0000000000..f3237c669a --- /dev/null +++ b/plugins/techdocs-backend/config.d.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + /** Configuration options for the techdocs-backend plugin */ + techdocs: { + /** + * attr: 'storageUrl' - accepts a string value + * e.g. storageUrl: http://localhost:7000/api/techdocs/static/docs + */ + storageUrl: string; + /** + * documentation building process depends on the builder attr + * attr: 'builder' - accepts a string value + * e.g. builder: 'local' + * alternative: 'external' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + builder: string; + /** + * techdocs publisher information + */ + publisher: { + /** + * attr: 'type' - accepts a string value + * e.g. type: 'local' + * aleternatives: 'googleGcs' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + type: string; + }; + }; +} diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 5552d87f3f..372c8aaa6e 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -48,6 +48,8 @@ "supertest": "^4.0.2" }, "files": [ - "dist" - ] + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" } diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts new file mode 100644 index 0000000000..a60fbed1b4 --- /dev/null +++ b/plugins/techdocs/config.d.ts @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + /** Configuration options for the techdocs plugin */ + techdocs: { + /** + * attr: 'requestUrl' - accepts a string value + * e.g. requestUrl: http://localhost:7000/api/techdocs + * @visibility frontend + */ + requestUrl: string; + /** + * attr: 'storageUrl' - accepts a string value + * e.g. storageUrl: http://localhost:7000/api/techdocs/static/docs + */ + storageUrl: string; + /** + * documentation building process depends on the builder attr + * attr: 'builder' - accepts a string value + * e.g. builder: 'local' + * alternative: 'external' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + * @visibility frontend + */ + builder: string; + + /** + * techdocs publisher information + */ + generators?: { + /** + * attr: 'techdocs' - accepts a string value + * e.g. type: 'docker' + * aleternatives: 'local' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + techdocs: string; + }; + + /** + * techdocs publisher information + */ + publisher?: { + /** + * attr: 'type' - accepts a string value + * e.g. type: 'local' + * aleternatives: 'googleGcs' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + type: string; + + /** + * googleGcs required when 'type' is set to googleGcs, skip otherwise + */ + googleGcs?: { + /** + * API key used to write to a storage bucket. + * attr: 'credentials' - accepts a string value + * @visibility secret + */ + credentials: string; + /** + * GCP Project ID where the Cloud Storage Bucket is hosted. + * attr: 'projectId' - accepts a string value + * @visibility secret + */ + projectId: string; + /** + * Cloud Storage Bucket Name + * attr: 'bucketName' - accepts a string value + * @visibility secret + */ + bucketName: string; + }; + }; + }; +} diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 361825e71a..2baebdcad0 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -63,85 +63,8 @@ "msw": "^0.21.2" }, "files": [ - "dist" + "dist", + "config.d.ts" ], - "configSchema": { - "$schema": "https://backstage.io/schema/config-v1", - "title": "@backstage/techdocs", - "type": "object", - "properties": { - "techdocs": { - "type": "object", - "properties": { - "requestUrl": { - "type": "string", - "visibility": "frontend" - }, - "storageUrl": { - "type": "string", - "visibility": "backend" - }, - "generators": { - "type": "object", - "properties": { - "techdocs": { - "type": "string", - "visibility": "backend" - } - } - }, - "builder": { - "type": "string", - "visibility": "frontend" - }, - "publisher": { - "oneOf": [ - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "local", - "visibility": "backend" - } - } - }, - { - "type": "object", - "properties": { - "type": { - "type": "string", - "const": "googleGcs", - "visibility": "backend" - }, - "googleGcs": { - "type": "object", - "properties": { - "credentials": { - "type": "string", - "visibility": "secret" - }, - "projectId": { - "type": "string", - "visibility": "secret" - }, - "bucketName": { - "type": "string", - "visibility": "secret" - } - } - } - } - } - ] - } - }, - "required": [ - "requestUrl", - "storageUrl", - "builder" - ] - } - } - } + "configSchema": "config.d.ts" } From e53d4a2ca823efd3eccbd91e0c962e5ee7ec94cc Mon Sep 17 00:00:00 2001 From: keshan Date: Mon, 21 Dec 2020 16:25:49 +0530 Subject: [PATCH 10/80] updated based on the feedbacks provided --- plugins/techdocs-backend/config.d.ts | 9 ++-- plugins/techdocs/config.d.ts | 76 ++++++++++++++++------------ 2 files changed, 49 insertions(+), 36 deletions(-) diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index f3237c669a..bb76b21eae 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/** + * techdocs schema below is an abstract of what's used within techdocs-backend and for its visisbility + * to view the complete techdoc schema please refer: plugins/techdocs/config.d.ts + * */ export interface Config { /** Configuration options for the techdocs-backend plugin */ techdocs: { @@ -29,7 +32,7 @@ export interface Config { * alternative: 'external' etc. * @see http://backstage.io/docs/features/techdocs/configuration */ - builder: string; + builder: 'local' | 'external'; /** * techdocs publisher information */ @@ -40,7 +43,7 @@ export interface Config { * aleternatives: 'googleGcs' etc. * @see http://backstage.io/docs/features/techdocs/configuration */ - type: string; + type: 'local' | 'googleGcs' | 'awsS3'; }; }; } diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index a60fbed1b4..10adcb9fbd 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -36,7 +36,7 @@ export interface Config { * @see http://backstage.io/docs/features/techdocs/configuration * @visibility frontend */ - builder: string; + builder: 'local' | 'external'; /** * techdocs publisher information @@ -54,38 +54,48 @@ export interface Config { /** * techdocs publisher information */ - publisher?: { - /** - * attr: 'type' - accepts a string value - * e.g. type: 'local' - * aleternatives: 'googleGcs' etc. - * @see http://backstage.io/docs/features/techdocs/configuration - */ - type: string; + publisher?: + | { + /** + * attr: 'type' - accepts a string value + * e.g. type: 'local' + * aleternatives: 'googleGcs' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + type: 'local' | 'awsS3'; + } + | { + /** + * attr: 'type' - accepts a string value + * e.g. type: 'googleGcs' + * aleternatives: 'googleGcs' etc. + * @see http://backstage.io/docs/features/techdocs/configuration + */ + type: 'googleGcs'; - /** - * googleGcs required when 'type' is set to googleGcs, skip otherwise - */ - googleGcs?: { - /** - * API key used to write to a storage bucket. - * attr: 'credentials' - accepts a string value - * @visibility secret - */ - credentials: string; - /** - * GCP Project ID where the Cloud Storage Bucket is hosted. - * attr: 'projectId' - accepts a string value - * @visibility secret - */ - projectId: string; - /** - * Cloud Storage Bucket Name - * attr: 'bucketName' - accepts a string value - * @visibility secret - */ - bucketName: string; - }; - }; + /** + * googleGcs required when 'type' is set to googleGcs + */ + googleGcs?: { + /** + * API key used to write to a storage bucket. + * attr: 'credentials' - accepts a string value + * @visibility secret + */ + credentials: string; + /** + * GCP Project ID where the Cloud Storage Bucket is hosted. + * attr: 'projectId' - accepts a string value + * @visibility secret + */ + projectId: string; + /** + * Cloud Storage Bucket Name + * attr: 'bucketName' - accepts a string value + * @visibility secret + */ + bucketName: string; + }; + }; }; } From 851dde45f7c95520822423df8fa425e67f07f2cb Mon Sep 17 00:00:00 2001 From: keshan Date: Mon, 21 Dec 2020 16:31:01 +0530 Subject: [PATCH 11/80] updated the missed attr change --- plugins/techdocs/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index 10adcb9fbd..543579e85f 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -48,7 +48,7 @@ export interface Config { * aleternatives: 'local' etc. * @see http://backstage.io/docs/features/techdocs/configuration */ - techdocs: string; + techdocs: 'local' | 'docker'; }; /** From 23cee0d8313d03576c14f5af59faeed8b292ef27 Mon Sep 17 00:00:00 2001 From: keshan Date: Mon, 21 Dec 2020 16:33:39 +0530 Subject: [PATCH 12/80] typo corrected --- plugins/techdocs-backend/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index bb76b21eae..b51d86138a 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ /** - * techdocs schema below is an abstract of what's used within techdocs-backend and for its visisbility + * techdocs schema below is an abstract of what's used within techdocs-backend and for its visibility * to view the complete techdoc schema please refer: plugins/techdocs/config.d.ts * */ export interface Config { From 70ceab3db447e0df58fd44d5daba2356ece14f77 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 21 Dec 2020 15:38:53 +0100 Subject: [PATCH 13/80] feat: adding in all the functions needed for isomorphic git feature --- packages/backend-common/package.json | 1 + packages/backend-common/src/scm/git.ts | 90 ++++++++++++++++++++++++-- yarn.lock | 8 ++- 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 13b827762c..db5750dd70 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -45,6 +45,7 @@ "fs-extra": "^9.0.1", "git-url-parse": "^11.4.0", "helmet": "^4.0.0", + "isomorphic-git": "^1.8.0", "knex": "^0.21.6", "lodash": "^4.17.15", "logform": "^2.1.1", diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index acfe53c1f8..eecfd36612 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -16,14 +16,19 @@ import git from 'isomorphic-git'; import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; +import { Logger } from 'winston'; class SCM { constructor( - private readonly config: { username: string; password: string }, - private readonly logger: Logger, + private readonly config: { + username: string; + password: string; + logger?: Logger; + }, ) {} - async clone({ url, dir }) { + async clone({ url, dir }: { url: string; dir: string }) { + this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`); return git.clone({ fs, http, @@ -35,7 +40,7 @@ class SCM { const total = event.total ? `${Math.round((event.loaded / event.total) * 100)}%` : event.loaded; - this.logger.info(`status={${event.phase},total={${total}}}`); + this.config.logger?.info(`status={${event.phase},total={${total}}}`); }, headers: { 'user-agent': 'git/@isomorphic-git', @@ -46,6 +51,79 @@ class SCM { }), }); } + + async init({ dir }: { dir: string }) { + this.config.logger?.info(`Init git repository {dir=${dir}}`); + + return git.init({ + fs, + dir, + }); + } + + async add({ dir, filepath }: { dir: string; filepath: string }) { + this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`); + + return git.add({ fs, dir, filepath }); + } + + async commit({ + dir, + message, + author, + committer, + }: { + dir: string; + message: string; + author: { name: string; email: string }; + committer: { name: string; email: string }; + }) { + this.config.logger?.info( + `Committing file to repo {dir=${dir},message=${message}}`, + ); + + return git.commit({ fs, dir, message, author, committer }); + } + + async addRemote({ + dir, + url, + remoteName, + }: { + dir: string; + remoteName: string; + url: string; + }) { + this.config.logger?.info( + `Creating new remote {dir=${dir},remoteName=${remoteName},url=${url}}`, + ); + return git.addRemote({ fs, dir, remote: remoteName, url }); + } + + async push({ dir, remoteName }: { dir: string; remoteName: string }) { + this.config.logger?.info( + `Pushing directory to remote {dir=${dir},remoteName=${remoteName}}`, + ); + git.push({ + fs, + dir, + http, + onProgress: event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + this.config.logger?.info(`status={${event.phase},total={${total}}}`); + }, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + remote: remoteName, + onAuth: () => ({ + username: this.config.username, + password: this.config.password, + }), + }); + } } export const fromAuth = ({ @@ -55,7 +133,7 @@ export const fromAuth = ({ }: { username: string; password: string; - logger: Logger; + logger?: Logger; }) => { - return new SCM({ username, password }); + return new SCM({ username, password, logger }); }; diff --git a/yarn.lock b/yarn.lock index f16e1326ab..4cb027e631 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1630,7 +1630,9 @@ to-fast-properties "^2.0.0" "@backstage/catalog-model@^0.2.0": - version "0.4.0" + version "0.2.0" + resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-0.2.0.tgz#e3fe2a4ddeb6a9b6ec480c80cb2b9c39cb245576" + integrity sha512-Y1ocdRpBlxK/VrJQjHlQd0bgADECd1B2NRjwd8ss46ibT5hwLvMOfD80+Fa7oPLu0ktJrH4lq0pNIIJIml48zA== dependencies: "@backstage/config" "^0.1.1" "@types/json-schema" "^7.0.5" @@ -1641,7 +1643,9 @@ yup "^0.29.3" "@backstage/catalog-model@^0.3.0": - version "0.4.0" + version "0.3.1" + resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-0.3.1.tgz#45d08e2f333c9c566b2bf2629fd707fe989bb404" + integrity sha512-9XhV7c4rmVW+Yzj2PiwTQ7DsegWGB3C4ELsDRExuEVZONdqNcC02cyJtrt3fT5F31ZS3tHkB9bMUymFOBLqUSA== dependencies: "@backstage/config" "^0.1.1" "@types/json-schema" "^7.0.5" From d0a972eb63bb727f321504e485b5d8730740453d Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 21 Dec 2020 16:05:10 +0100 Subject: [PATCH 14/80] chore: reworking how we deal with exporting things from the main package --- packages/backend-common/src/index.ts | 1 + packages/backend-common/src/scm/git.ts | 23 +++-- packages/backend-common/src/scm/index.ts | 16 ++++ .../src/scaffolder/stages/prepare/github.ts | 40 +++------ .../src/scaffolder/stages/publish/github.ts | 17 +++- .../src/scaffolder/stages/publish/helpers.ts | 85 ------------------- 6 files changed, 57 insertions(+), 125 deletions(-) create mode 100644 packages/backend-common/src/scm/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts diff --git a/packages/backend-common/src/index.ts b/packages/backend-common/src/index.ts index e968edef69..3f04f32b34 100644 --- a/packages/backend-common/src/index.ts +++ b/packages/backend-common/src/index.ts @@ -24,3 +24,4 @@ export * from './reading'; export * from './service'; export * from './paths'; export * from './hot'; +export * from './scm'; diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index eecfd36612..25115bab26 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -18,11 +18,19 @@ import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; import { Logger } from 'winston'; +/* +provider username password +GitHub token 'x-oauth-basic' +GitHub App token 'x-access-token' +BitBucket 'x-token-auth' token +GitLab 'oauth2' token +From : https://isomorphic-git.org/docs/en/onAuth +*/ class SCM { constructor( private readonly config: { - username: string; - password: string; + username?: string; + password?: string; logger?: Logger; }, ) {} @@ -126,14 +134,15 @@ class SCM { } } +// TODO(blam): This could potentially become something like for URL +// and use the integrations config for URLReading instead. +// But for now, I don't want to do all that in this PR. export const fromAuth = ({ username, password, logger, }: { - username: string; - password: string; + username?: string; + password?: string; logger?: Logger; -}) => { - return new SCM({ username, password, logger }); -}; +}) => new SCM({ username, password, logger }); diff --git a/packages/backend-common/src/scm/index.ts b/packages/backend-common/src/scm/index.ts new file mode 100644 index 0000000000..76af535fd0 --- /dev/null +++ b/packages/backend-common/src/scm/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * as Git from './git'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 8e5581d63d..761259c0c5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -18,11 +18,9 @@ import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; -import { InputError } from '@backstage/backend-common'; +import { InputError, Git } from '@backstage/backend-common'; import { PreparerBase, PreparerOptions } from './types'; import GitUriParser from 'git-url-parse'; -import git from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; export class GithubPreparer implements PreparerBase { token?: string; @@ -37,7 +35,6 @@ export class GithubPreparer implements PreparerBase { ): Promise { const { protocol, location } = parseLocationAnnotation(template); const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); - const { token } = this; if (!['github', 'url'].includes(protocol)) { throw new InputError( @@ -58,33 +55,16 @@ export class GithubPreparer implements PreparerBase { ); const checkoutLocation = path.resolve(tempDir, templateDirectory); + const git = Git.fromAuth({ + username: this.token, + password: 'x-oauth-basic', + logger: opts.logger, + }); - try { - await git.clone({ - fs, - http, - url: repositoryCheckoutUrl, - dir: checkoutLocation, - singleBranch: true, - depth: 1, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - opts.logger.info(`status={${event.phase},total={${total}}}`); - }, - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onAuth: () => ({ username: token, password: 'x-oauth-basic' }), - }); - } catch (ex) { - opts.logger.error( - `Failed checking out repository: ${repositoryCheckoutUrl}`, - ); - opts.logger.error(ex.message); - throw ex; - } + await git.clone({ + url: repositoryCheckoutUrl, + dir: checkoutLocation, + }); return checkoutLocation; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index e262c59274..6e99590e15 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -16,7 +16,7 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { Octokit } from '@octokit/rest'; -import { pushToRemoteCred } from './helpers'; +import { Git } from '@backstage/backend-common'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; @@ -49,10 +49,21 @@ export class GithubPublisher implements PublisherBase { logger, }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - - await pushToRemoteCred(directory, remoteUrl, logger, { + const git = Git.fromAuth({ username: this.token, password: 'x-oauth-basic', + logger, + }); + + await git.addRemote({ + dir: directory, + url: remoteUrl, + remoteName: 'origin', + }); + + await git.push({ + dir: directory, + remoteName: 'origin', }); const catalogInfoUrl = remoteUrl.replace( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts deleted file mode 100644 index 1dcf3fdee1..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import git from 'isomorphic-git'; -import globby from 'globby'; -import fs from 'fs'; -import http from 'isomorphic-git/http/node'; -import { Logger } from 'winston'; -/* -username password -GitHub | token 'x-oauth-basic' -GitHub App | token 'x-access-token' -BitBucket | 'x-token-auth' token -GitLab | 'oauth2' token -From : https://isomorphic-git.org/docs/en/onAuth -*/ -export async function push( - dir: string, - remote: string, - logger: Logger, - auth: { username: string; password: string }, -): Promise { - logger.info('Initializing Git Repo', dir); - await git.init({ - fs, - dir, - }); - - const paths = await globby(['./**', './**/.*'], { - cwd: dir, - gitignore: true, - }); - - logger.info('Adding files to repository', dir); - for (const filepath of paths) { - await git.add({ fs, dir, filepath }); - } - - logger.info('Creating commit', dir); - await git.commit({ - fs, - dir, - message: 'Initial commit', - author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, - committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, - }); - - await git.addRemote({ - fs, - dir, - remote: 'origin', - url: remote, - }); - - logger.info('Pushing code to remote', remote); - await git.push({ - fs, - dir, - http, - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - logger.info(`status={${event.phase},total={${total}}}`); - }, - remote: 'origin', - onAuth: () => auth, - }); -} From 54a19d444497a2c53bdeefe1dba64ccaf2ac66cd Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 21 Dec 2020 16:05:24 +0100 Subject: [PATCH 15/80] feat: move all publishers over to the backend common way to interact with git scm --- packages/backend-common/src/scm/git.ts | 2 + packages/backend-common/src/scm/index.ts | 4 +- .../src/scaffolder/stages/publish/azure.ts | 21 ++++- .../src/scaffolder/stages/publish/gitlab.ts | 21 ++++- .../src/scaffolder/stages/publish/helpers.ts | 85 +++++++++++++++++++ 5 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 25115bab26..7e31b4e8e1 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -25,6 +25,8 @@ GitHub App token 'x-access-token' BitBucket 'x-token-auth' token GitLab 'oauth2' token From : https://isomorphic-git.org/docs/en/onAuth + +Azure 'notempty' token */ class SCM { constructor( diff --git a/packages/backend-common/src/scm/index.ts b/packages/backend-common/src/scm/index.ts index 76af535fd0..83a59310cd 100644 --- a/packages/backend-common/src/scm/index.ts +++ b/packages/backend-common/src/scm/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * as Git from './git'; +import * as Git from './git'; + +export { Git }; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts index 1e962bf223..16956cc8fb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts @@ -16,8 +16,8 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { GitApi } from 'azure-devops-node-api/GitApi'; +import { Git } from '@backstage/backend-common'; import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { pushToRemoteUserPass } from './helpers'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; @@ -33,11 +33,28 @@ export class AzurePublisher implements PublisherBase { async publish({ values, directory, + logger, }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - await pushToRemoteUserPass(directory, remoteUrl, 'notempty', this.token); const catalogInfoUrl = `${remoteUrl}?path=%2Fcatalog-info.yaml`; + const git = Git.fromAuth({ + username: 'notempty', + password: this.token, + logger, + }); + + await git.addRemote({ + dir: directory, + url: remoteUrl, + remoteName: 'origin', + }); + + await git.push({ + dir: directory, + remoteName: 'origin', + }); + return { remoteUrl, catalogInfoUrl }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts index 4fae8e8a5c..32b203bf51 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts @@ -16,7 +16,7 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { Gitlab } from '@gitbeaker/core'; -import { pushToRemoteUserPass } from './helpers'; +import { Git } from '@backstage/backend-common'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; @@ -32,9 +32,26 @@ export class GitlabPublisher implements PublisherBase { async publish({ values, directory, + logger, }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - await pushToRemoteUserPass(directory, remoteUrl, 'oauth2', this.token); + + const git = Git.fromAuth({ + password: this.token, + username: 'oauth2', + logger, + }); + + await git.addRemote({ + dir: directory, + url: remoteUrl, + remoteName: 'origin', + }); + + await git.push({ + dir: directory, + remoteName: 'origin', + }); return { remoteUrl }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts new file mode 100644 index 0000000000..1dcf3fdee1 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import git from 'isomorphic-git'; +import globby from 'globby'; +import fs from 'fs'; +import http from 'isomorphic-git/http/node'; +import { Logger } from 'winston'; +/* +username password +GitHub | token 'x-oauth-basic' +GitHub App | token 'x-access-token' +BitBucket | 'x-token-auth' token +GitLab | 'oauth2' token +From : https://isomorphic-git.org/docs/en/onAuth +*/ +export async function push( + dir: string, + remote: string, + logger: Logger, + auth: { username: string; password: string }, +): Promise { + logger.info('Initializing Git Repo', dir); + await git.init({ + fs, + dir, + }); + + const paths = await globby(['./**', './**/.*'], { + cwd: dir, + gitignore: true, + }); + + logger.info('Adding files to repository', dir); + for (const filepath of paths) { + await git.add({ fs, dir, filepath }); + } + + logger.info('Creating commit', dir); + await git.commit({ + fs, + dir, + message: 'Initial commit', + author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + }); + + await git.addRemote({ + fs, + dir, + remote: 'origin', + url: remote, + }); + + logger.info('Pushing code to remote', remote); + await git.push({ + fs, + dir, + http, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onProgress: event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + logger.info(`status={${event.phase},total={${total}}}`); + }, + remote: 'origin', + onAuth: () => auth, + }); +} From ab82709595acdeae1bfcc2ecacd7a7d203e086fb Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 21 Dec 2020 16:31:50 +0100 Subject: [PATCH 16/80] bug: need to actually use the tmpDirectory for checkout not the end location --- .../scaffolder-backend/src/scaffolder/stages/prepare/github.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 761259c0c5..87612bb0fb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -55,6 +55,7 @@ export class GithubPreparer implements PreparerBase { ); const checkoutLocation = path.resolve(tempDir, templateDirectory); + const git = Git.fromAuth({ username: this.token, password: 'x-oauth-basic', @@ -63,7 +64,7 @@ export class GithubPreparer implements PreparerBase { await git.clone({ url: repositoryCheckoutUrl, - dir: checkoutLocation, + dir: tempDir, }); return checkoutLocation; From 3727e3b36739fc672f652bebd7bdc25b7798c620 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 22 Dec 2020 13:00:36 +0100 Subject: [PATCH 17/80] feat: update all preparers to use isomorphic git --- packages/backend-common/src/scm/git.ts | 2 +- plugins/scaffolder-backend/package.json | 1 - .../src/scaffolder/stages/prepare/azure.ts | 29 ++++++++++--------- .../src/scaffolder/stages/prepare/github.ts | 13 +++++---- .../src/scaffolder/stages/prepare/gitlab.ts | 25 ++++++++-------- .../src/scaffolder/stages/publish/github.ts | 22 ++++++++++++++ 6 files changed, 59 insertions(+), 33 deletions(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 7e31b4e8e1..3b31d7c60b 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -114,7 +114,7 @@ class SCM { this.config.logger?.info( `Pushing directory to remote {dir=${dir},remoteName=${remoteName}}`, ); - git.push({ + return git.push({ fs, dir, http, diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 992a9efc3b..a51e9edfcb 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -53,7 +53,6 @@ "isomorphic-git": "^1.8.0", "jsonschema": "^1.2.6", "morgan": "^1.10.0", - "nodegit": "^0.27.0", "uuid": "^8.2.0", "winston": "^3.2.1", "yaml": "^1.10.0" diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index 333bf9116c..ce1c18e048 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -18,10 +18,9 @@ import fs from 'fs-extra'; import path from 'path'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { parseLocationAnnotation } from '../helpers'; -import { InputError } from '@backstage/backend-common'; +import { InputError, Git } from '@backstage/backend-common'; import { PreparerBase, PreparerOptions } from './types'; import GitUriParser from 'git-url-parse'; -import { Clone, Cred } from 'nodegit'; import { Config } from '@backstage/config'; export class AzurePreparer implements PreparerBase { @@ -38,6 +37,7 @@ export class AzurePreparer implements PreparerBase { ): Promise { const { protocol, location } = parseLocationAnnotation(template); const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); + const { logger } = opts; if (!['azure/api', 'url'].includes(protocol)) { throw new InputError( @@ -57,19 +57,20 @@ export class AzurePreparer implements PreparerBase { template.spec.path ?? '.', ); - const options = this.privateToken - ? { - fetchOpts: { - callbacks: { - credentials: () => - // Username can anything but the empty string according to: https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat - Cred.userpassPlaintextNew('notempty', this.privateToken), - }, - }, - } - : {}; + // Username can anything but the empty string according to: + // https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat + const git = this.privateToken + ? Git.fromAuth({ + password: this.privateToken, + username: 'notempty', + logger, + }) + : Git.fromAuth({ logger }); - await Clone.clone(repositoryCheckoutUrl, tempDir, options); + await git.clone({ + url: repositoryCheckoutUrl, + dir: tempDir, + }); return path.resolve(tempDir, templateDirectory); } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts index 87612bb0fb..e7fa0c9b72 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts @@ -35,6 +35,7 @@ export class GithubPreparer implements PreparerBase { ): Promise { const { protocol, location } = parseLocationAnnotation(template); const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); + const { logger } = opts; if (!['github', 'url'].includes(protocol)) { throw new InputError( @@ -56,11 +57,13 @@ export class GithubPreparer implements PreparerBase { const checkoutLocation = path.resolve(tempDir, templateDirectory); - const git = Git.fromAuth({ - username: this.token, - password: 'x-oauth-basic', - logger: opts.logger, - }); + const git = this.token + ? Git.fromAuth({ + username: this.token, + password: 'x-oauth-basic', + logger, + }) + : Git.fromAuth({ logger }); await git.clone({ url: repositoryCheckoutUrl, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts index c2c2dcd3fd..6e169baa98 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { InputError } from '@backstage/backend-common'; +import { InputError, Git } from '@backstage/backend-common'; import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { @@ -22,7 +22,6 @@ import { } from '@backstage/integration'; import fs from 'fs-extra'; import GitUriParser from 'git-url-parse'; -import { Clone, Cred } from 'nodegit'; import os from 'os'; import path from 'path'; import { parseLocationAnnotation } from '../helpers'; @@ -46,6 +45,7 @@ export class GitlabPreparer implements PreparerBase { opts: PreparerOptions, ): Promise { const { protocol, location } = parseLocationAnnotation(template); + const { logger } = opts; const workingDirectory = opts?.workingDirectory ?? os.tmpdir(); if (!['gitlab', 'gitlab/api', 'url'].includes(protocol)) { @@ -67,17 +67,18 @@ export class GitlabPreparer implements PreparerBase { ); const token = this.getToken(parsedGitLocation.resource); - const options = token - ? { - fetchOpts: { - callbacks: { - credentials: () => Cred.userpassPlaintextNew('oauth2', token), - }, - }, - } - : {}; + const git = token + ? Git.fromAuth({ + password: token, + username: 'oauth2', + logger, + }) + : Git.fromAuth({ logger }); - await Clone.clone(repositoryCheckoutUrl, tempDir, options); + await git.clone({ + url: repositoryCheckoutUrl, + dir: tempDir, + }); return path.resolve(tempDir, templateDirectory); } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index 6e99590e15..7abcee193c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -19,6 +19,7 @@ import { Octokit } from '@octokit/rest'; import { Git } from '@backstage/backend-common'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; +import globby from 'globby'; export type RepoVisibilityOptions = 'private' | 'internal' | 'public'; @@ -55,6 +56,27 @@ export class GithubPublisher implements PublisherBase { logger, }); + await git.init({ + dir: directory, + }); + + const paths = await globby(['./**', './**/.*'], { + cwd: directory, + gitignore: true, + dot: true, + }); + + for (const filepath of paths) { + await git.add({ dir: directory, filepath }); + } + + await git.commit({ + dir: directory, + message: 'Initial commit', + author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + }); + await git.addRemote({ dir: directory, url: remoteUrl, From 1e7f526bd3e0a231c56f43d0329e37c4283d89e3 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 22 Dec 2020 13:09:27 +0100 Subject: [PATCH 18/80] feat: update all publishers to use isomorphic-gint --- .../src/scaffolder/stages/publish/azure.ts | 23 +++---- .../src/scaffolder/stages/publish/github.ts | 46 +++---------- .../src/scaffolder/stages/publish/gitlab.ts | 23 +++---- .../src/scaffolder/stages/publish/helpers.ts | 64 +++++++------------ 4 files changed, 49 insertions(+), 107 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts index 16956cc8fb..ffe6845f01 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts @@ -16,10 +16,10 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { GitApi } from 'azure-devops-node-api/GitApi'; -import { Git } from '@backstage/backend-common'; import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; +import { initRepoAndPush } from './helpers'; export class AzurePublisher implements PublisherBase { private readonly client: GitApi; @@ -38,23 +38,16 @@ export class AzurePublisher implements PublisherBase { const remoteUrl = await this.createRemote(values); const catalogInfoUrl = `${remoteUrl}?path=%2Fcatalog-info.yaml`; - const git = Git.fromAuth({ - username: 'notempty', - password: this.token, + await initRepoAndPush({ + dir: directory, + remoteUrl, + auth: { + username: 'notempty', + password: this.token, + }, logger, }); - await git.addRemote({ - dir: directory, - url: remoteUrl, - remoteName: 'origin', - }); - - await git.push({ - dir: directory, - remoteName: 'origin', - }); - return { remoteUrl, catalogInfoUrl }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index 7abcee193c..39a588882f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -16,10 +16,9 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { Octokit } from '@octokit/rest'; -import { Git } from '@backstage/backend-common'; +import { initRepoAndPush } from './helpers'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; -import globby from 'globby'; export type RepoVisibilityOptions = 'private' | 'internal' | 'public'; @@ -50,44 +49,17 @@ export class GithubPublisher implements PublisherBase { logger, }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - const git = Git.fromAuth({ - username: this.token, - password: 'x-oauth-basic', + + await initRepoAndPush({ + dir: directory, + remoteUrl, + auth: { + username: this.token, + password: 'x-oauth-basic', + }, logger, }); - await git.init({ - dir: directory, - }); - - const paths = await globby(['./**', './**/.*'], { - cwd: directory, - gitignore: true, - dot: true, - }); - - for (const filepath of paths) { - await git.add({ dir: directory, filepath }); - } - - await git.commit({ - dir: directory, - message: 'Initial commit', - author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, - committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, - }); - - await git.addRemote({ - dir: directory, - url: remoteUrl, - remoteName: 'origin', - }); - - await git.push({ - dir: directory, - remoteName: 'origin', - }); - const catalogInfoUrl = remoteUrl.replace( /\.git$/, '/blob/master/catalog-info.yaml', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts index 32b203bf51..156a4a249c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts @@ -16,8 +16,8 @@ import { PublisherBase, PublisherOptions, PublisherResult } from './types'; import { Gitlab } from '@gitbeaker/core'; -import { Git } from '@backstage/backend-common'; import { JsonValue } from '@backstage/config'; +import { initRepoAndPush } from './helpers'; import { RequiredTemplateValues } from '../templater'; export class GitlabPublisher implements PublisherBase { @@ -36,23 +36,16 @@ export class GitlabPublisher implements PublisherBase { }: PublisherOptions): Promise { const remoteUrl = await this.createRemote(values); - const git = Git.fromAuth({ - password: this.token, - username: 'oauth2', + await initRepoAndPush({ + dir: directory, + remoteUrl, + auth: { + username: 'oauth2', + password: this.token, + }, logger, }); - await git.addRemote({ - dir: directory, - url: remoteUrl, - remoteName: 'origin', - }); - - await git.push({ - dir: directory, - remoteName: 'origin', - }); - return { remoteUrl }; } diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index 1dcf3fdee1..bf19c2f56d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -14,44 +14,42 @@ * limitations under the License. */ -import git from 'isomorphic-git'; import globby from 'globby'; -import fs from 'fs'; -import http from 'isomorphic-git/http/node'; import { Logger } from 'winston'; -/* -username password -GitHub | token 'x-oauth-basic' -GitHub App | token 'x-access-token' -BitBucket | 'x-token-auth' token -GitLab | 'oauth2' token -From : https://isomorphic-git.org/docs/en/onAuth -*/ -export async function push( - dir: string, - remote: string, - logger: Logger, - auth: { username: string; password: string }, -): Promise { - logger.info('Initializing Git Repo', dir); +import { Git } from '@backstage/backend-common'; + +export async function initRepoAndPush({ + dir, + remoteUrl, + auth, + logger, +}: { + dir: string; + remoteUrl: string; + auth: { username: string; password: string }; + logger: Logger; +}): Promise { + const git = Git.fromAuth({ + username: auth.username, + password: auth.password, + logger, + }); + await git.init({ - fs, dir, }); const paths = await globby(['./**', './**/.*'], { cwd: dir, gitignore: true, + dot: true, }); - logger.info('Adding files to repository', dir); for (const filepath of paths) { - await git.add({ fs, dir, filepath }); + await git.add({ dir, filepath }); } - logger.info('Creating commit', dir); await git.commit({ - fs, dir, message: 'Initial commit', author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, @@ -59,27 +57,13 @@ export async function push( }); await git.addRemote({ - fs, dir, - remote: 'origin', - url: remote, + url: remoteUrl, + remoteName: 'origin', }); - logger.info('Pushing code to remote', remote); await git.push({ - fs, dir, - http, - headers: { - 'user-agent': 'git/@isomorphic-git', - }, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - logger.info(`status={${event.phase},total={${total}}}`); - }, - remote: 'origin', - onAuth: () => auth, + remoteName: 'origin', }); } From 907fac9d9272444a40ff46a979de2e47b4088b71 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 22 Dec 2020 09:45:25 -0600 Subject: [PATCH 19/80] eliminate racey code --- packages/core-api/src/lib/loginPopup.test.ts | 80 -------------------- packages/core-api/src/lib/loginPopup.ts | 18 ----- 2 files changed, 98 deletions(-) diff --git a/packages/core-api/src/lib/loginPopup.test.ts b/packages/core-api/src/lib/loginPopup.test.ts index 98541c268e..f645b75af7 100644 --- a/packages/core-api/src/lib/loginPopup.test.ts +++ b/packages/core-api/src/lib/loginPopup.test.ts @@ -135,84 +135,4 @@ describe('showLoginPopup', () => { expect(addEventListenerSpy).toBeCalledTimes(1); expect(removeEventListenerSpy).toBeCalledTimes(1); }); - - it('should fail if popup is closed', async () => { - const openSpy = jest - .spyOn(window, 'open') - .mockReturnValue({ closed: false } as Window); - const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); - const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); - const popupMock = { closed: false }; - - openSpy.mockReturnValue(popupMock as Window); - - const payloadPromise = showLoginPopup({ - url: 'url', - name: 'name', - origin: 'origin', - }); - - expect(openSpy).toBeCalledTimes(1); - expect(addEventListenerSpy).toBeCalledTimes(1); - expect(removeEventListenerSpy).toBeCalledTimes(0); - - const listener = addEventListenerSpy.mock.calls[0][1] as EventListener; - listener({ - source: popupMock, - origin: 'origin', - data: { - type: 'config_info', - targetOrigin: 'http://localhost', - }, - } as MessageEvent); - - setTimeout(() => { - popupMock.closed = true; - }, 150); - await expect(payloadPromise).rejects.toThrow( - 'Login failed, popup was closed', - ); - - expect(openSpy).toBeCalledTimes(1); - expect(addEventListenerSpy).toBeCalledTimes(1); - expect(removeEventListenerSpy).toBeCalledTimes(1); - }); - - it('should indicate if origin does not match', async () => { - const openSpy = jest - .spyOn(window, 'open') - .mockReturnValue({ closed: false } as Window); - const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); - const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); - const popupMock = { closed: false }; - - openSpy.mockReturnValue(popupMock as Window); - - const payloadPromise = showLoginPopup({ - url: 'url', - name: 'name', - origin: 'origin', - }); - - const listener = addEventListenerSpy.mock.calls[0][1] as EventListener; - listener({ - source: popupMock, - origin: 'origin', - data: { - type: 'config_info', - targetOrigin: 'http://differenthost', - }, - } as MessageEvent); - - setTimeout(() => { - popupMock.closed = true; - }, 150); - await expect(payloadPromise).rejects.toThrow( - 'Login failed, Incorrect app origin, expected http://differenthost', - ); - - expect(openSpy).toBeCalledTimes(1); - expect(addEventListenerSpy).toBeCalledTimes(1); - expect(removeEventListenerSpy).toBeCalledTimes(1); - }); }); diff --git a/packages/core-api/src/lib/loginPopup.ts b/packages/core-api/src/lib/loginPopup.ts index 2e14447882..1741d845e8 100644 --- a/packages/core-api/src/lib/loginPopup.ts +++ b/packages/core-api/src/lib/loginPopup.ts @@ -79,8 +79,6 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { `menubar=no,location=no,resizable=no,scrollbars=no,status=no,width=${width},height=${height},top=${top},left=${left}`, ); - let targetOrigin = ''; - if (!popup || typeof popup.closed === 'undefined' || popup.closed) { reject(new Error('Failed to open auth popup.')); return; @@ -96,7 +94,6 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { const { data } = event; if (data.type === 'config_info') { - targetOrigin = data.targetOrigin; return; } @@ -117,23 +114,8 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { done(); }; - const intervalId = setInterval(() => { - if (popup.closed) { - const errMessage = `Login failed, ${ - targetOrigin !== window.location.origin - ? `Incorrect app origin, expected ${targetOrigin}` - : 'popup was closed' - }`; - const error = new Error(errMessage); - error.name = 'PopupClosedError'; - reject(error); - done(); - } - }, 100); - function done() { window.removeEventListener('message', messageListener); - clearInterval(intervalId); } window.addEventListener('message', messageListener); From 27f2af9354baf792291ab77714f2c25ea2e1cc62 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 22 Dec 2020 09:55:51 -0600 Subject: [PATCH 20/80] change log --- .changeset/purple-turtles-float.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/purple-turtles-float.md diff --git a/.changeset/purple-turtles-float.md b/.changeset/purple-turtles-float.md new file mode 100644 index 0000000000..2e5688bf11 --- /dev/null +++ b/.changeset/purple-turtles-float.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-api': patch +--- + +Remove race condition in loginPopup From 0c6fd807bf6278bc299582b0faa40a59c55d0e35 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 22 Dec 2020 23:29:50 +0530 Subject: [PATCH 21/80] fixed category lables --- microsite/data/plugins/aws-lambda.yaml | 2 +- microsite/data/plugins/firebase-functions.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/microsite/data/plugins/aws-lambda.yaml b/microsite/data/plugins/aws-lambda.yaml index f325c0df8b..cc3d59d188 100644 --- a/microsite/data/plugins/aws-lambda.yaml +++ b/microsite/data/plugins/aws-lambda.yaml @@ -2,7 +2,7 @@ title: AWS Lambda author: roadie.io authorUrl: https://roadie.io -category: Monitoring +category: Infrastructure description: View AWS Lambda functions for your components in Backstage. documentation: https://roadie.io/backstage/plugins/aws-lambda iconUrl: https://roadie.io/images/logos/lambda.png diff --git a/microsite/data/plugins/firebase-functions.yaml b/microsite/data/plugins/firebase-functions.yaml index 8c1ea0be0a..9a1777754a 100644 --- a/microsite/data/plugins/firebase-functions.yaml +++ b/microsite/data/plugins/firebase-functions.yaml @@ -2,7 +2,7 @@ title: Firebase Functions author: roadie.io authorUrl: https://roadie.io/ -category: Monitoring +category: Infrastructure description: View Firebase Functions details for your service in Backstage. documentation: https://roadie.io/backstage/plugins/firebase-functions iconUrl: https://roadie.io/images/logos/firebase.png From 0836691020370a127a2847cd38f16cc6356e8779 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 22 Dec 2020 15:44:42 -0600 Subject: [PATCH 22/80] Revert "eliminate racey code" This reverts commit 907fac9d9272444a40ff46a979de2e47b4088b71. --- packages/core-api/src/lib/loginPopup.test.ts | 80 ++++++++++++++++++++ packages/core-api/src/lib/loginPopup.ts | 18 +++++ 2 files changed, 98 insertions(+) diff --git a/packages/core-api/src/lib/loginPopup.test.ts b/packages/core-api/src/lib/loginPopup.test.ts index f645b75af7..98541c268e 100644 --- a/packages/core-api/src/lib/loginPopup.test.ts +++ b/packages/core-api/src/lib/loginPopup.test.ts @@ -135,4 +135,84 @@ describe('showLoginPopup', () => { expect(addEventListenerSpy).toBeCalledTimes(1); expect(removeEventListenerSpy).toBeCalledTimes(1); }); + + it('should fail if popup is closed', async () => { + const openSpy = jest + .spyOn(window, 'open') + .mockReturnValue({ closed: false } as Window); + const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); + const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); + const popupMock = { closed: false }; + + openSpy.mockReturnValue(popupMock as Window); + + const payloadPromise = showLoginPopup({ + url: 'url', + name: 'name', + origin: 'origin', + }); + + expect(openSpy).toBeCalledTimes(1); + expect(addEventListenerSpy).toBeCalledTimes(1); + expect(removeEventListenerSpy).toBeCalledTimes(0); + + const listener = addEventListenerSpy.mock.calls[0][1] as EventListener; + listener({ + source: popupMock, + origin: 'origin', + data: { + type: 'config_info', + targetOrigin: 'http://localhost', + }, + } as MessageEvent); + + setTimeout(() => { + popupMock.closed = true; + }, 150); + await expect(payloadPromise).rejects.toThrow( + 'Login failed, popup was closed', + ); + + expect(openSpy).toBeCalledTimes(1); + expect(addEventListenerSpy).toBeCalledTimes(1); + expect(removeEventListenerSpy).toBeCalledTimes(1); + }); + + it('should indicate if origin does not match', async () => { + const openSpy = jest + .spyOn(window, 'open') + .mockReturnValue({ closed: false } as Window); + const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); + const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); + const popupMock = { closed: false }; + + openSpy.mockReturnValue(popupMock as Window); + + const payloadPromise = showLoginPopup({ + url: 'url', + name: 'name', + origin: 'origin', + }); + + const listener = addEventListenerSpy.mock.calls[0][1] as EventListener; + listener({ + source: popupMock, + origin: 'origin', + data: { + type: 'config_info', + targetOrigin: 'http://differenthost', + }, + } as MessageEvent); + + setTimeout(() => { + popupMock.closed = true; + }, 150); + await expect(payloadPromise).rejects.toThrow( + 'Login failed, Incorrect app origin, expected http://differenthost', + ); + + expect(openSpy).toBeCalledTimes(1); + expect(addEventListenerSpy).toBeCalledTimes(1); + expect(removeEventListenerSpy).toBeCalledTimes(1); + }); }); diff --git a/packages/core-api/src/lib/loginPopup.ts b/packages/core-api/src/lib/loginPopup.ts index 1741d845e8..2e14447882 100644 --- a/packages/core-api/src/lib/loginPopup.ts +++ b/packages/core-api/src/lib/loginPopup.ts @@ -79,6 +79,8 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { `menubar=no,location=no,resizable=no,scrollbars=no,status=no,width=${width},height=${height},top=${top},left=${left}`, ); + let targetOrigin = ''; + if (!popup || typeof popup.closed === 'undefined' || popup.closed) { reject(new Error('Failed to open auth popup.')); return; @@ -94,6 +96,7 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { const { data } = event; if (data.type === 'config_info') { + targetOrigin = data.targetOrigin; return; } @@ -114,8 +117,23 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { done(); }; + const intervalId = setInterval(() => { + if (popup.closed) { + const errMessage = `Login failed, ${ + targetOrigin !== window.location.origin + ? `Incorrect app origin, expected ${targetOrigin}` + : 'popup was closed' + }`; + const error = new Error(errMessage); + error.name = 'PopupClosedError'; + reject(error); + done(); + } + }, 100); + function done() { window.removeEventListener('message', messageListener); + clearInterval(intervalId); } window.addEventListener('message', messageListener); From 29b4056f2c6fbc32029a567572669b9711806538 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Tue, 22 Dec 2020 16:03:21 -0600 Subject: [PATCH 23/80] delay window close by 200 ms --- .changeset/purple-turtles-float.md | 2 +- plugins/auth-backend/src/lib/flow/authFlowHelpers.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.changeset/purple-turtles-float.md b/.changeset/purple-turtles-float.md index 2e5688bf11..8736a7315f 100644 --- a/.changeset/purple-turtles-float.md +++ b/.changeset/purple-turtles-float.md @@ -2,4 +2,4 @@ '@backstage/core-api': patch --- -Remove race condition in loginPopup +Delay auth loginPopup close to avoid race condition with callers of authFlowHelpers. diff --git a/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts b/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts index 22ffc7af88..86a615e721 100644 --- a/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts +++ b/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts @@ -56,7 +56,9 @@ export const postMessageResponse = ( var originInfo = {'type': 'config_info', 'targetOrigin': origin}; (window.opener || window.parent).postMessage(originInfo, '*'); (window.opener || window.parent).postMessage(JSON.parse(authResponse), origin); - window.close(); + setTimeout(() => { + window.close(); + }, 100 * 2); // double the interval of the core-api lib/loginPopup.ts `; const hash = crypto.createHash('sha256').update(script).digest('base64'); From 9ca586e579feb2a450b48246801506f6db485c27 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Wed, 23 Dec 2020 00:12:20 +0100 Subject: [PATCH 24/80] techdocs: Replace nodegit with isomorphic-git TechDocs needs 4 functions from the git library 1. To clone 2. To get the commit timestamp for HEAD 3. To fetch 4. To merge two branches Created necessary commands in the new SCM client and reordered them alphabetically for convenience --- packages/backend-common/src/scm/git.ts | 122 +++++++++--- packages/techdocs-common/package.json | 2 - packages/techdocs-common/src/helpers.ts | 89 +++++---- .../src/scaffolder/stages/prepare/azure.ts | 2 +- yarn.lock | 182 +----------------- 5 files changed, 154 insertions(+), 243 deletions(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 3b31d7c60b..b744040cb2 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -37,6 +37,45 @@ class SCM { }, ) {} + async add({ dir, filepath }: { dir: string; filepath: string }) { + this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`); + + return git.add({ fs, dir, filepath }); + } + + async addRemote({ + dir, + url, + remoteName, + }: { + dir: string; + remoteName: string; + url: string; + }) { + this.config.logger?.info( + `Creating new remote {dir=${dir},remoteName=${remoteName},url=${url}}`, + ); + return git.addRemote({ fs, dir, remote: remoteName, url }); + } + + async commit({ + dir, + message, + author, + committer, + }: { + dir: string; + message: string; + author: { name: string; email: string }; + committer: { name: string; email: string }; + }) { + this.config.logger?.info( + `Committing file to repo {dir=${dir},message=${message}}`, + ); + + return git.commit({ fs, dir, message, author, committer }); + } + async clone({ url, dir }: { url: string; dir: string }) { this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`); return git.clone({ @@ -62,6 +101,39 @@ class SCM { }); } + // https://isomorphic-git.org/docs/en/currentBranch + async currentBranch({ dir, fullName }: { dir: string; fullName?: boolean }) { + const fullname = fullName ?? false; + return git.currentBranch({ fs, dir, fullname }); + } + + // https://isomorphic-git.org/docs/en/fetch + async fetch({ dir, remote }: { dir: string; remote?: string }) { + const remoteValue = remote ?? 'origin'; + this.config.logger?.info( + `Fetching remote=${remoteValue} for repository {dir=${dir}}`, + ); + return git.fetch({ + fs, + http, + dir, + remote: remoteValue, + onProgress: event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + this.config.logger?.info(`status={${event.phase},total={${total}}}`); + }, + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onAuth: () => ({ + username: this.config.username, + password: this.config.password, + }), + }); + } + async init({ dir }: { dir: string }) { this.config.logger?.info(`Init git repository {dir=${dir}}`); @@ -71,43 +143,21 @@ class SCM { }); } - async add({ dir, filepath }: { dir: string; filepath: string }) { - this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`); - - return git.add({ fs, dir, filepath }); - } - - async commit({ + // https://isomorphic-git.org/docs/en/merge + async merge({ dir, - message, - author, - committer, + headBranch, + baseBranch, }: { dir: string; - message: string; - author: { name: string; email: string }; - committer: { name: string; email: string }; + headBranch: string; + baseBranch?: string; }) { this.config.logger?.info( - `Committing file to repo {dir=${dir},message=${message}}`, + `Merging branch '${headBranch}' into '${baseBranch}' for repository {dir=${dir}}`, ); - - return git.commit({ fs, dir, message, author, committer }); - } - - async addRemote({ - dir, - url, - remoteName, - }: { - dir: string; - remoteName: string; - url: string; - }) { - this.config.logger?.info( - `Creating new remote {dir=${dir},remoteName=${remoteName},url=${url}}`, - ); - return git.addRemote({ fs, dir, remote: remoteName, url }); + // If baseBranch is undefined, current branch is used. + return git.merge({ fs, dir, ours: baseBranch, theirs: headBranch }); } async push({ dir, remoteName }: { dir: string; remoteName: string }) { @@ -134,6 +184,16 @@ class SCM { }), }); } + + // https://isomorphic-git.org/docs/en/readCommit + async readCommit({ dir, sha }: { dir: string; sha: string }) { + return git.readCommit({ fs, dir, oid: sha }); + } + + // https://isomorphic-git.org/docs/en/resolveRef + async resolveRef({ dir, ref }: { dir: string; ref: string }) { + return git.resolveRef({ fs, dir, ref }); + } } // TODO(blam): This could potentially become something like for URL diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index d0c09919a0..632dbc2b66 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -50,7 +50,6 @@ "js-yaml": "^3.14.0", "mime-types": "^2.1.27", "mock-fs": "^4.13.0", - "nodegit": "^0.27.0", "recursive-readdir": "^2.2.2", "winston": "^3.2.1" }, @@ -61,7 +60,6 @@ "@types/js-yaml": "^3.12.5", "@types/mime-types": "^2.1.0", "@types/mock-fs": "^4.13.0", - "@types/nodegit": "^0.26.12", "@types/recursive-readdir": "^2.2.0" }, "jest": { diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts index e08d58d58e..749c91adc0 100644 --- a/packages/techdocs-common/src/helpers.ts +++ b/packages/techdocs-common/src/helpers.ts @@ -17,19 +17,14 @@ import os from 'os'; import path from 'path'; import parseGitUrl from 'git-url-parse'; -import NodeGit, { Clone, Repository } from 'nodegit'; import fs from 'fs-extra'; import { getDefaultBranch } from './default-branch'; import { getGitRepoType, getTokenForGitRepo } from './git-auth'; import { Entity } from '@backstage/catalog-model'; -import { InputError, UrlReader } from '@backstage/backend-common'; +import { InputError, UrlReader, Git } from '@backstage/backend-common'; import { RemoteProtocol } from './stages/prepare/types'; import { Logger } from 'winston'; -// Enables core.longpaths on windows to prevent crashing when checking out repos with long foldernames and/or deep nesting -// @ts-ignore -NodeGit.Libgit2.opts(28, 1); - export type ParsedLocationAnnotation = { type: RemoteProtocol; target: string; @@ -124,17 +119,56 @@ export const checkoutGitRepository = async ( const repositoryTmpPath = await getGitRepositoryTempFolder(repoUrl); const token = await getTokenForGitRepo(repoUrl); + // Initialize a git client + let git = Git.fromAuth({ logger }); + + // Docs about why username and password are set to these specific values. + // https://isomorphic-git.org/docs/en/onAuth#oauth2-tokens + if (token) { + const type = getGitRepoType(repoUrl); + switch (type) { + case 'github': + git = Git.fromAuth({ + username: token, + password: 'x-oauth-basic', + logger, + }); + parsedGitLocation.token = `${token}:x-oauth-basic`; + break; + case 'gitlab': + git = Git.fromAuth({ + username: 'oauth2', + password: token, + logger, + }); + parsedGitLocation.token = `dummyUsername:${token}`; + parsedGitLocation.git_suffix = true; + break; + case 'azure/api': + git = Git.fromAuth({ + username: 'notempty', + password: token, + logger: logger, + }); + break; + default: + parsedGitLocation.token = `:${token}`; + } + } + + // Pull from repository if it has already been cloned. if (fs.existsSync(repositoryTmpPath)) { try { - const repository = await Repository.open(repositoryTmpPath); - const currentBranchName = ( - await repository.getCurrentBranch() - ).shorthand(); - await repository.fetch('origin'); - await repository.mergeBranches( - currentBranchName, - `origin/${currentBranchName}`, - ); + const currentBranchName = await git.currentBranch({ + dir: repositoryTmpPath, + }); + + await git.fetch({ dir: repositoryTmpPath, remote: 'origin' }); + await git.merge({ + dir: repositoryTmpPath, + headBranch: `origin/${currentBranchName}`, + baseBranch: currentBranchName || undefined, + }); return repositoryTmpPath; } catch (e) { logger.info( @@ -144,26 +178,10 @@ export const checkoutGitRepository = async ( } } - if (token) { - const type = getGitRepoType(repoUrl); - switch (type) { - case 'gitlab': - // Personal Access Token - parsedGitLocation.token = `dummyUsername:${token}`; - parsedGitLocation.git_suffix = true; - break; - case 'github': - parsedGitLocation.token = `${token}:x-oauth-basic`; - break; - default: - parsedGitLocation.token = `:${token}`; - } - } - const repositoryCheckoutUrl = parsedGitLocation.toString('https'); fs.mkdirSync(repositoryTmpPath, { recursive: true }); - await Clone.clone(repositoryCheckoutUrl, repositoryTmpPath); + await git.clone({ url: repositoryCheckoutUrl, dir: repositoryTmpPath }); return repositoryTmpPath; }; @@ -174,10 +192,11 @@ export const getLastCommitTimestamp = async ( ): Promise => { const repositoryLocation = await checkoutGitRepository(repositoryUrl, logger); - const repository = await Repository.open(repositoryLocation); - const commit = await repository.getReferenceCommit('HEAD'); + const git = Git.fromAuth({ logger }); + const sha = await git.resolveRef({ dir: repositoryLocation, ref: 'HEAD' }); + const commit = await git.readCommit({ dir: repositoryLocation, sha }); - return commit.date().getTime(); + return commit.commit.committer.timestamp; }; export const getDocFilesFromRepository = async ( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts index ce1c18e048..a38c5f4fdc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts @@ -57,7 +57,7 @@ export class AzurePreparer implements PreparerBase { template.spec.path ?? '.', ); - // Username can anything but the empty string according to: + // Username can be anything but the empty string according to: // https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat const git = this.privateToken ? Git.fromAuth({ diff --git a/yarn.lock b/yarn.lock index 99c691297a..43da6893ed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4348,11 +4348,6 @@ resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@sindresorhus/is@^2.0.0": - version "2.1.1" - resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz#ceff6a28a5b4867c2dd4a1ba513de278ccbe8bb1" - integrity sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg== - "@sindresorhus/is@^3.1.1": version "3.1.2" resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8" @@ -5110,7 +5105,7 @@ dependencies: defer-to-connect "^1.0.1" -"@szmarczak/http-timer@^4.0.0", "@szmarczak/http-timer@^4.0.5": +"@szmarczak/http-timer@^4.0.5": version "4.0.5" resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" integrity sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ== @@ -5822,7 +5817,7 @@ resolved "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72" integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw== -"@types/keyv@*", "@types/keyv@^3.1.1": +"@types/keyv@*": version "3.1.1" resolved "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" integrity sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw== @@ -8278,14 +8273,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - bl@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" @@ -8544,19 +8531,6 @@ btoa@^1.2.1: resolved "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -8567,11 +8541,6 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -8740,14 +8709,6 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cacheable-lookup@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz#87be64a18b925234875e10a9bb1ebca4adce6b38" - integrity sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg== - dependencies: - "@types/keyv" "^3.1.1" - keyv "^4.0.0" - cacheable-lookup@^5.0.3: version "5.0.3" resolved "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz#049fdc59dffdd4fc285e8f4f82936591bd59fec3" @@ -9055,7 +9016,7 @@ chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.3.1, chokidar@^3.4.1, chokidar@^3. optionalDependencies: fsevents "~2.1.2" -chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2: +chownr@^1.1.1, chownr@^1.1.2: version "1.1.4" resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -10719,13 +10680,6 @@ decompress-response@^4.2.0: dependencies: mimic-response "^2.0.0" -decompress-response@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz#7849396e80e3d1eba8cb2f75ef4930f76461cb0f" - integrity sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw== - dependencies: - mimic-response "^2.0.0" - decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -12874,7 +12828,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^7.0.0, fs-extra@^7.0.1: +fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -13446,27 +13400,6 @@ google-p12-pem@^3.0.3: dependencies: node-forge "^0.10.0" -got@^10.7.0: - version "10.7.0" - resolved "https://registry.npmjs.org/got/-/got-10.7.0.tgz#62889dbcd6cca32cd6a154cc2d0c6895121d091f" - integrity sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg== - dependencies: - "@sindresorhus/is" "^2.0.0" - "@szmarczak/http-timer" "^4.0.0" - "@types/cacheable-request" "^6.0.1" - cacheable-lookup "^2.0.0" - cacheable-request "^7.0.1" - decompress-response "^5.0.0" - duplexer3 "^0.1.4" - get-stream "^5.0.0" - lowercase-keys "^2.0.0" - mimic-response "^2.1.0" - p-cancelable "^2.0.0" - p-event "^4.0.0" - responselike "^2.0.0" - to-readable-stream "^2.0.0" - type-fest "^0.10.0" - got@^11.5.2: version "11.6.0" resolved "https://registry.npmjs.org/got/-/got-11.6.0.tgz#4978c78f3cbc3a45ee95381f8bb6efd1db1f4638" @@ -15969,7 +15902,7 @@ json3@^3.3.2: resolved "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== -json5@2.x, json5@^2.1.0, json5@^2.1.1, json5@^2.1.2: +json5@2.x, json5@^2.1.1, json5@^2.1.2: version "2.1.3" resolved "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== @@ -17481,7 +17414,7 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0, mimic-response@^2.1.0: +mimic-response@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== @@ -18001,23 +17934,6 @@ node-gyp@3.x: tar "^2.0.0" which "1" -node-gyp@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45" - integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA== - dependencies: - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - osenv "0" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" - tar "^4.4.8" - which "1" - node-gyp@^5.0.2: version "5.1.0" resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.0.tgz#8e31260a7af4a2e2f994b0673d4e0b3866156332" @@ -18107,22 +18023,6 @@ node-pre-gyp@^0.11.0: semver "^5.3.0" tar "^4" -node-pre-gyp@^0.13.0: - version "0.13.0" - resolved "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" - integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - node-releases@^1.1.52, node-releases@^1.1.58: version "1.1.60" resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" @@ -18151,21 +18051,6 @@ node-request-interceptor@^0.5.1: debug "^4.1.1" headers-utils "^1.2.0" -nodegit@^0.27.0: - version "0.27.0" - resolved "https://registry.npmjs.org/nodegit/-/nodegit-0.27.0.tgz#4e8cc236f60e1c97324a5acff99056fe116a6ebe" - integrity sha512-E9K4gPjWiA0b3Tx5lfWCzG7Cvodi2idl3V5UD2fZrOrHikIfrN7Fc2kWLtMUqqomyoToYJLeIC8IV7xb1CYRLA== - dependencies: - fs-extra "^7.0.0" - got "^10.7.0" - json5 "^2.1.0" - lodash "^4.17.14" - nan "^2.14.0" - node-gyp "^4.0.0" - node-pre-gyp "^0.13.0" - ramda "^0.25.0" - tar-fs "^1.16.3" - nodemon@^2.0.2: version "2.0.6" resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz#1abe1937b463aaf62f0d52e2b7eaadf28cc2240d" @@ -18750,7 +18635,7 @@ p-each-series@^2.1.0: resolved "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== -p-event@^4.0.0, p-event@^4.1.0: +p-event@^4.1.0: version "4.2.0" resolved "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== @@ -20285,14 +20170,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -pump@^1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" - integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - pump@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -20438,11 +20315,6 @@ ramda@^0.21.0: resolved "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= -ramda@^0.25.0: - version "0.25.0" - resolved "https://registry.npmjs.org/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" - integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== - ramda@^0.26, ramda@~0.26.1: version "0.26.1" resolved "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" @@ -21201,7 +21073,7 @@ read@1, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -23495,16 +23367,6 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar-fs@^1.16.3: - version "1.16.3" - resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" - integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== - dependencies: - chownr "^1.0.1" - mkdirp "^0.5.1" - pump "^1.0.0" - tar-stream "^1.1.2" - tar-fs@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" @@ -23515,19 +23377,6 @@ tar-fs@~2.0.1: pump "^3.0.0" tar-stream "^2.0.0" -tar-stream@^1.1.2: - version "1.6.2" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - tar-stream@^2.0.0, tar-stream@^2.1.4: version "2.1.4" resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz#c4fb1a11eb0da29b893a5b25476397ba2d053bfa" @@ -23867,11 +23716,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -23889,11 +23733,6 @@ to-readable-stream@^1.0.0: resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== -to-readable-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz#82880316121bea662cdc226adb30addb50cb06e8" - integrity sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w== - to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -24194,11 +24033,6 @@ type-detect@4.0.8: resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.10.0: - version "0.10.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642" - integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw== - type-fest@^0.11.0: version "0.11.0" resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" From cb28e1a6a0ceede54d6fa9a2397ef3a87cdc327b Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Wed, 23 Dec 2020 00:34:12 +0100 Subject: [PATCH 25/80] chore(git): Need author and commiter for doing git merge --- packages/backend-common/src/scm/git.ts | 13 ++++++++++++- packages/techdocs-common/src/helpers.ts | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index b744040cb2..871a623b19 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -148,16 +148,27 @@ class SCM { dir, headBranch, baseBranch, + author, + committer, }: { dir: string; headBranch: string; baseBranch?: string; + author: { name: string; email: string }; + committer: { name: string; email: string }; }) { this.config.logger?.info( `Merging branch '${headBranch}' into '${baseBranch}' for repository {dir=${dir}}`, ); // If baseBranch is undefined, current branch is used. - return git.merge({ fs, dir, ours: baseBranch, theirs: headBranch }); + return git.merge({ + fs, + dir, + ours: baseBranch, + theirs: headBranch, + author, + committer, + }); } async push({ dir, remoteName }: { dir: string; remoteName: string }) { diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts index 749c91adc0..9685218bfa 100644 --- a/packages/techdocs-common/src/helpers.ts +++ b/packages/techdocs-common/src/helpers.ts @@ -168,6 +168,11 @@ export const checkoutGitRepository = async ( dir: repositoryTmpPath, headBranch: `origin/${currentBranchName}`, baseBranch: currentBranchName || undefined, + author: { name: 'Backstage TechDocs', email: 'techdocs@backstage.io' }, + committer: { + name: 'Backstage TechDocs', + email: 'techdocs@backstage.io', + }, }); return repositoryTmpPath; } catch (e) { From 2f8b7ca646859cd0b86847e16e500220c8bcac10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Dec 2020 04:46:37 +0000 Subject: [PATCH 26/80] build(deps-dev): bump @octokit/openapi-types from 2.0.0 to 2.0.1 Bumps [@octokit/openapi-types](https://github.com/octokit/openapi-types.ts) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/octokit/openapi-types.ts/releases) - [Commits](https://github.com/octokit/openapi-types.ts/compare/v2.0.0...v2.0.1) Signed-off-by: dependabot[bot] --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 195f746693..83e2465106 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1666,10 +1666,10 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.4.1" + version "0.4.2" dependencies: "@backstage/config" "^0.1.2" - "@backstage/core-api" "^0.2.6" + "@backstage/core-api" "^0.2.7" "@backstage/theme" "^0.2.2" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -3921,9 +3921,9 @@ universal-user-agent "^6.0.0" "@octokit/openapi-types@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.0.tgz#6d8f8ad9db3b75a39115f5def2654df8bed39f28" - integrity sha512-J4bfM7lf8oZvEAdpS71oTvC1ofKxfEZgU5vKVwzZKi4QPiL82udjpseJwxPid9Pu2FNmyRQOX4iEj6W1iOSnPw== + version "2.0.1" + resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.0.1.tgz#7453d8281ce66b8ed1607f7ac7d751c3baffd2cc" + integrity sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q== "@octokit/plugin-enterprise-rest@^6.0.1": version "6.0.1" From 4b896485e4d2ac423fdf348ca5222546066c108f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 23 Dec 2020 13:56:24 +0100 Subject: [PATCH 27/80] core-api: deprecate RouteRef path and remove deprecated createSubRoute --- packages/core-api/src/routing/RouteRef.ts | 14 ++------------ packages/core-api/src/routing/types.ts | 9 +++------ 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index f89634e0ec..164722766b 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -25,25 +25,15 @@ export class AbsoluteRouteRef { // TODO(Rugvip): Remove this, routes are looked up via the registry instead get path() { - return this.config.path; + return this.config.path ?? ''; } get title() { return this.config.title; } - /** - * This function should not be used, create a separate RouteRef instead - * @deprecated - */ - createSubRoute(): any { - throw new Error( - 'This method should not be called, create a separate RouteRef instead', - ); - } - toString() { - return `routeRef{path=${this.path}}`; + return `routeRef{title=${this.title}}`; } } diff --git a/packages/core-api/src/routing/types.ts b/packages/core-api/src/routing/types.ts index c6d79fd991..99a20c31e9 100644 --- a/packages/core-api/src/routing/types.ts +++ b/packages/core-api/src/routing/types.ts @@ -19,14 +19,10 @@ import { IconComponent } from '../icons'; // @ts-ignore, we're just embedding the Params type for usage in other places export type RouteRef = { // TODO(Rugvip): Remove path, look up via registry instead + /** @deprecated paths are no longer accessed directly from RouteRefs, use useRouteRef instead */ path: string; icon?: IconComponent; title: string; - /** - * This function should not be used, create a separate RouteRef instead - * @deprecated - */ - createSubRoute(): any; }; export type AnyRouteRef = RouteRef; @@ -51,7 +47,8 @@ export type MutableRouteRef = RouteRef<{}>; export type RouteRefConfig = { params?: Array; - path: string; + /** @deprecated Route refs no longer decide their own path */ + path?: string; icon?: IconComponent; title: string; }; From 99205ec62590ac43e76c8bb949078f45fcf06ea5 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 23 Dec 2020 14:29:13 +0100 Subject: [PATCH 28/80] core-api: use typescript workaround for using private constructor instead of a runtime one --- packages/core-api/src/routing/RouteRef.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/core-api/src/routing/RouteRef.ts b/packages/core-api/src/routing/RouteRef.ts index 164722766b..4c2da34098 100644 --- a/packages/core-api/src/routing/RouteRef.ts +++ b/packages/core-api/src/routing/RouteRef.ts @@ -44,13 +44,7 @@ export function createRouteRef< return new AbsoluteRouteRef(config); } -const create = Symbol('create-external-route-ref'); - export class ExternalRouteRef { - static [create]() { - return new ExternalRouteRef(); - } - private constructor() {} toString() { @@ -59,5 +53,5 @@ export class ExternalRouteRef { } export function createExternalRouteRef(): ExternalRouteRef { - return ExternalRouteRef[create](); + return new ((ExternalRouteRef as unknown) as { new (): ExternalRouteRef })(); } From 86c3c652a8ced9e31dbed1d47f85c8ee72d8017e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 23 Dec 2020 14:32:04 +0100 Subject: [PATCH 29/80] changeset: add changeset for core-api RouteRef deprecations --- .changeset/polite-turtles-prove.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-turtles-prove.md diff --git a/.changeset/polite-turtles-prove.md b/.changeset/polite-turtles-prove.md new file mode 100644 index 0000000000..094617026c --- /dev/null +++ b/.changeset/polite-turtles-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-api': patch +--- + +Deprecate `RouteRef` path parameter and member, and remove deprecated `routeRef.createSubRouteRef`. From 51f4005f3afcccfea8d91d9ee8284b2869ad3cb8 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 10:12:20 -0500 Subject: [PATCH 30/80] Remove unnecessary step --- .github/workflows/codeql-analysis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2fafd3756d..fdb6797920 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,11 +36,6 @@ jobs: # a pull request then we can checkout the head. fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v1 From b721eab127358aa1f20a3284e54f3c1bdfe03e35 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 10:18:52 -0500 Subject: [PATCH 31/80] Speed up some PRs with paths-ignore --- .github/workflows/codeql-analysis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index fdb6797920..92660b9ca4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -11,6 +11,11 @@ on: pull_request: # The branches below must be a subset of the branches above branches: [master] + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#scanning-pull-requests + paths-ignore: + - '**/*.md' + - '**/*.yml' + - '**/*.yaml' schedule: - cron: '0 8 * * 6' From 7dfcdc1720e96f6d61d873ab550678d142f25139 Mon Sep 17 00:00:00 2001 From: Fidel Coria Date: Wed, 23 Dec 2020 11:15:36 -0600 Subject: [PATCH 32/80] reduce close timeout to 100 ms --- plugins/auth-backend/src/lib/flow/authFlowHelpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts b/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts index 86a615e721..e70aa0bfee 100644 --- a/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts +++ b/plugins/auth-backend/src/lib/flow/authFlowHelpers.ts @@ -58,7 +58,7 @@ export const postMessageResponse = ( (window.opener || window.parent).postMessage(JSON.parse(authResponse), origin); setTimeout(() => { window.close(); - }, 100 * 2); // double the interval of the core-api lib/loginPopup.ts + }, 100); // same as the interval of the core-api lib/loginPopup.ts (to address race conditions) `; const hash = crypto.createHash('sha256').update(script).digest('base64'); From 87c0c53c2f2018b2d1878bad01940d0f765a3bf4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 23 Dec 2020 18:45:43 +0100 Subject: [PATCH 33/80] Create polite-glasses-occur.md --- .changeset/polite-glasses-occur.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-glasses-occur.md diff --git a/.changeset/polite-glasses-occur.md b/.changeset/polite-glasses-occur.md new file mode 100644 index 0000000000..bec533caad --- /dev/null +++ b/.changeset/polite-glasses-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Add new `EntityProvider` component, which can be used to provide an entity for the `useEntity` hook. From 696b8ce74a864d37106d637f7b3554bd39d6d9ed Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 23 Dec 2020 18:46:42 +0100 Subject: [PATCH 34/80] Create loud-days-breathe.md --- .changeset/loud-days-breathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/loud-days-breathe.md diff --git a/.changeset/loud-days-breathe.md b/.changeset/loud-days-breathe.md new file mode 100644 index 0000000000..f8eb561f31 --- /dev/null +++ b/.changeset/loud-days-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/dev-utils': patch +--- + +Add new `addPage` method for use with extensions, as well as an `EntityGridItem` to easily create different test cases for entity overview cards. From d4c6feb67b6acb26b1e41d46c935fc78f5d6d51b Mon Sep 17 00:00:00 2001 From: Jeff Feng <46946747+fengypants@users.noreply.github.com> Date: Wed, 23 Dec 2020 13:50:57 -0500 Subject: [PATCH 35/80] Update microsite's demos page to link to demo site Updating the intro paragraph on backstage.io/demos to include a link to demo.backstage.io. --- microsite/pages/en/demos.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/microsite/pages/en/demos.js b/microsite/pages/en/demos.js index 63c15ab698..bcc8520965 100644 --- a/microsite/pages/en/demos.js +++ b/microsite/pages/en/demos.js @@ -17,22 +17,21 @@ const Background = props => { - See us in action. + See us in action - To illustrate the potential of Backstage, we’re showing you{' '} - - how we use it here at Spotify + To explore the UI and basic features of Backstage firsthand, go to: {' '} + + demo.backstage.io - . The videos below feature the custom plugins and templates that - we built for our internal version of Backstage. You can use - Backstage to build the developer portal you want — integrating the - tools that you use in your own infrastructure ecosystem. (Or get - started by building an open source plugin for Backstage that - everyone can use, like our{' '} - - Lighthouse Plugin + . + + + Watch the videos below to get an introduction to Backstage and + to see how we use different plugins to customize {' '} + + our internal version of Backstage at Spotify - .) + . From 2f2bc1b3f8e5162abc0e7aa23f025b047003d147 Mon Sep 17 00:00:00 2001 From: Jeff Feng <46946747+fengypants@users.noreply.github.com> Date: Wed, 23 Dec 2020 13:59:29 -0500 Subject: [PATCH 36/80] Update demos.js --- microsite/pages/en/demos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/pages/en/demos.js b/microsite/pages/en/demos.js index bcc8520965..d29ab0ccf5 100644 --- a/microsite/pages/en/demos.js +++ b/microsite/pages/en/demos.js @@ -28,7 +28,7 @@ const Background = props => { Watch the videos below to get an introduction to Backstage and to see how we use different plugins to customize {' '} - + our internal version of Backstage at Spotify . From 660f646d118b7a0bdd70633e195c887e742fd31a Mon Sep 17 00:00:00 2001 From: Jeff Feng <46946747+fengypants@users.noreply.github.com> Date: Wed, 23 Dec 2020 14:15:52 -0500 Subject: [PATCH 37/80] Update demo.js (fixing blog URL) --- microsite/pages/en/demos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/pages/en/demos.js b/microsite/pages/en/demos.js index d29ab0ccf5..9e53c39afa 100644 --- a/microsite/pages/en/demos.js +++ b/microsite/pages/en/demos.js @@ -28,7 +28,7 @@ const Background = props => { Watch the videos below to get an introduction to Backstage and to see how we use different plugins to customize {' '} - + our internal version of Backstage at Spotify . From 5f0bb1dfb51c600425b6de9e66ceaaadf707bfd4 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 14:27:48 -0500 Subject: [PATCH 38/80] Fix typo and rewording --- .../ProjectGrowthInstructionsPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index 4fcc34c87f..dcd33a02e8 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -101,7 +101,7 @@ export const ProjectGrowthInstructionsPage = () => { Investigating cloud cost growth Cost Insights shows an alert when costs for a particular billing entity, - such as a GCP project, have grown at a rate faster than our alerting + such as a GCP project, has grown at a rate faster than our alerting threshold. The responsible team should follow this guide to decide whether this warrants further investigation. @@ -135,7 +135,7 @@ export const ProjectGrowthInstructionsPage = () => { Next, evaluate whether the growth is significant. This helps avoid premature optimization, where cost in engineering time is more than - would be saved from the optimization over a reasonable timeframe. + would be saved from the optimization over a reasonable time frame. We recommend reframing the cost growth itself in terms of engineering @@ -205,7 +205,7 @@ export const ProjectGrowthInstructionsPage = () => { Is the workload using cloud resources efficiently? For compute resources, do the utilization metrics look reasonable? Autoscaling infrastructure, such as Kubernetes, can run workloads more efficiently - without comprimising reliability. + without compromising reliability. Lifecycle From f1462655f9ce8c06ce7b286d3b16c90e7acb8275 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 14:28:11 -0500 Subject: [PATCH 39/80] Display links properly in label instructions --- .../LabelDataflowInstructionsPage.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx index 3442de49fc..ba5a22e932 100644 --- a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Box, Typography } from '@material-ui/core'; +import { Box, Typography, Link } from '@material-ui/core'; import { CodeSnippet } from '@backstage/core'; import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; @@ -31,10 +31,10 @@ export const LabelDataflowInstructionsPage = () => { In Cloud Dataflow, labels can be added to a job either programmatically - or via the command-line when launching a job. Note that GCP has - + or via the command-line when launching a job. Note that GCP has{' '} + restrictions - {' '} + {' '} on the length and characters that can be used in labels. @@ -46,9 +46,9 @@ export const LabelDataflowInstructionsPage = () => { DataflowPipelineOptions Dataflow jobs using Beam's{' '} - + DataflowPipelineOptions - {' '} + {' '} directly can use the setLabels function to add one or more labels: "my-dataflow-job For more information on specifying options, see the{' '} - + Dataflow documentation - {' '} + {' '} or{' '} - + Scio Scaladoc - + . From 3fca9adb97a9062612ea5b9feef4f1d875ccaf67 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 14:31:35 -0500 Subject: [PATCH 40/80] Add changeset --- .changeset/lucky-fans-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-fans-wait.md diff --git a/.changeset/lucky-fans-wait.md b/.changeset/lucky-fans-wait.md new file mode 100644 index 0000000000..439d943c65 --- /dev/null +++ b/.changeset/lucky-fans-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Fix links in sample instructions From 51f55e5105890b1e3e8bd8e8e55e3b4efa120466 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 23 Dec 2020 15:08:13 -0500 Subject: [PATCH 41/80] Return wording --- .../ProjectGrowthInstructionsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx index dcd33a02e8..02b66b0fd1 100644 --- a/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/ProjectGrowthInstructionsPage/ProjectGrowthInstructionsPage.tsx @@ -101,7 +101,7 @@ export const ProjectGrowthInstructionsPage = () => { Investigating cloud cost growth Cost Insights shows an alert when costs for a particular billing entity, - such as a GCP project, has grown at a rate faster than our alerting + such as a GCP project, have grown at a rate faster than our alerting threshold. The responsible team should follow this guide to decide whether this warrants further investigation. From db1fafb32156548805fc7e5c58be9a43b740d30f Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Wed, 23 Dec 2020 21:40:40 +0100 Subject: [PATCH 42/80] microsite: run prettier on demo page --- microsite/pages/en/demos.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/microsite/pages/en/demos.js b/microsite/pages/en/demos.js index 9e53c39afa..c26fc9a8e8 100644 --- a/microsite/pages/en/demos.js +++ b/microsite/pages/en/demos.js @@ -19,17 +19,14 @@ const Background = props => { See us in action - To explore the UI and basic features of Backstage firsthand, go to: {' '} - - demo.backstage.io - - . + To explore the UI and basic features of Backstage firsthand, go + to: demo.backstage.io. - Watch the videos below to get an introduction to Backstage and - to see how we use different plugins to customize {' '} + Watch the videos below to get an introduction to Backstage and to + see how we use different plugins to customize{' '} - our internal version of Backstage at Spotify + our internal version of Backstage at Spotify . From 021e40aff625e354df48cac0c6188514fb17f71e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Dec 2020 05:04:33 +0000 Subject: [PATCH 43/80] build(deps): bump rollup-plugin-esbuild from 2.6.0 to 2.6.1 Bumps [rollup-plugin-esbuild](https://github.com/egoist/rollup-plugin-esbuild) from 2.6.0 to 2.6.1. - [Release notes](https://github.com/egoist/rollup-plugin-esbuild/releases) - [Changelog](https://github.com/egoist/rollup-plugin-esbuild/blob/master/.releaserc.json) - [Commits](https://github.com/egoist/rollup-plugin-esbuild/compare/v2.6.0...v2.6.1) Signed-off-by: dependabot[bot] --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 195f746693..208d87591b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1666,10 +1666,10 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.4.1" + version "0.4.2" dependencies: "@backstage/config" "^0.1.2" - "@backstage/core-api" "^0.2.6" + "@backstage/core-api" "^0.2.7" "@backstage/theme" "^0.2.2" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -21856,9 +21856,9 @@ rollup-plugin-dts@1.4.13: "@babel/code-frame" "^7.10.4" rollup-plugin-esbuild@2.6.x: - version "2.6.0" - resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.6.0.tgz#80336399b113a179ccb2af5bdf7c03f061f37146" - integrity sha512-wtyDAX8kNABrBfwkrrG2xLRKRGSWUyMBURS067IRvRMpgJlLRo14WcFl95uGc4iYWfdAx436/z1LMzYqdlY4ig== + version "2.6.1" + resolved "https://registry.npmjs.org/rollup-plugin-esbuild/-/rollup-plugin-esbuild-2.6.1.tgz#5785532940d49adf1bff5b38e9bd9089262d4e7a" + integrity sha512-hskMEQQ4Vxlyoeg1OWlFTwWHIhpNaw6q+diOT7p9pdkk34m9Mbk3aymS/JbTqLXy/AbJi22iuXrucknKpeczfg== dependencies: "@rollup/pluginutils" "^4.1.0" joycon "^2.2.5" From d63cc1fe5267b1d01eb9dffc4ea330f7daafea80 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Sun, 27 Dec 2020 09:45:06 +0100 Subject: [PATCH 44/80] fix: token expiration in s, not ms --- plugins/auth-backend/src/identity/TokenFactory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index c4c259ed22..36622332e0 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -69,7 +69,7 @@ export class TokenFactory implements TokenIssuer { const sub = params.claims.sub; const aud = 'backstage'; const iat = Math.floor(Date.now() / MS_IN_S); - const exp = iat + this.keyDurationSeconds * MS_IN_S; + const exp = iat + this.keyDurationSeconds; this.logger.info(`Issuing token for ${sub}`); From cc046682e2ef1ad5ab9ccd1a834704f64c8d197f Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Sun, 27 Dec 2020 09:55:19 +0100 Subject: [PATCH 45/80] Add changeset --- .changeset/warm-pets-sin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/warm-pets-sin.md diff --git a/.changeset/warm-pets-sin.md b/.changeset/warm-pets-sin.md new file mode 100644 index 0000000000..3a9197e7f2 --- /dev/null +++ b/.changeset/warm-pets-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +fix bug in token expiration date From 4975224d8ec65bd725cca8a55b67cf48bccabafb Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Sun, 27 Dec 2020 10:52:18 +0100 Subject: [PATCH 46/80] Adjust test --- plugins/auth-backend/src/identity/TokenFactory.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/src/identity/TokenFactory.test.ts b/plugins/auth-backend/src/identity/TokenFactory.test.ts index 4303401ee6..8b719799b1 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.test.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.test.ts @@ -87,7 +87,7 @@ describe('TokenFactory', () => { iat: expect.any(Number), exp: expect.any(Number), }); - expect(payload.exp).toBe(payload.iat + keyDurationSeconds * 1000); + expect(payload.exp).toBe(payload.iat + keyDurationSeconds); }); it('should generate new signing keys when the current one expires', async () => { From cff6a9e70f0d1cd74b0a924c324812807fb000a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Kalv=C4=81ns?= Date: Mon, 28 Dec 2020 10:38:49 +0100 Subject: [PATCH 47/80] Fix parameter name in docstring for duration#inclusiveStartDateOf --- plugins/cost-insights/src/utils/duration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cost-insights/src/utils/duration.ts b/plugins/cost-insights/src/utils/duration.ts index 7a330b6f91..6eebead1d7 100644 --- a/plugins/cost-insights/src/utils/duration.ts +++ b/plugins/cost-insights/src/utils/duration.ts @@ -24,7 +24,7 @@ export const DEFAULT_DURATION = Duration.P30D; * Derive the start date of a given period, assuming two repeating intervals. * * @param duration see comment on Duration enum - * @param endDate from CostInsightsApi.getLastCompleteBillingDate + 1 day + * @param exclusiveEndDate from CostInsightsApi.getLastCompleteBillingDate + 1 day */ export function inclusiveStartDateOf( duration: Duration, From 63f40032ca03049f9f7a942e76c565d60993e6ab Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 28 Dec 2020 11:13:50 +0100 Subject: [PATCH 48/80] Update plugins/catalog/src/hooks/useEntity.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw --- plugins/catalog/src/hooks/useEntity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/hooks/useEntity.ts b/plugins/catalog/src/hooks/useEntity.ts index 7b689e8730..289c4e26aa 100644 --- a/plugins/catalog/src/hooks/useEntity.ts +++ b/plugins/catalog/src/hooks/useEntity.ts @@ -55,7 +55,7 @@ export const useEntityFromUrl = (): EntityLoadingStatus => { }; /** - * Grab Entity from the context and it's current loading state. + * Grab Entity from the context and its current loading state. */ export const useEntity = () => { const { entity, loading, error } = useContext<{ From 5b6533eb76aea627c295b23d40b68664e6a31c15 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 24 Dec 2020 12:53:02 +0100 Subject: [PATCH 49/80] core-api: rename BackstageRoutes to FlatRoutes --- .changeset/dull-seals-march.md | 2 +- .../src/routing/{BackstageRoutes.tsx => FlatRoutes.tsx} | 6 ++---- packages/core-api/src/routing/index.ts | 2 +- packages/dev-utils/src/devApp/render.tsx | 6 +++--- 4 files changed, 7 insertions(+), 9 deletions(-) rename packages/core-api/src/routing/{BackstageRoutes.tsx => FlatRoutes.tsx} (94%) diff --git a/.changeset/dull-seals-march.md b/.changeset/dull-seals-march.md index 714c5c5cad..49e1f7f2e6 100644 --- a/.changeset/dull-seals-march.md +++ b/.changeset/dull-seals-march.md @@ -3,4 +3,4 @@ '@backstage/core': patch --- -Add `BackstageRoutes` component to replace the top-level `Routes` component from `react-router` within apps, removing the need for manually appending `/*` to paths or sorting routes. +Add `FlatRoutes` component to replace the top-level `Routes` component from `react-router` within apps, removing the need for manually appending `/*` to paths or sorting routes. diff --git a/packages/core-api/src/routing/BackstageRoutes.tsx b/packages/core-api/src/routing/FlatRoutes.tsx similarity index 94% rename from packages/core-api/src/routing/BackstageRoutes.tsx rename to packages/core-api/src/routing/FlatRoutes.tsx index 6c042af27d..a6783964a7 100644 --- a/packages/core-api/src/routing/BackstageRoutes.tsx +++ b/packages/core-api/src/routing/FlatRoutes.tsx @@ -66,13 +66,11 @@ function createRoutesFromChildren(children: ReactNode): RouteObject[] { }); } -type BackstageRoutesProps = { +type FlatRoutesProps = { children: ReactNode; }; -export const BackstageRoutes = ( - props: BackstageRoutesProps, -): JSX.Element | null => { +export const FlatRoutes = (props: FlatRoutesProps): JSX.Element | null => { const routes = createRoutesFromChildren(props.children); return useRoutes(routes); }; diff --git a/packages/core-api/src/routing/index.ts b/packages/core-api/src/routing/index.ts index 2bdf0aa5e8..9564b3b225 100644 --- a/packages/core-api/src/routing/index.ts +++ b/packages/core-api/src/routing/index.ts @@ -21,6 +21,6 @@ export type { ConcreteRoute, MutableRouteRef, } from './types'; -export { BackstageRoutes } from './BackstageRoutes'; +export { FlatRoutes } from './FlatRoutes'; export { createRouteRef } from './RouteRef'; export { useRouteRef } from './hooks'; diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index f15a4c4078..f1a6d30b4c 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -30,7 +30,7 @@ import { OAuthRequestDialog, AnyApiFactory, IconComponent, - BackstageRoutes, + FlatRoutes, attachComponentData, } from '@backstage/core'; import SentimentDissatisfiedIcon from '@material-ui/icons/SentimentDissatisfied'; @@ -133,10 +133,10 @@ class DevAppBuilder { {sidebar} - + {this.routes} {deprecatedAppRoutes} - + From 37b28bad44acb2003735cacee80275f147547b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81rti=C5=86=C5=A1=20Kalv=C4=81ns?= Date: Mon, 28 Dec 2020 11:34:56 +0100 Subject: [PATCH 50/80] Introduce slight bias towards positive trend in cost insights mock data --- plugins/cost-insights/src/utils/mockData.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/cost-insights/src/utils/mockData.ts b/plugins/cost-insights/src/utils/mockData.ts index ce9e65f1c3..19f9676eea 100644 --- a/plugins/cost-insights/src/utils/mockData.ts +++ b/plugins/cost-insights/src/utils/mockData.ts @@ -234,14 +234,24 @@ export function aggregationFor( 'day', ); + function nextDelta(): number { + const varianceFromBaseline = 0.15; + // Let's give positive vibes in trendlines - higher change for positive delta with >0.5 value + const positiveTrendChance = 0.55; + const normalization = positiveTrendChance - 1; + return baseline * (Math.random() + normalization) * varianceFromBaseline; + } + return [...Array(days).keys()].reduce( (values: DateAggregation[], i: number): DateAggregation[] => { const last = values.length ? values[values.length - 1].amount : baseline; + const date = dayjs(inclusiveStartDateOf(duration, endDate)) + .add(i, 'day') + .format(DEFAULT_DATE_FORMAT); + const amount = Math.max(0, last + nextDelta()); values.push({ - date: dayjs(inclusiveStartDateOf(duration, endDate)) - .add(i, 'day') - .format(DEFAULT_DATE_FORMAT), - amount: Math.max(0, last + (baseline / 20) * (Math.random() * 2 - 1)), + date: date, + amount: amount, }); return values; }, From 0574a27b7ce32daa0f3038a01e666cee91227084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 28 Dec 2020 10:02:34 +0100 Subject: [PATCH 51/80] cli: fix windows tests --- .../LinkedPackageResolvePlugin.test.ts | 63 +++++++++++-------- .../src/stages/publish/helpers.test.ts | 12 ++-- 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.test.ts b/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.test.ts index 53512567eb..b4580ea281 100644 --- a/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.test.ts +++ b/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.test.ts @@ -14,20 +14,27 @@ * limitations under the License. */ +import * as os from 'os'; +import * as path from 'path'; import { LinkedPackageResolvePlugin } from './LinkedPackageResolvePlugin'; describe('LinkedPackageResolvePlugin', () => { + const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; + it('should re-write paths for external packages', () => { - const plugin = new LinkedPackageResolvePlugin('/root/repo/node_modules', [ - { - name: 'a', - location: '/root/external-a', - }, - { - name: '@s/b', - location: '/root/external-b', - }, - ]); + const plugin = new LinkedPackageResolvePlugin( + path.resolve(root, 'repo/node_modules'), + [ + { + name: 'a', + location: path.resolve(root, 'external-a'), + }, + { + name: '@s/b', + location: path.resolve(root, 'external-b'), + }, + ], + ); const tapAsync = jest.fn(); const doResolve = jest.fn(); @@ -50,10 +57,10 @@ describe('LinkedPackageResolvePlugin', () => { const callbackX = jest.fn(); tap( { - request: '/root/repo/package/x/src/module.ts', - path: '/root/repo/package/x/src', + request: path.resolve(root, 'repo/package/x/src/module.ts'), + path: path.resolve(root, 'repo/package/x/src'), context: { - issuer: '/root/repo/package/x/src/index.ts', + issuer: path.resolve(root, 'repo/package/x/src/index.ts'), }, }, 'some-context', @@ -81,10 +88,10 @@ describe('LinkedPackageResolvePlugin', () => { const callbackA = jest.fn(); tap( { - request: '/root/external-a/src/module.ts', - path: '/root/external-a/src', + request: path.resolve(root, 'external-a/src/module.ts'), + path: path.resolve(root, 'external-a/src'), context: { - issuer: '/root/external-a/src/index.ts', + issuer: path.resolve(root, 'external-a/src/index.ts'), }, }, 'some-context', @@ -95,13 +102,16 @@ describe('LinkedPackageResolvePlugin', () => { expect(doResolve).toHaveBeenCalledWith( resolver.hooks.resolve, { - request: '/root/external-a/src/module.ts', - path: '/root/repo/node_modules/a/src', + request: path.resolve(root, 'external-a/src/module.ts'), + path: path.resolve(root, 'repo/node_modules/a/src'), context: { - issuer: '/root/repo/node_modules/a/src/index.ts', + issuer: path.resolve(root, 'repo/node_modules/a/src/index.ts'), }, }, - 'resolve /root/external-a/src/module.ts in /root/repo/node_modules/a', + `resolve ${path.resolve( + root, + 'external-a/src/module.ts', + )} in ${path.resolve(root, 'repo/node_modules/a')}`, 'some-context', callbackA, ); @@ -110,8 +120,8 @@ describe('LinkedPackageResolvePlugin', () => { const callbackB = jest.fn(); tap( { - request: '/root/external-b/src/module.ts', - path: '/root/external-b/src', + request: path.resolve(root, 'external-b/src/module.ts'), + path: path.resolve(root, 'external-b/src'), context: { issuer: false, }, @@ -124,13 +134,16 @@ describe('LinkedPackageResolvePlugin', () => { expect(doResolve).toHaveBeenLastCalledWith( resolver.hooks.resolve, { - request: '/root/external-b/src/module.ts', - path: '/root/repo/node_modules/@s/b/src', + request: path.resolve(root, 'external-b/src/module.ts'), + path: path.resolve(root, 'repo/node_modules/@s/b/src'), context: { issuer: false, }, }, - 'resolve /root/external-b/src/module.ts in /root/repo/node_modules/@s/b', + `resolve ${path.resolve( + root, + 'external-b/src/module.ts', + )} in ${path.resolve(root, 'repo/node_modules/@s/b')}`, 'some-context', callbackB, ); diff --git a/packages/techdocs-common/src/stages/publish/helpers.test.ts b/packages/techdocs-common/src/stages/publish/helpers.test.ts index 3b01f5ac43..1fae66f3d2 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.test.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.test.ts @@ -14,6 +14,8 @@ * limitations under the License. */ import mockFs from 'mock-fs'; +import * as os from 'os'; +import * as path from 'path'; import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; describe('getHeadersForFileExtension', () => { @@ -39,9 +41,11 @@ describe('getHeadersForFileExtension', () => { }); describe('getFileTreeRecursively', () => { + const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; + beforeEach(() => { mockFs({ - '/rootDir': { + [root]: { file1: '', subDirA: { file2: '', @@ -57,9 +61,9 @@ describe('getFileTreeRecursively', () => { }); it('returns complete file tree of a path', async () => { - const fileList = await getFileTreeRecursively('/rootDir'); + const fileList = await getFileTreeRecursively(root); expect(fileList.length).toBe(2); - expect(fileList).toContain('/rootDir/file1'); - expect(fileList).toContain('/rootDir/subDirA/file2'); + expect(fileList).toContain(path.resolve(root, 'file1')); + expect(fileList).toContain(path.resolve(root, 'subDirA/file2')); }); }); From 5118cb472fa37d12583d9f3c840452ace7d31977 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 16:16:18 +0100 Subject: [PATCH 52/80] test(backend-common/git): Adding tests for all the git helpers in backend common --- packages/backend-common/src/scm/git.test.ts | 321 ++++++++++++++++++++ packages/backend-common/src/scm/git.ts | 50 ++- 2 files changed, 340 insertions(+), 31 deletions(-) create mode 100644 packages/backend-common/src/scm/git.test.ts diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts new file mode 100644 index 0000000000..7c38eafa0c --- /dev/null +++ b/packages/backend-common/src/scm/git.test.ts @@ -0,0 +1,321 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +jest.mock('isomorphic-git'); +jest.mock('isomorphic-git/http/node'); +jest.mock('fs-extra'); + +import * as isomorphic from 'isomorphic-git'; +import * as Git from './git'; +import http from 'isomorphic-git/http/node'; +import fs from 'fs-extra'; + +describe('Git', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + describe('add', () => { + it('should call isomorphic-git add with the correct arguments', async () => { + const git = Git.fromAuth({}); + const dir = 'mockdirectory'; + const filepath = 'mockfile/path'; + + await git.add({ dir, filepath }); + + expect(isomorphic.add).toHaveBeenCalledWith({ + fs, + dir, + filepath, + }); + }); + }); + + describe('addRemote', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const git = Git.fromAuth({}); + const dir = 'mockdirectory'; + const remoteName = 'origin'; + const url = 'git@github.com/something/sads'; + + await git.addRemote({ dir, remoteName, url }); + + expect(isomorphic.addRemote).toHaveBeenCalledWith({ + fs, + dir, + remote: remoteName, + url, + }); + }); + }); + + describe('commit', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const git = Git.fromAuth({}); + const dir = 'mockdirectory'; + const message = 'Inital Commit'; + const author = { + name: 'author', + email: 'test@backstage.io', + }; + const committer = { + name: 'comitter', + email: 'test@backstage.io', + }; + + await git.commit({ dir, message, author, committer }); + + expect(isomorphic.commit).toHaveBeenCalledWith({ + fs, + dir, + message, + author, + committer, + }); + }); + }); + + describe('clone', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const url = 'http://github.com/some/repo'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.clone({ url, dir }); + + expect(isomorphic.clone).toHaveBeenCalledWith({ + fs, + http, + url, + dir, + singleBranch: true, + depth: 1, + onProgress: expect.any(Function), + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onAuth: expect.any(Function), + }); + }); + it('should pass a function that returns the authorization as the onAuth handler', async () => { + const url = 'http://github.com/some/repo'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.clone({ url, dir }); + + const { onAuth } = ((isomorphic.clone as unknown) as jest.Mock< + typeof isomorphic['clone'] + >).mock.calls[0][0]!; + + expect(onAuth()).toEqual(auth); + }); + }); + + describe('currentBranch', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const dir = '/some/mock/dir'; + const fullName = true; + const git = Git.fromAuth({}); + + await git.currentBranch({ dir, fullName }); + + expect(isomorphic.currentBranch).toHaveBeenCalledWith({ + fs, + dir, + fullname: true, + }); + + await git.currentBranch({ dir }); + + expect(isomorphic.currentBranch).toHaveBeenCalledWith({ + fs, + dir, + fullname: false, + }); + }); + }); + + describe('fetch', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const remote = 'http://github.com/some/repo'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.fetch({ remote, dir }); + + expect(isomorphic.fetch).toHaveBeenCalledWith({ + fs, + http, + remote, + dir, + onProgress: expect.any(Function), + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onAuth: expect.any(Function), + }); + }); + it('should pass a function that returns the authorization as the onAuth handler', async () => { + const remote = 'http://github.com/some/repo'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.fetch({ remote, dir }); + + const { onAuth } = ((isomorphic.fetch as unknown) as jest.Mock< + typeof isomorphic['fetch'] + >).mock.calls[0][0]!; + + expect(onAuth()).toEqual(auth); + }); + }); + + describe('init', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const dir = '/some/mock/dir'; + + const git = Git.fromAuth({}); + + await git.init({ dir }); + + expect(isomorphic.init).toHaveBeenCalledWith({ + fs, + dir, + }); + }); + }); + + describe('merge', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const dir = '/some/mock/dir'; + const author = { + name: 'author', + email: 'test@backstage.io', + }; + const committer = { + name: 'comitter', + email: 'test@backstage.io', + }; + const headBranch = 'master'; + const baseBranch = 'production'; + + const git = Git.fromAuth({}); + + await git.merge({ dir, headBranch, baseBranch, author, committer }); + + expect(isomorphic.merge).toHaveBeenCalledWith({ + fs, + dir, + ours: baseBranch, + theirs: headBranch, + author, + committer, + }); + }); + }); + + describe('push', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const remoteName = 'origin'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.push({ dir, remoteName }); + + expect(isomorphic.push).toHaveBeenCalledWith({ + fs, + http, + remote: remoteName, + dir, + onProgress: expect.any(Function), + headers: { + 'user-agent': 'git/@isomorphic-git', + }, + onAuth: expect.any(Function), + }); + }); + it('should pass a function that returns the authorization as the onAuth handler', async () => { + const remoteName = 'origin'; + const dir = '/some/mock/dir'; + const auth = { + username: 'blob', + password: 'hunter2', + }; + const git = Git.fromAuth(auth); + + await git.push({ remoteName, dir }); + + const { onAuth } = ((isomorphic.push as unknown) as jest.Mock< + typeof isomorphic['push'] + >).mock.calls[0][0]!; + + expect(onAuth()).toEqual(auth); + }); + }); + + describe('readCommit', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const dir = '/some/mock/dir'; + const sha = 'as43bd7'; + + const git = Git.fromAuth({}); + + await git.readCommit({ dir, sha }); + + expect(isomorphic.readCommit).toHaveBeenCalledWith({ + fs, + dir, + oid: sha, + }); + }); + }); + + describe('resolveRef', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const dir = '/some/mock/dir'; + const ref = 'as43bd7'; + + const git = Git.fromAuth({}); + + await git.resolveRef({ dir, ref }); + + expect(isomorphic.resolveRef).toHaveBeenCalledWith({ + fs, + dir, + ref, + }); + }); + }); +}); diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 871a623b19..5d3f95d42c 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import git from 'isomorphic-git'; +import git, { ProgressCallback } from 'isomorphic-git'; import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; import { Logger } from 'winston'; @@ -85,19 +85,11 @@ class SCM { dir, singleBranch: true, depth: 1, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.info(`status={${event.phase},total={${total}}}`); - }, + onProgress: this.onProgressHandler, headers: { 'user-agent': 'git/@isomorphic-git', }, - onAuth: () => ({ - username: this.config.username, - password: this.config.password, - }), + onAuth: this.onAuth, }); } @@ -118,19 +110,11 @@ class SCM { http, dir, remote: remoteValue, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.info(`status={${event.phase},total={${total}}}`); - }, + onProgress: this.onProgressHandler, headers: { 'user-agent': 'git/@isomorphic-git', }, - onAuth: () => ({ - username: this.config.username, - password: this.config.password, - }), + onAuth: this.onAuth, }); } @@ -179,20 +163,12 @@ class SCM { fs, dir, http, - onProgress: event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.info(`status={${event.phase},total={${total}}}`); - }, + onProgress: this.onProgressHandler, headers: { 'user-agent': 'git/@isomorphic-git', }, remote: remoteName, - onAuth: () => ({ - username: this.config.username, - password: this.config.password, - }), + onAuth: this.onAuth, }); } @@ -205,6 +181,18 @@ class SCM { async resolveRef({ dir, ref }: { dir: string; ref: string }) { return git.resolveRef({ fs, dir, ref }); } + + private onAuth = () => ({ + username: this.config.username, + password: this.config.password, + }); + + private onProgressHandler: ProgressCallback = event => { + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + this.config.logger?.info(`status={${event.phase},total={${total}}}`); + }; } // TODO(blam): This could potentially become something like for URL From 8022655e0bf4cedfd088aae49fd9dee5bc8a4520 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 16:42:11 +0100 Subject: [PATCH 53/80] chore: removing the dependency on the azure preparer for nodegit --- .../scaffolder/stages/prepare/azure.test.ts | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts index 4d19069b5e..39efd1c62a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts @@ -14,11 +14,6 @@ * limitations under the License. */ -const mocks = { - Clone: { clone: jest.fn() }, - CheckoutOptions: jest.fn(() => {}), -}; -jest.doMock('nodegit', () => mocks); jest.doMock('fs-extra', () => ({ promises: { mkdtemp: jest.fn(dir => `${dir}-static`), @@ -30,10 +25,16 @@ import { TemplateEntityV1alpha1, LOCATION_ANNOTATION, } from '@backstage/catalog-model'; -import { getVoidLogger } from '@backstage/backend-common'; +import { getVoidLogger, Git } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; describe('AzurePreparer', () => { + const mockGitClient = { + clone: jest.fn(), + }; + + jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); + let mockEntity: TemplateEntityV1alpha1; beforeEach(() => { jest.clearAllMocks(); @@ -77,18 +78,7 @@ describe('AzurePreparer', () => { }; }); - it('calls the clone command with the correct arguments for a repository', async () => { - const preparer = new AzurePreparer(new ConfigReader({})); - await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - expect.any(String), - {}, - ); - }); - - it('calls the clone command with the correct arguments if an access token is provided for a repository', async () => { + it('initializes git client with the correct arguments if an access token is provided for a repository', async () => { const preparer = new AzurePreparer( new ConfigReader({ scaffolder: { @@ -100,36 +90,44 @@ describe('AzurePreparer', () => { }, }), ); + const logger = getVoidLogger(); + await preparer.prepare(mockEntity, { logger }); + + expect(Git.fromAuth).toHaveBeenCalledWith({ + username: 'notempty', + password: 'fake-token', + logger, + }); + }); + it('calls the clone command with the correct arguments for a repository', async () => { + const preparer = new AzurePreparer(new ConfigReader({})); + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - expect.any(String), - { - fetchOpts: { - callbacks: { - credentials: expect.anything(), - }, - }, - }, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: + 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', + dir: expect.any(String), + }); }); it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new AzurePreparer(new ConfigReader({})); delete mockEntity.spec.path; + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - expect.any(String), - {}, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: + 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', + dir: expect.any(String), + }); }); it('return the temp directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(new ConfigReader({})); mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, { logger: getVoidLogger(), }); @@ -142,6 +140,7 @@ describe('AzurePreparer', () => { it('return the working directory with the path to the folder if it is specified', async () => { const preparer = new AzurePreparer(new ConfigReader({})); mockEntity.spec.path = './template/test/1/2/3'; + const response = await preparer.prepare(mockEntity, { logger: getVoidLogger(), workingDirectory: '/workDir', From 9a9604408c1e65163691929a881145114d27c05e Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 16:48:02 +0100 Subject: [PATCH 54/80] chore: removing dependency for githubn preparer --- .../scaffolder/stages/prepare/github.test.ts | 64 ++++++++----------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts index 86a870330e..aa040bfe58 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts @@ -14,11 +14,6 @@ * limitations under the License. */ -const mocks = { - Clone: { clone: jest.fn() }, - CheckoutOptions: jest.fn(() => {}), -}; -jest.doMock('nodegit', () => mocks); jest.doMock('fs-extra', () => ({ promises: { mkdtemp: jest.fn(dir => `${dir}-static`), @@ -30,10 +25,16 @@ import { TemplateEntityV1alpha1, LOCATION_ANNOTATION, } from '@backstage/catalog-model'; -import { getVoidLogger } from '@backstage/backend-common'; +import { getVoidLogger, Git } from '@backstage/backend-common'; describe('GitHubPreparer', () => { let mockEntity: TemplateEntityV1alpha1; + const mockGitClient = { + clone: jest.fn(), + }; + + jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); + beforeEach(() => { jest.clearAllMocks(); mockEntity = { @@ -77,28 +78,24 @@ describe('GitHubPreparer', () => { }); it('calls the clone command with the correct arguments for a repository', async () => { const preparer = new GithubPreparer(); + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://github.com/benjdlambert/backstage-graphql-template', - expect.any(String), - { - checkoutBranch: 'master', - }, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: 'https://github.com/benjdlambert/backstage-graphql-template', + dir: expect.any(String), + }); }); it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { const preparer = new GithubPreparer(); delete mockEntity.spec.path; + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://github.com/benjdlambert/backstage-graphql-template', - expect.any(String), - { - checkoutBranch: 'master', - }, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: 'https://github.com/benjdlambert/backstage-graphql-template', + dir: expect.any(String), + }); }); it('return the temp directory with the path to the folder if it is specified', async () => { @@ -128,19 +125,14 @@ describe('GitHubPreparer', () => { it('calls the clone command with the token when provided', async () => { const preparer = new GithubPreparer({ token: 'abc' }); - await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://github.com/benjdlambert/backstage-graphql-template', - expect.any(String), - { - checkoutBranch: 'master', - fetchOpts: { - callbacks: { - credentials: expect.any(Function), - }, - }, - }, - ); + const logger = getVoidLogger(); + + await preparer.prepare(mockEntity, { logger }); + + expect(Git.fromAuth).toHaveBeenCalledWith({ + logger, + username: 'abc', + password: 'x-oauth-basic', + }); }); }); From 84e937e32448951f5aa2bef884cc38def86360a4 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:08:53 +0100 Subject: [PATCH 55/80] chore: fix gitlab preparer tests to remove the node-git dependency --- .../scaffolder/stages/prepare/gitlab.test.ts | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts index 8712507026..8dad349a13 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const mocks = { - Clone: { clone: jest.fn() }, - CheckoutOptions: jest.fn(() => {}), -}; -jest.doMock('nodegit', () => mocks); jest.doMock('fs-extra', () => ({ promises: { mkdtemp: jest.fn(dir => `${dir}-static`), @@ -30,7 +25,7 @@ import { LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; -import { getVoidLogger } from '@backstage/backend-common'; +import { getVoidLogger, Git } from '@backstage/backend-common'; const mockEntityWithProtocol = (protocol: string): TemplateEntityV1alpha1 => ({ apiVersion: 'backstage.io/v1alpha1', @@ -72,6 +67,12 @@ const mockEntityWithProtocol = (protocol: string): TemplateEntityV1alpha1 => ({ describe('GitLabPreparer', () => { let mockEntity: TemplateEntityV1alpha1; + const mockGitClient = { + clone: jest.fn(), + }; + + jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); + beforeEach(() => { jest.clearAllMocks(); }); @@ -80,13 +81,13 @@ describe('GitLabPreparer', () => { it(`calls the clone command with the correct arguments for a repository using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity = mockEntityWithProtocol(protocol); + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://gitlab.com/benjdlambert/backstage-graphql-template', - expect.any(String), - {}, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: 'https://gitlab.com/benjdlambert/backstage-graphql-template', + dir: expect.any(String), + }); }); it(`calls the clone command with the correct arguments if an access token is provided in integrations for a repository using the ${protocol} protocol`, async () => { @@ -103,19 +104,15 @@ describe('GitLabPreparer', () => { }), ); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://gitlab.com/benjdlambert/backstage-graphql-template', - expect.any(String), - { - fetchOpts: { - callbacks: { - credentials: expect.anything(), - }, - }, - }, - ); + const logger = getVoidLogger(); + + await preparer.prepare(mockEntity, { logger }); + + expect(Git.fromAuth).toHaveBeenCalledWith({ + logger, + username: 'oauth2', + password: 'fake-token', + }); }); it(`calls the clone command with the correct arguments if an access token is provided in scaffolder for a repository using the ${protocol} protocol`, async () => { @@ -127,32 +124,28 @@ describe('GitLabPreparer', () => { }), ); mockEntity = mockEntityWithProtocol(protocol); - await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://gitlab.com/benjdlambert/backstage-graphql-template', - expect.any(String), - { - fetchOpts: { - callbacks: { - credentials: expect.anything(), - }, - }, - }, - ); + const logger = getVoidLogger(); + + await preparer.prepare(mockEntity, { logger }); + + expect(Git.fromAuth).toHaveBeenCalledWith({ + logger, + username: 'oauth2', + password: 'fake-token', + }); }); it(`calls the clone command with the correct arguments for a repository when no path is provided using the ${protocol} protocol`, async () => { const preparer = new GitlabPreparer(new ConfigReader({})); mockEntity = mockEntityWithProtocol(protocol); delete mockEntity.spec.path; + await preparer.prepare(mockEntity, { logger: getVoidLogger() }); - expect(mocks.Clone.clone).toHaveBeenNthCalledWith( - 1, - 'https://gitlab.com/benjdlambert/backstage-graphql-template', - expect.any(String), - {}, - ); + + expect(mockGitClient.clone).toHaveBeenCalledWith({ + url: 'https://gitlab.com/benjdlambert/backstage-graphql-template', + dir: expect.any(String), + }); }); it(`return the temp directory with the path to the folder if it is specified using the ${protocol} protocol`, async () => { From 438948f9bbc57d85b45383a57f6180bc31b90e2a Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:23:39 +0100 Subject: [PATCH 56/80] chore: remove nodegit dependency on azure publisher --- .../scaffolder/stages/publish/azure.test.ts | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts index 9ea7d2de5f..f1e0cd6175 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts @@ -13,17 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -jest.mock('nodegit'); -jest.mock('azure-devops-node-api/GitApi'); -jest.mock('azure-devops-node-api/interfaces/GitInterfaces'); -jest.mock('./helpers', () => ({ - pushToRemoteUserPass: jest.fn(), -})); +jest.mock('./helpers'); import { AzurePublisher } from './azure'; import { GitApi } from 'azure-devops-node-api/GitApi'; -import { pushToRemoteUserPass } from './helpers'; +import * as helpers from './helpers'; +import { getVoidLogger } from '@backstage/backend-common'; const { mockGitApi } = require('azure-devops-node-api/GitApi') as { mockGitApi: { @@ -33,6 +28,7 @@ const { mockGitApi } = require('azure-devops-node-api/GitApi') as { describe('Azure Publisher', () => { const publisher = new AzurePublisher(new GitApi('', []), 'fake-token'); + const logger = getVoidLogger(); beforeEach(() => { jest.clearAllMocks(); @@ -50,6 +46,7 @@ describe('Azure Publisher', () => { owner: 'bob', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -63,12 +60,12 @@ describe('Azure Publisher', () => { }, 'project', ); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://dev.azure.com/organization/project/_git/repo', - 'notempty', - 'fake-token', - ); + expect(helpers.initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + auth: { username: 'notempty', password: 'fake-token' }, + logger, + }); }); }); }); From 783ac57ce7b344a0a04b0cccb03c7efed360a915 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:33:04 +0100 Subject: [PATCH 57/80] chore: removing nodegit dependency on the github publisher --- .../scaffolder/stages/publish/github.test.ts | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts index cda64faf25..22f1cd3172 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts @@ -15,10 +15,7 @@ */ jest.mock('@octokit/rest'); -jest.mock('nodegit'); -jest.mock('./helpers', () => ({ - pushToRemoteUserPass: jest.fn(), -})); +jest.mock('./helpers'); import { Octokit } from '@octokit/rest'; import { @@ -27,7 +24,8 @@ import { UsersGetByUsernameResponseData, } from '@octokit/types'; import { GithubPublisher } from './github'; -import { pushToRemoteUserPass } from './helpers'; +import { initRepoAndPush } from './helpers'; +import { getVoidLogger } from '@backstage/backend-common'; const { mockGithubClient } = require('@octokit/rest') as { mockGithubClient: { @@ -38,6 +36,7 @@ const { mockGithubClient } = require('@octokit/rest') as { }; describe('GitHub Publisher', () => { + const logger = getVoidLogger(); beforeEach(() => { jest.clearAllMocks(); }); @@ -69,6 +68,7 @@ describe('GitHub Publisher', () => { access: 'blam/team', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -91,12 +91,12 @@ describe('GitHub Publisher', () => { repo: 'test', permission: 'admin', }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://github.com/backstage/backstage.git', - 'abc', - 'x-oauth-basic', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://github.com/backstage/backstage.git', + auth: { username: 'abc', password: 'x-oauth-basic' }, + logger, + }); }); it('should use octokit to create a repo in the authed user if the organisation property is not set', async () => { @@ -118,6 +118,7 @@ describe('GitHub Publisher', () => { access: 'blam', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -132,12 +133,13 @@ describe('GitHub Publisher', () => { private: false, }); expect(mockGithubClient.repos.addCollaborator).not.toHaveBeenCalled(); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://github.com/backstage/backstage.git', - 'abc', - 'x-oauth-basic', - ); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://github.com/backstage/backstage.git', + auth: { username: 'abc', password: 'x-oauth-basic' }, + logger, + }); }); }); @@ -161,6 +163,7 @@ describe('GitHub Publisher', () => { description: 'description', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -181,12 +184,12 @@ describe('GitHub Publisher', () => { username: 'bob', permission: 'admin', }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://github.com/backstage/backstage.git', - 'abc', - 'x-oauth-basic', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://github.com/backstage/backstage.git', + auth: { username: 'abc', password: 'x-oauth-basic' }, + logger, + }); }); }); @@ -216,6 +219,7 @@ describe('GitHub Publisher', () => { owner: 'bob', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -229,12 +233,12 @@ describe('GitHub Publisher', () => { private: true, visibility: 'internal', }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://github.com/backstage/backstage.git', - 'abc', - 'x-oauth-basic', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://github.com/backstage/backstage.git', + auth: { username: 'abc', password: 'x-oauth-basic' }, + logger, + }); }); }); @@ -263,6 +267,7 @@ describe('GitHub Publisher', () => { owner: 'bob', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ @@ -276,12 +281,12 @@ describe('GitHub Publisher', () => { name: 'test', private: true, }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'https://github.com/backstage/backstage.git', - 'abc', - 'x-oauth-basic', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'https://github.com/backstage/backstage.git', + auth: { username: 'abc', password: 'x-oauth-basic' }, + logger, + }); }); }); }); From 4311d59521f52e33691b113901991f8052448f48 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:37:11 +0100 Subject: [PATCH 58/80] chore: remove nodegit dependency from gitlab publisher --- .../scaffolder/stages/publish/gitlab.test.ts | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts index a87fa6c6d9..61113003d4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts @@ -16,14 +16,13 @@ jest.mock('nodegit'); jest.mock('@gitbeaker/node'); -jest.mock('./helpers', () => ({ - pushToRemoteUserPass: jest.fn(), -})); +jest.mock('./helpers'); import { GitlabPublisher } from './gitlab'; import { Gitlab as GitlabAPI } from '@gitbeaker/core'; import { Gitlab } from '@gitbeaker/node'; -import { pushToRemoteUserPass } from './helpers'; +import { initRepoAndPush } from './helpers'; +import { getVoidLogger } from '@backstage/backend-common'; const { mockGitlabClient } = require('@gitbeaker/node') as { mockGitlabClient: { @@ -34,6 +33,7 @@ const { mockGitlabClient } = require('@gitbeaker/node') as { }; describe('GitLab Publisher', () => { + const logger = getVoidLogger(); const publisher = new GitlabPublisher(new Gitlab({}), 'fake-token'); beforeEach(() => { @@ -56,6 +56,7 @@ describe('GitLab Publisher', () => { owner: 'bob', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ remoteUrl: 'mockclone' }); @@ -63,12 +64,12 @@ describe('GitLab Publisher', () => { namespace_id: 42, name: 'test', }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'mockclone', - 'oauth2', - 'fake-token', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'mockclone', + auth: { username: 'oauth2', password: 'fake-token' }, + logger, + }); }); it('should use gitbeaker to create a repo in the authed user if the namespace property is not set', async () => { @@ -86,6 +87,7 @@ describe('GitLab Publisher', () => { owner: 'bob', }, directory: '/tmp/test', + logger, }); expect(result).toEqual({ remoteUrl: 'mockclone' }); @@ -94,12 +96,12 @@ describe('GitLab Publisher', () => { namespace_id: 21, name: 'test', }); - expect(pushToRemoteUserPass).toHaveBeenCalledWith( - '/tmp/test', - 'mockclone', - 'oauth2', - 'fake-token', - ); + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: '/tmp/test', + remoteUrl: 'mockclone', + auth: { username: 'oauth2', password: 'fake-token' }, + logger, + }); }); }); }); From 5c6da874de80d0366c531a36b39fe7bb4b51db3e Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:38:52 +0100 Subject: [PATCH 59/80] chore: removing old helper tests --- .../scaffolder/stages/publish/helpers.test.ts | 112 ------------------ 1 file changed, 112 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.test.ts deleted file mode 100644 index 3a317adacd..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.test.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -jest.mock('nodegit'); -import * as NodeGit from 'nodegit'; -import { pushToRemoteCred } from './helpers'; - -const { - Repository, - mockRepo, - mockIndex, - Signature, - Remote, - mockRemote, - Cred, -} = require('nodegit') as { - Repository: jest.Mocked<{ init: any }>; - Signature: jest.Mocked<{ now: any }>; - Cred: jest.Mocked<{ userpassPlaintextNew: any }>; - Remote: jest.Mocked<{ create: any }>; - - mockIndex: jest.Mocked; - mockRepo: jest.Mocked; - mockRemote: jest.Mocked; -}; - -describe('pushToRemoteCred', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - const directory = '/tmp/test/dir'; - const remote = 'mockclone'; - const credentialsProvider = () => - NodeGit.Cred.userpassPlaintextNew('username', 'password'); - - it('should call init on the repo with the directory', async () => { - await pushToRemoteCred(directory, remote, credentialsProvider); - - expect(Repository.init).toHaveBeenCalledWith(directory, 0); - }); - - it('should call refresh index on the index and write the new files', async () => { - await pushToRemoteCred(directory, remote, credentialsProvider); - - expect(mockRepo.refreshIndex).toHaveBeenCalled(); - }); - - it('should call add all files and write', async () => { - await pushToRemoteCred(directory, remote, credentialsProvider); - - expect(mockIndex.addAll).toHaveBeenCalled(); - expect(mockIndex.write).toHaveBeenCalled(); - expect(mockIndex.writeTree).toHaveBeenCalled(); - }); - - it('should create a commit with on head with the right name and commiter', async () => { - const mockSignature = { mockSignature: 'bloblly' }; - Signature.now.mockReturnValue(mockSignature); - - await pushToRemoteCred(directory, remote, credentialsProvider); - - expect(Signature.now).toHaveBeenCalledTimes(2); - expect(Signature.now).toHaveBeenCalledWith( - 'Scaffolder', - 'scaffolder@backstage.io', - ); - - expect(mockRepo.createCommit).toHaveBeenCalledWith( - 'HEAD', - mockSignature, - mockSignature, - 'initial commit', - 'mockoid', - [], - ); - }); - - it('creates a remote with the repo and remote', async () => { - await pushToRemoteCred(directory, remote, credentialsProvider); - - expect(Remote.create).toHaveBeenCalledWith(mockRepo, 'origin', 'mockclone'); - }); - - it('shoud push to the remote repo', async () => { - await pushToRemoteCred(directory, remote, credentialsProvider); - - const [remotes, { callbacks }] = mockRemote.push.mock - .calls[0] as NodeGit.PushOptions[]; - - expect(remotes).toEqual(['refs/heads/master:refs/heads/master']); - - callbacks?.credentials?.(); - - expect(Cred.userpassPlaintextNew).toHaveBeenCalledWith( - 'username', - 'password', - ); - }); -}); From e203b56d13123037f71b4ed9e6b49070cb2a943b Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 28 Dec 2020 17:41:25 +0100 Subject: [PATCH 60/80] chore: fix typescript issues with scaffolder-backend now the publishers require a logger :) --- plugins/scaffolder-backend/src/service/router.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index ac3b1c80ec..ffd4d6487c 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -159,6 +159,7 @@ export async function createRouter( const result = await publisher.publish({ values: ctx.values, directory: ctx.resultDir, + logger: ctx.logger, }); return result; }, From c91e4d6b0468eee3bf273487b4d3505c8ff7c4f9 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 21 Dec 2020 23:09:41 +0100 Subject: [PATCH 61/80] techdocs: Use @backstage/integration for scm tokens and request options --- packages/techdocs-common/package.json | 1 + .../techdocs-common/src/default-branch.ts | 80 ++++---------- packages/techdocs-common/src/git-auth.ts | 101 ++++++++---------- packages/techdocs-common/src/helpers.ts | 19 +++- .../src/stages/prepare/commonGit.test.ts | 9 +- .../src/stages/prepare/commonGit.ts | 15 ++- .../src/stages/prepare/dir.test.ts | 11 +- .../techdocs-common/src/stages/prepare/dir.ts | 11 +- .../src/stages/prepare/preparers.ts | 7 +- .../techdocs-common/src/stages/prepare/url.ts | 4 +- .../src/DocsBuilder/builder.ts | 11 +- .../techdocs-backend/src/service/router.ts | 1 + .../src/service/standaloneServer.ts | 2 +- 13 files changed, 127 insertions(+), 145 deletions(-) diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index 68debc2448..20d0f68a98 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -39,6 +39,7 @@ "@backstage/backend-common": "^0.4.1", "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", + "@backstage/integration": "^0.1.4", "@google-cloud/storage": "^5.6.0", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", diff --git a/packages/techdocs-common/src/default-branch.ts b/packages/techdocs-common/src/default-branch.ts index 1090fcb3d3..7dd460a9fe 100644 --- a/packages/techdocs-common/src/default-branch.ts +++ b/packages/techdocs-common/src/default-branch.ts @@ -16,13 +16,17 @@ import fetch from 'cross-fetch'; import parseGitUrl from 'git-url-parse'; import { Config } from '@backstage/config'; -import { getRootLogger, loadBackendConfig } from '@backstage/backend-common'; import { - getAzureHostToken, + getGitHubRequestOptions, + getGitLabRequestOptions, + getAzureRequestOptions, +} from '@backstage/integration'; +import { getGitHost, - getGithubHostToken, - getGitlabHostToken, getGitRepoType, + getGitHubIntegrationConfig, + getGitLabIntegrationConfig, + getAzureIntegrationConfig, } from './git-auth'; interface IGitlabBranch { @@ -86,62 +90,15 @@ function getAzureApiUrl(url: string): URL { ); } -function getGithubRequestOptions(config: Config, host: string): RequestInit { - const headers: HeadersInit = { - Accept: 'application/vnd.github.v3.raw', - }; - - const token = getGithubHostToken(config, host); - - if (token) { - headers.Authorization = `token ${token}`; - } - - return { - headers, - }; -} - -function getGitlabRequestOptions(config: Config, host: string): RequestInit { - const headers: HeadersInit = { - 'PRIVATE-TOKEN': '', - }; - - const token = getGitlabHostToken(config, host); - if (token) { - headers['PRIVATE-TOKEN'] = token; - } - - return { - headers, - }; -} - -function getAzureRequestOptions(config: Config, host: string): RequestInit { - const headers: HeadersInit = {}; - - const token = getAzureHostToken(config, host); - - if (token !== '') { - headers.Authorization = `Basic ${Buffer.from(`:${token}`, 'utf8').toString( - 'base64', - )}`; - } - - const requestOptions: RequestInit = { - headers, - }; - - return requestOptions; -} - async function getGithubDefaultBranch( repositoryUrl: string, config: Config, ): Promise { const path = getGithubApiUrl(config, repositoryUrl).toString(); const host = getGitHost(repositoryUrl); - const options = getGithubRequestOptions(config, host); + + const integrationConfig = getGitHubIntegrationConfig(config, host); + const options = getGitHubRequestOptions(integrationConfig); try { const raw = await fetch(path, options); @@ -169,9 +126,10 @@ async function getGitlabDefaultBranch( config: Config, ): Promise { const path = getGitlabApiUrl(repositoryUrl).toString(); + const host = getGitHost(repositoryUrl); - const gitlabHost = getGitHost(repositoryUrl); - const options = getGitlabRequestOptions(config, gitlabHost); + const integrationConfig = getGitLabIntegrationConfig(config, host); + const options = getGitLabRequestOptions(integrationConfig); try { const raw = await fetch(path, options); @@ -203,7 +161,9 @@ async function getAzureDefaultBranch( ): Promise { const path = getAzureApiUrl(repositoryUrl).toString(); const host = getGitHost(repositoryUrl); - const options = getAzureRequestOptions(config, host); + + const integrationConfig = getAzureIntegrationConfig(config, host); + const options = getAzureRequestOptions(integrationConfig); try { const urlResponse = await fetch(path, options); @@ -235,12 +195,8 @@ async function getAzureDefaultBranch( export const getDefaultBranch = async ( repositoryUrl: string, + config: Config, ): Promise => { - // TODO(Rugvip): Config should not be loaded here, pass it in instead - const config = await loadBackendConfig({ - logger: getRootLogger(), - argv: process.argv, - }); const type = getGitRepoType(repositoryUrl); try { diff --git a/packages/techdocs-common/src/git-auth.ts b/packages/techdocs-common/src/git-auth.ts index b580a6f05b..41a33340af 100644 --- a/packages/techdocs-common/src/git-auth.ts +++ b/packages/techdocs-common/src/git-auth.ts @@ -15,7 +15,14 @@ */ import parseGitUrl from 'git-url-parse'; import { Config } from '@backstage/config'; -import { getRootLogger, loadBackendConfig } from '@backstage/backend-common'; +import { + readGitHubIntegrationConfigs, + readGitLabIntegrationConfigs, + readAzureIntegrationConfigs, + GitHubIntegrationConfig, + GitLabIntegrationConfig, + AzureIntegrationConfig, +} from '@backstage/integration'; export function getGitHost(url: string): string { const { resource } = parseGitUrl(url); @@ -34,85 +41,67 @@ export function getGitRepoType(url: string): string { return type; } -export function getGithubHostToken( +export const getGitHubIntegrationConfig = ( config: Config, host: string, -): string | undefined { - const providerConfigs = - config.getOptionalConfigArray('integrations.github') ?? []; - - const hostConfig = providerConfigs.filter( - providerConfig => providerConfig.getOptionalString('host') === host, +): GitHubIntegrationConfig => { + const allGitHubConfigs = readGitHubIntegrationConfigs( + config.getOptionalConfigArray('integrations.github') ?? [], ); - const token = - hostConfig[0]?.getOptionalString('token') ?? - config.getOptionalString('catalog.processors.github.privateToken') ?? - config.getOptionalString('catalog.processors.githubApi.privateToken') ?? - process.env.GITHUB_TOKEN; + const gitHubIntegrationConfig = allGitHubConfigs.find(v => v.host === host); + if (!gitHubIntegrationConfig) { + throw new Error(`Unable to locate GitHub integration for the host ${host}`); + } + return gitHubIntegrationConfig; +}; - return token; -} - -export function getGitlabHostToken( +export const getGitLabIntegrationConfig = ( config: Config, host: string, -): string | undefined { - const providerConfigs = - config.getOptionalConfigArray('integrations.gitlab') ?? []; - - const hostConfig = providerConfigs.filter( - providerConfig => providerConfig.getOptionalString('host') === host, +): GitLabIntegrationConfig => { + const allGitLabConfigs = readGitLabIntegrationConfigs( + config.getOptionalConfigArray('integrations.gitlab') ?? [], ); - const token = - hostConfig[0]?.getOptionalString('token') ?? - config.getOptionalString('catalog.processors.gitlab.privateToken') ?? - config.getOptionalString('catalog.processors.gitlabApi.privateToken') ?? - process.env.GITLAB_TOKEN; + const gitLabIntegrationConfig = allGitLabConfigs.find(v => v.host === host); + if (!gitLabIntegrationConfig) { + throw new Error(`Unable to locate GitLab integration for the host ${host}`); + } + return gitLabIntegrationConfig; +}; - return token; -} - -export function getAzureHostToken( +export const getAzureIntegrationConfig = ( config: Config, host: string, -): string | undefined { - const providerConfigs = - config.getOptionalConfigArray('integrations.azure') ?? []; - - const hostConfig = providerConfigs.filter( - providerConfig => providerConfig.getOptionalString('host') === host, +): AzureIntegrationConfig => { + const allAzureIntegrationConfig = readAzureIntegrationConfigs( + config.getOptionalConfigArray('integrations.azure') ?? [], ); - const token = - hostConfig[0]?.getOptionalString('token') ?? - config.getOptionalString('catalog.processors.azureApi.privateToken') ?? - process.env.AZURE_TOKEN; - - return token; -} + const azureIntegrationConfig = allAzureIntegrationConfig.find( + v => v.host === host, + ); + if (!azureIntegrationConfig) { + throw new Error(`Unable to locate Azure integration for the host ${host}`); + } + return azureIntegrationConfig; +}; export const getTokenForGitRepo = async ( repositoryUrl: string, + config: Config, ): Promise => { - // TODO(Rugvip): Config should not be loaded here, pass it in instead - const config = await loadBackendConfig({ - logger: getRootLogger(), - argv: process.argv, - }); - const host = getGitHost(repositoryUrl); const type = getGitRepoType(repositoryUrl); try { switch (type) { case 'github': - return getGithubHostToken(config, host); + return getGitHubIntegrationConfig(config, host).token; case 'gitlab': - return getGitlabHostToken(config, host); + return getGitLabIntegrationConfig(config, host).token; case 'azure/api': - return getAzureHostToken(config, host); - + return getAzureIntegrationConfig(config, host).token; default: - throw new Error('Failed to get repository type'); + throw new Error('Failed to get reository type'); } } catch (error) { throw error; diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts index e08d58d58e..ab1e3e615f 100644 --- a/packages/techdocs-common/src/helpers.ts +++ b/packages/techdocs-common/src/helpers.ts @@ -19,10 +19,11 @@ import path from 'path'; import parseGitUrl from 'git-url-parse'; import NodeGit, { Clone, Repository } from 'nodegit'; import fs from 'fs-extra'; +import { InputError, UrlReader } from '@backstage/backend-common'; +import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; import { getDefaultBranch } from './default-branch'; import { getGitRepoType, getTokenForGitRepo } from './git-auth'; -import { Entity } from '@backstage/catalog-model'; -import { InputError, UrlReader } from '@backstage/backend-common'; import { RemoteProtocol } from './stages/prepare/types'; import { Logger } from 'winston'; @@ -94,6 +95,7 @@ export const getLocationForEntity = ( export const getGitRepositoryTempFolder = async ( repositoryUrl: string, + config: Config, ): Promise => { const parsedGitLocation = parseGitUrl(repositoryUrl); // removes .git from git location path @@ -102,6 +104,7 @@ export const getGitRepositoryTempFolder = async ( if (!parsedGitLocation.ref) { parsedGitLocation.ref = await getDefaultBranch( parsedGitLocation.toString('https'), + config, ); } @@ -118,11 +121,12 @@ export const getGitRepositoryTempFolder = async ( export const checkoutGitRepository = async ( repoUrl: string, + config: Config, logger: Logger, ): Promise => { const parsedGitLocation = parseGitUrl(repoUrl); - const repositoryTmpPath = await getGitRepositoryTempFolder(repoUrl); - const token = await getTokenForGitRepo(repoUrl); + const repositoryTmpPath = await getGitRepositoryTempFolder(repoUrl, config); + const token = await getTokenForGitRepo(repoUrl, config); if (fs.existsSync(repositoryTmpPath)) { try { @@ -170,9 +174,14 @@ export const checkoutGitRepository = async ( export const getLastCommitTimestamp = async ( repositoryUrl: string, + config: Config, logger: Logger, ): Promise => { - const repositoryLocation = await checkoutGitRepository(repositoryUrl, logger); + const repositoryLocation = await checkoutGitRepository( + repositoryUrl, + config, + logger, + ); const repository = await Repository.open(repositoryLocation); const commit = await repository.getReferenceCommit('HEAD'); diff --git a/packages/techdocs-common/src/stages/prepare/commonGit.test.ts b/packages/techdocs-common/src/stages/prepare/commonGit.test.ts index a4240514b5..704cd23daa 100644 --- a/packages/techdocs-common/src/stages/prepare/commonGit.test.ts +++ b/packages/techdocs-common/src/stages/prepare/commonGit.test.ts @@ -15,6 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import { CommonGitPreparer } from './commonGit'; import { checkoutGitRepository } from '../../helpers'; @@ -43,11 +44,13 @@ const createMockEntity = (annotations = {}) => { }; }; +const mockConfig = new ConfigReader({}); + const logger = getVoidLogger(); describe('commonGit preparer', () => { it('should prepare temp docs path from github repo', async () => { - const preparer = new CommonGitPreparer(logger); + const preparer = new CommonGitPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/techdocs-ref': @@ -62,7 +65,7 @@ describe('commonGit preparer', () => { }); it('should prepare temp docs path from gitlab repo', async () => { - const preparer = new CommonGitPreparer(logger); + const preparer = new CommonGitPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/techdocs-ref': @@ -77,7 +80,7 @@ describe('commonGit preparer', () => { }); it('should prepare temp docs path from azure repo', async () => { - const preparer = new CommonGitPreparer(logger); + const preparer = new CommonGitPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/techdocs-ref': diff --git a/packages/techdocs-common/src/stages/prepare/commonGit.ts b/packages/techdocs-common/src/stages/prepare/commonGit.ts index d79373fba3..7eac07d76f 100644 --- a/packages/techdocs-common/src/stages/prepare/commonGit.ts +++ b/packages/techdocs-common/src/stages/prepare/commonGit.ts @@ -14,17 +14,20 @@ * limitations under the License. */ import path from 'path'; -import { Entity } from '@backstage/catalog-model'; -import { PreparerBase } from './types'; import parseGitUrl from 'git-url-parse'; +import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { PreparerBase } from './types'; import { parseReferenceAnnotation, checkoutGitRepository } from '../../helpers'; import { Logger } from 'winston'; export class CommonGitPreparer implements PreparerBase { + private readonly config: Config; private readonly logger: Logger; - constructor(logger: Logger) { + constructor(config: Config, logger: Logger) { + this.config = config; this.logger = logger; } @@ -35,7 +38,11 @@ export class CommonGitPreparer implements PreparerBase { ); try { - const repoPath = await checkoutGitRepository(target, this.logger); + const repoPath = await checkoutGitRepository( + target, + this.config, + this.logger, + ); const parsedGitLocation = parseGitUrl(target); return path.join(repoPath, parsedGitLocation.filepath); diff --git a/packages/techdocs-common/src/stages/prepare/dir.test.ts b/packages/techdocs-common/src/stages/prepare/dir.test.ts index 5b51f1f46d..d082b1367b 100644 --- a/packages/techdocs-common/src/stages/prepare/dir.test.ts +++ b/packages/techdocs-common/src/stages/prepare/dir.test.ts @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { DirectoryPreparer } from './dir'; import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { DirectoryPreparer } from './dir'; import { checkoutGitRepository } from '../../helpers'; function normalizePath(path: string) { @@ -44,9 +45,11 @@ const createMockEntity = (annotations: {}) => { }; }; +const mockConfig = new ConfigReader({}); + describe('directory preparer', () => { it('should merge managed-by-location and techdocs-ref when techdocs-ref is relative', async () => { - const directoryPreparer = new DirectoryPreparer(logger); + const directoryPreparer = new DirectoryPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/managed-by-location': @@ -60,7 +63,7 @@ describe('directory preparer', () => { }); it('should merge managed-by-location and techdocs-ref when techdocs-ref is absolute', async () => { - const directoryPreparer = new DirectoryPreparer(logger); + const directoryPreparer = new DirectoryPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/managed-by-location': @@ -74,7 +77,7 @@ describe('directory preparer', () => { }); it('should merge managed-by-location and techdocs-ref when managed-by-location is a git repository', async () => { - const directoryPreparer = new DirectoryPreparer(logger); + const directoryPreparer = new DirectoryPreparer(mockConfig, logger); const mockEntity = createMockEntity({ 'backstage.io/managed-by-location': diff --git a/packages/techdocs-common/src/stages/prepare/dir.ts b/packages/techdocs-common/src/stages/prepare/dir.ts index 3485ecb5dd..537f670edc 100644 --- a/packages/techdocs-common/src/stages/prepare/dir.ts +++ b/packages/techdocs-common/src/stages/prepare/dir.ts @@ -15,6 +15,7 @@ */ import { PreparerBase } from './types'; import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; import path from 'path'; import { parseReferenceAnnotation, checkoutGitRepository } from '../../helpers'; import { InputError } from '@backstage/backend-common'; @@ -22,9 +23,11 @@ import parseGitUrl from 'git-url-parse'; import { Logger } from 'winston'; export class DirectoryPreparer implements PreparerBase { + private readonly config: Config; private readonly logger: Logger; - constructor(logger: Logger) { + constructor(config: Config, logger: Logger) { + this.config = config; this.logger = logger; } @@ -43,7 +46,11 @@ export class DirectoryPreparer implements PreparerBase { case 'url': case 'azure/api': { const parsedGitLocation = parseGitUrl(target); - const repoLocation = await checkoutGitRepository(target, this.logger); + const repoLocation = await checkoutGitRepository( + target, + this.config, + this.logger, + ); return path.dirname( path.join(repoLocation, parsedGitLocation.filepath), diff --git a/packages/techdocs-common/src/stages/prepare/preparers.ts b/packages/techdocs-common/src/stages/prepare/preparers.ts index 4a2d60eb31..4625d7b0e4 100644 --- a/packages/techdocs-common/src/stages/prepare/preparers.ts +++ b/packages/techdocs-common/src/stages/prepare/preparers.ts @@ -30,18 +30,15 @@ export class Preparers implements PreparerBuilder { private preparerMap = new Map(); static async fromConfig( - // @ts-ignore - // Config not used now, but will be used in urlPreparer when it starts using - // @backstage/integration to get the tokens for providers. config: Config, { logger, reader }: factoryOptions, ): Promise { const preparers = new Preparers(); - const directoryPreparer = new DirectoryPreparer(logger); + const directoryPreparer = new DirectoryPreparer(config, logger); preparers.register('dir', directoryPreparer); - const commonGitPreparer = new CommonGitPreparer(logger); + const commonGitPreparer = new CommonGitPreparer(config, logger); preparers.register('github', commonGitPreparer); preparers.register('gitlab', commonGitPreparer); preparers.register('azure/api', commonGitPreparer); diff --git a/packages/techdocs-common/src/stages/prepare/url.ts b/packages/techdocs-common/src/stages/prepare/url.ts index 3407684837..b938c6b5bc 100644 --- a/packages/techdocs-common/src/stages/prepare/url.ts +++ b/packages/techdocs-common/src/stages/prepare/url.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { Logger } from 'winston'; import { Entity } from '@backstage/catalog-model'; +import { UrlReader } from '@backstage/backend-common'; import { PreparerBase } from './types'; import { getDocFilesFromRepository } from '../../helpers'; -import { Logger } from 'winston'; -import { UrlReader } from '@backstage/backend-common'; export class UrlPreparer implements PreparerBase { private readonly logger: Logger; diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 67d0dfb89e..863f587a96 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -16,6 +16,7 @@ import Docker from 'dockerode'; import { Logger } from 'winston'; import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; import { PreparerBuilder, PublisherBase, @@ -40,6 +41,7 @@ type DocsBuilderArguments = { entity: Entity; logger: Logger; dockerClient: Docker; + config: Config; }; export class DocsBuilder { @@ -49,6 +51,7 @@ export class DocsBuilder { private entity: Entity; private logger: Logger; private dockerClient: Docker; + private config: Config; constructor({ preparers, @@ -57,6 +60,7 @@ export class DocsBuilder { entity, logger, dockerClient, + config, }: DocsBuilderArguments) { this.preparer = preparers.get(entity); this.generator = generators.get(entity); @@ -64,6 +68,7 @@ export class DocsBuilder { this.entity = entity; this.logger = logger; this.dockerClient = dockerClient; + this.config = config; } public async build() { @@ -109,7 +114,11 @@ export class DocsBuilder { // Unless docs are stored locally const nonAgeCheckTypes = ['dir', 'file', 'url']; if (!nonAgeCheckTypes.includes(type)) { - const lastCommit = await getLastCommitTimestamp(target, this.logger); + const lastCommit = await getLastCommitTimestamp( + target, + this.config, + this.logger, + ); const storageTimeStamp = buildMetadataStorage.getTimestamp(); // Check if documentation source is newer than what we have diff --git a/plugins/techdocs-backend/src/service/router.ts b/plugins/techdocs-backend/src/service/router.ts index a64f581a1e..37d5dd59ed 100644 --- a/plugins/techdocs-backend/src/service/router.ts +++ b/plugins/techdocs-backend/src/service/router.ts @@ -131,6 +131,7 @@ export async function createRouter({ dockerClient, logger, entity, + config, }); if (publisherType === 'local') { if (!(await docsBuilder.docsUpToDate())) { diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index 65a286feef..721c10a1ec 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -52,7 +52,7 @@ export async function startStandaloneServer( logger.debug('Creating application...'); const preparers = new Preparers(); - const directoryPreparer = new DirectoryPreparer(logger); + const directoryPreparer = new DirectoryPreparer(config, logger); preparers.register('dir', directoryPreparer); const generators = new Generators(); From 8804e8981131f8755894baffa817f2168398e638 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 21 Dec 2020 23:15:21 +0100 Subject: [PATCH 62/80] techdocs: Add changeset for @backstage/integration changes --- .changeset/little-plums-beg.md | 20 ++++++++++++++++++++ packages/techdocs-common/src/git-auth.ts | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .changeset/little-plums-beg.md diff --git a/.changeset/little-plums-beg.md b/.changeset/little-plums-beg.md new file mode 100644 index 0000000000..351545fd6b --- /dev/null +++ b/.changeset/little-plums-beg.md @@ -0,0 +1,20 @@ +--- +'@backstage/techdocs-common': patch +'@backstage/plugin-techdocs-backend': patch +--- + +Using @backstage/integration package for GitHub/GitLab/Azure tokens and request options. + +Most probably you do not have to make any changes in the app because of this change. +However, if you are using the `DirectoryPreparer` or `CommonGitPreparer` exported by +`@backstage/techdocs-common` package, you now need to add pass in a `config` (from `@backstage/config`) +instance as argument. + +``` + + const directoryPreparer = new DirectoryPreparer(logger); + const commonGitPreparer = new CommonGitPreparer(logger); + + const directoryPreparer = new DirectoryPreparer(config, logger); + const commonGitPreparer = new CommonGitPreparer(config, logger); +``` diff --git a/packages/techdocs-common/src/git-auth.ts b/packages/techdocs-common/src/git-auth.ts index 41a33340af..b58afae490 100644 --- a/packages/techdocs-common/src/git-auth.ts +++ b/packages/techdocs-common/src/git-auth.ts @@ -101,7 +101,7 @@ export const getTokenForGitRepo = async ( case 'azure/api': return getAzureIntegrationConfig(config, host).token; default: - throw new Error('Failed to get reository type'); + throw new Error('Failed to get repository type'); } } catch (error) { throw error; From 8a53d92299aa85f8ffe242e60860161013ad344d Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 28 Dec 2020 16:25:28 -0500 Subject: [PATCH 63/80] Change Link to use backstage/core --- .../LabelDataflowInstructionsPage.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx index ba5a22e932..c3f4b4f79c 100644 --- a/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx +++ b/plugins/cost-insights/src/components/LabelDataflowInstructionsPage/LabelDataflowInstructionsPage.tsx @@ -15,8 +15,8 @@ */ import React from 'react'; -import { Box, Typography, Link } from '@material-ui/core'; -import { CodeSnippet } from '@backstage/core'; +import { Box, Typography } from '@material-ui/core'; +import { CodeSnippet, Link } from '@backstage/core'; import { AlertInstructionsLayout } from '../AlertInstructionsLayout'; export const LabelDataflowInstructionsPage = () => { @@ -32,7 +32,7 @@ export const LabelDataflowInstructionsPage = () => { In Cloud Dataflow, labels can be added to a job either programmatically or via the command-line when launching a job. Note that GCP has{' '} - + restrictions {' '} on the length and characters that can be used in labels. @@ -46,7 +46,7 @@ export const LabelDataflowInstructionsPage = () => { DataflowPipelineOptions Dataflow jobs using Beam's{' '} - + DataflowPipelineOptions {' '} directly can use the setLabels function to add one or more @@ -79,11 +79,11 @@ sc.optionsAs[DataflowPipelineOptions].setLabels(Map("job-id" -> "my-dataflow-job For more information on specifying options, see the{' '} - + Dataflow documentation {' '} or{' '} - + Scio Scaladoc . From d45efbc9bd7797785cf15dd21f3debcfe18383d4 Mon Sep 17 00:00:00 2001 From: Joel Low Date: Tue, 29 Dec 2020 09:24:30 +0800 Subject: [PATCH 64/80] Fix typo in .app.listen.port config schema --- .changeset/late-crabs-itch.md | 5 +++++ packages/cli/package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/late-crabs-itch.md diff --git a/.changeset/late-crabs-itch.md b/.changeset/late-crabs-itch.md new file mode 100644 index 0000000000..8d49d0ecf9 --- /dev/null +++ b/.changeset/late-crabs-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fix typo in .app.listen.port config schema diff --git a/packages/cli/package.json b/packages/cli/package.json index 90d2fe24f1..f46314bbb6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -182,7 +182,7 @@ "visibility": "frontend", "description": "The host that the frontend should be bound to. Only used for local development." }, - "post": { + "port": { "type": "number", "visibility": "frontend", "description": "The port that the frontend should be bound to. Only used for local development." From 4e0e3b1bf053d8abd062d38b6aacf0a5a161b172 Mon Sep 17 00:00:00 2001 From: Joel Low Date: Tue, 29 Dec 2020 09:21:44 +0800 Subject: [PATCH 65/80] Add missing `yarn clean` for frontend --- .changeset/eight-experts-visit.md | 13 +++++++++++++ .../default-app/packages/app/package.json.hbs | 1 + 2 files changed, 14 insertions(+) create mode 100644 .changeset/eight-experts-visit.md diff --git a/.changeset/eight-experts-visit.md b/.changeset/eight-experts-visit.md new file mode 100644 index 0000000000..d1a6da1bdf --- /dev/null +++ b/.changeset/eight-experts-visit.md @@ -0,0 +1,13 @@ +--- +'@backstage/create-app': patch +--- + +Add missing `yarn clean` for app. + +For users with existing Backstage installations, add the following under the `scripts` section in `packages/app/package.json`, after the "lint" entry: + +```json +"clean": "backstage-cli clean", +``` + +This will add the missing `yarn clean` for the generated frontend. diff --git a/packages/create-app/templates/default-app/packages/app/package.json.hbs b/packages/create-app/templates/default-app/packages/app/package.json.hbs index 1746f171c9..919ca678a0 100644 --- a/packages/create-app/templates/default-app/packages/app/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/app/package.json.hbs @@ -46,6 +46,7 @@ "build": "backstage-cli app:build", "test": "backstage-cli test", "lint": "backstage-cli lint", + "clean": "backstage-cli clean", "test:e2e": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:dev", "test:e2e:ci": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:run", "cy:dev": "cypress open", From 7839e0fb42bd3d7d04cc542e534123b05d65f47c Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 10:05:27 +0100 Subject: [PATCH 66/80] chore: removing last occurrence of nodegit --- plugins/scaffolder-backend/package.json | 1 - .../src/scaffolder/stages/publish/gitlab.test.ts | 1 - yarn.lock | 11 ++--------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index d53e04fe3e..1a443ceb7c 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -62,7 +62,6 @@ "@octokit/types": "^5.4.1", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", - "@types/nodegit": "^0.26.12", "@types/supertest": "^2.0.8", "supertest": "^4.0.2", "yaml": "^1.10.0" diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts index 61113003d4..2f33358829 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -jest.mock('nodegit'); jest.mock('@gitbeaker/node'); jest.mock('./helpers'); diff --git a/yarn.lock b/yarn.lock index 528c653b38..7a49095f70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1666,10 +1666,10 @@ yup "^0.29.3" "@backstage/core@^0.3.0": - version "0.4.1" + version "0.4.2" dependencies: "@backstage/config" "^0.1.2" - "@backstage/core-api" "^0.2.6" + "@backstage/core-api" "^0.2.7" "@backstage/theme" "^0.2.2" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -5972,13 +5972,6 @@ resolved "https://registry.npmjs.org/@types/node/-/node-13.13.15.tgz#fe1cc3aa465a3ea6858b793fd380b66c39919766" integrity sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw== -"@types/nodegit@^0.26.12": - version "0.26.12" - resolved "https://registry.npmjs.org/@types/nodegit/-/nodegit-0.26.12.tgz#93afb4cb85d3a48d392c3232699c9c07d8251a36" - integrity sha512-4YpeTImFZNJ1cve4lEueHFVS8rAs8XpZqlmx+Bm9bMc+XMiCrcwaUf6peN7pod7Rl3esVlGP1zdBB7Z12eMVAA== - dependencies: - "@types/node" "*" - "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" From 50aa364d0b9fa7b629f529deaf407054f74789a8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Dec 2020 11:08:44 +0100 Subject: [PATCH 67/80] create-app: ignore lint error --- packages/create-app/bin/backstage-create-app | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/create-app/bin/backstage-create-app b/packages/create-app/bin/backstage-create-app index 467a0cae8f..902f341bfb 100755 --- a/packages/create-app/bin/backstage-create-app +++ b/packages/create-app/bin/backstage-create-app @@ -24,6 +24,8 @@ const isLocal = require('fs').existsSync(path.resolve(__dirname, '../src')); if (!isLocal || process.env.BACKSTAGE_E2E_CLI_TEST) { require('..'); } else { + // Only used for development, so should be a devDependency + // eslint-disable-next-line import/no-extraneous-dependencies require('ts-node').register({ transpileOnly: true, project: path.resolve(__dirname, '../../../tsconfig.json'), From cb9416574520df6f1d30a2a3bbb1f4f391a9e15f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Dec 2020 11:08:54 +0100 Subject: [PATCH 68/80] create-app: fix nodemon config --- packages/create-app/package.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 23a0b1a584..1f6f65d730 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -70,6 +70,11 @@ "@types/recursive-readdir": "^2.2.0", "ts-node": "^8.6.2" }, + "nodemonConfig": { + "watch": "./src", + "exec": "bin/backstage-create-app", + "ext": "ts" + }, "files": [ "bin", "dist", From 352a6581ff49e9f43d9d515dd517c7fdb93f903c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Dec 2020 11:17:58 +0100 Subject: [PATCH 69/80] create-app: add start-backend script to template --- .changeset/sweet-ears-move.md | 11 +++++++++++ .../create-app/templates/default-app/package.json.hbs | 1 + 2 files changed, 12 insertions(+) create mode 100644 .changeset/sweet-ears-move.md diff --git a/.changeset/sweet-ears-move.md b/.changeset/sweet-ears-move.md new file mode 100644 index 0000000000..10eaf1f649 --- /dev/null +++ b/.changeset/sweet-ears-move.md @@ -0,0 +1,11 @@ +--- +'@backstage/create-app': patch +--- + +Added `"start-backend"` script to root `package.json`. + +To apply this change to an existing app, add the following script to the root `package.json`: + +```json +"start-backend": "yarn workspace backend start" +``` diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index 975a5a2ed2..1353e33072 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -7,6 +7,7 @@ }, "scripts": { "start": "yarn workspace app start", + "start-backend": "yarn workspace backend start", "build": "lerna run build", "build-image": "yarn workspace backend build-image", "tsc": "tsc", From ba6f2b8a40ad9dce9f606e64378990527e4f55ca Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 11:46:36 +0100 Subject: [PATCH 70/80] chore: reworking the API exports and fixing the logging to be a little less verbose --- packages/backend-common/src/scm/git.test.ts | 2 +- packages/backend-common/src/scm/git.ts | 61 +++++++++++---------- packages/backend-common/src/scm/index.ts | 3 +- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index 7c38eafa0c..96c0f919a7 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -18,7 +18,7 @@ jest.mock('isomorphic-git/http/node'); jest.mock('fs-extra'); import * as isomorphic from 'isomorphic-git'; -import * as Git from './git'; +import { Git } from './git'; import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 5d3f95d42c..ca0bc7853a 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -19,17 +19,17 @@ import fs from 'fs-extra'; import { Logger } from 'winston'; /* -provider username password +provider username password GitHub token 'x-oauth-basic' -GitHub App token 'x-access-token' -BitBucket 'x-token-auth' token -GitLab 'oauth2' token +GitHub App token 'x-access-token' +BitBucket 'x-token-auth' token +GitLab 'oauth2' token From : https://isomorphic-git.org/docs/en/onAuth Azure 'notempty' token */ -class SCM { - constructor( +export class Git { + private constructor( private readonly config: { username?: string; password?: string; @@ -85,7 +85,7 @@ class SCM { dir, singleBranch: true, depth: 1, - onProgress: this.onProgressHandler, + onProgress: this.onProgressHandler(), headers: { 'user-agent': 'git/@isomorphic-git', }, @@ -110,7 +110,7 @@ class SCM { http, dir, remote: remoteValue, - onProgress: this.onProgressHandler, + onProgress: this.onProgressHandler(), headers: { 'user-agent': 'git/@isomorphic-git', }, @@ -163,7 +163,7 @@ class SCM { fs, dir, http, - onProgress: this.onProgressHandler, + onProgress: this.onProgressHandler(), headers: { 'user-agent': 'git/@isomorphic-git', }, @@ -187,23 +187,28 @@ class SCM { password: this.config.password, }); - private onProgressHandler: ProgressCallback = event => { - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.info(`status={${event.phase},total={${total}}}`); - }; -} + private onProgressHandler = (): ProgressCallback => { + let currentPhase = ''; -// TODO(blam): This could potentially become something like for URL -// and use the integrations config for URLReading instead. -// But for now, I don't want to do all that in this PR. -export const fromAuth = ({ - username, - password, - logger, -}: { - username?: string; - password?: string; - logger?: Logger; -}) => new SCM({ username, password, logger }); + return event => { + if (currentPhase !== event.phase) { + currentPhase = event.phase; + this.config.logger?.info(event.phase); + } + const total = event.total + ? `${Math.round((event.loaded / event.total) * 100)}%` + : event.loaded; + this.config.logger?.debug(`status={${event.phase},total={${total}}}`); + }; + }; + + static fromAuth = ({ + username, + password, + logger, + }: { + username?: string; + password?: string; + logger?: Logger; + }) => new Git({ username, password, logger }); +} diff --git a/packages/backend-common/src/scm/index.ts b/packages/backend-common/src/scm/index.ts index 83a59310cd..e967fffb44 100644 --- a/packages/backend-common/src/scm/index.ts +++ b/packages/backend-common/src/scm/index.ts @@ -13,6 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import * as Git from './git'; -export { Git }; +export { Git } from './git'; From 0829ff12692fb37c4c0ea974f14bf2988a0a50a1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 28 Dec 2020 18:34:41 +0100 Subject: [PATCH 71/80] backend-common: include extra fields on dev log formatter --- .changeset/mighty-plums-wave.md | 5 +++++ packages/backend-common/src/logging/formats.ts | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 .changeset/mighty-plums-wave.md diff --git a/.changeset/mighty-plums-wave.md b/.changeset/mighty-plums-wave.md new file mode 100644 index 0000000000..ac84b68e04 --- /dev/null +++ b/.changeset/mighty-plums-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Tweaked development log formatter to include extra fields at the end of each log line diff --git a/packages/backend-common/src/logging/formats.ts b/packages/backend-common/src/logging/formats.ts index 5f00448744..4f7949f115 100644 --- a/packages/backend-common/src/logging/formats.ts +++ b/packages/backend-common/src/logging/formats.ts @@ -17,19 +17,23 @@ import * as winston from 'winston'; import { TransformableInfo } from 'logform'; const coloredTemplate = (info: TransformableInfo) => { - const { timestamp, level, message, plugin, service } = info; + const { timestamp, level, message, plugin, service, ...fields } = info; const colorizer = winston.format.colorize(); const prefix = plugin || service; const timestampColor = colorizer.colorize('timestamp', timestamp); const prefixColor = colorizer.colorize('prefix', prefix); - return `${timestampColor} ${prefixColor} ${level} ${message}`; + const extraFields = Object.entries(fields) + .map(([key, value]) => `${colorizer.colorize('field', `${key}`)}=${value}`) + .join(' '); + + return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`; }; export const coloredFormat = winston.format.combine( winston.format.timestamp(), winston.format.colorize({ - colors: { timestamp: 'dim', prefix: 'blue' }, + colors: { timestamp: 'dim', prefix: 'blue', field: 'cyan' }, }), winston.format.printf(coloredTemplate), ); From 610b3a205a123c1a51a5b768a9943b824b314196 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 11:54:30 +0100 Subject: [PATCH 72/80] chore: try to fix the alignment --- packages/backend-common/src/scm/git.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index ca0bc7853a..690f464d35 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -20,8 +20,8 @@ import { Logger } from 'winston'; /* provider username password -GitHub token 'x-oauth-basic' -GitHub App token 'x-access-token' +GitHub token 'x-oauth-basic' +GitHub App token 'x-access-token' BitBucket 'x-token-auth' token GitLab 'oauth2' token From : https://isomorphic-git.org/docs/en/onAuth From a1ebbdeee04c1022e1349ccc9aebf95721905402 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 29 Dec 2020 10:59:38 +0000 Subject: [PATCH 73/80] Version Packages --- .changeset/dull-seals-march.md | 6 ------ .changeset/eight-experts-visit.md | 13 ------------- .changeset/famous-eagles-swim.md | 5 ----- .changeset/friendly-shoes-compare.md | 9 --------- .changeset/gentle-dragons-marry.md | 5 ----- .changeset/late-crabs-itch.md | 5 ----- .changeset/little-plums-beg.md | 20 -------------------- .changeset/loud-days-breathe.md | 5 ----- .changeset/lucky-fans-wait.md | 5 ----- .changeset/modern-timers-obey.md | 6 ------ .changeset/neat-maps-return.md | 5 ----- .changeset/polite-glasses-occur.md | 5 ----- .changeset/polite-turtles-prove.md | 5 ----- .changeset/purple-turtles-float.md | 5 ----- .changeset/sweet-ears-move.md | 11 ----------- .changeset/warm-pets-sin.md | 5 ----- packages/cli/CHANGELOG.md | 6 ++++++ packages/cli/package.json | 6 +++--- packages/core-api/CHANGELOG.md | 8 ++++++++ packages/core-api/package.json | 4 ++-- packages/core/CHANGELOG.md | 10 ++++++++++ packages/core/package.json | 6 +++--- packages/create-app/CHANGELOG.md | 22 ++++++++++++++++++++++ packages/create-app/package.json | 18 +++++++++--------- packages/dev-utils/CHANGELOG.md | 11 +++++++++++ packages/dev-utils/package.json | 8 ++++---- packages/techdocs-common/CHANGELOG.md | 20 ++++++++++++++++++++ packages/techdocs-common/package.json | 4 ++-- plugins/api-docs/CHANGELOG.md | 11 +++++++++++ plugins/api-docs/package.json | 10 +++++----- plugins/auth-backend/CHANGELOG.md | 6 ++++++ plugins/auth-backend/package.json | 4 ++-- plugins/catalog-import/package.json | 6 +++--- plugins/catalog/CHANGELOG.md | 16 ++++++++++++++++ plugins/catalog/package.json | 10 +++++----- plugins/circleci/package.json | 6 +++--- plugins/cloudbuild/package.json | 6 +++--- plugins/cost-insights/CHANGELOG.md | 8 ++++++++ plugins/cost-insights/package.json | 8 ++++---- plugins/explore/package.json | 6 +++--- plugins/fossa/CHANGELOG.md | 9 +++++++++ plugins/fossa/package.json | 8 ++++---- plugins/gcp-projects/package.json | 6 +++--- plugins/github-actions/package.json | 6 +++--- plugins/gitops-profiles/package.json | 6 +++--- plugins/graphiql/package.json | 6 +++--- plugins/jenkins/package.json | 6 +++--- plugins/kubernetes/package.json | 6 +++--- plugins/lighthouse/package.json | 6 +++--- plugins/newrelic/package.json | 6 +++--- plugins/org/package.json | 6 +++--- plugins/pagerduty/package.json | 6 +++--- plugins/register-component/CHANGELOG.md | 11 +++++++++++ plugins/register-component/package.json | 10 +++++----- plugins/rollbar/package.json | 6 +++--- plugins/scaffolder/package.json | 6 +++--- plugins/search/package.json | 6 +++--- plugins/sentry/package.json | 6 +++--- plugins/sonarqube/package.json | 6 +++--- plugins/tech-radar/package.json | 6 +++--- plugins/techdocs-backend/CHANGELOG.md | 24 ++++++++++++++++++++++++ plugins/techdocs-backend/package.json | 6 +++--- plugins/techdocs/CHANGELOG.md | 16 ++++++++++++++++ plugins/techdocs/package.json | 14 +++++++------- plugins/user-settings/package.json | 6 +++--- plugins/welcome/package.json | 6 +++--- 66 files changed, 302 insertions(+), 239 deletions(-) delete mode 100644 .changeset/dull-seals-march.md delete mode 100644 .changeset/eight-experts-visit.md delete mode 100644 .changeset/famous-eagles-swim.md delete mode 100644 .changeset/friendly-shoes-compare.md delete mode 100644 .changeset/gentle-dragons-marry.md delete mode 100644 .changeset/late-crabs-itch.md delete mode 100644 .changeset/little-plums-beg.md delete mode 100644 .changeset/loud-days-breathe.md delete mode 100644 .changeset/lucky-fans-wait.md delete mode 100644 .changeset/modern-timers-obey.md delete mode 100644 .changeset/neat-maps-return.md delete mode 100644 .changeset/polite-glasses-occur.md delete mode 100644 .changeset/polite-turtles-prove.md delete mode 100644 .changeset/purple-turtles-float.md delete mode 100644 .changeset/sweet-ears-move.md delete mode 100644 .changeset/warm-pets-sin.md create mode 100644 plugins/fossa/CHANGELOG.md diff --git a/.changeset/dull-seals-march.md b/.changeset/dull-seals-march.md deleted file mode 100644 index 49e1f7f2e6..0000000000 --- a/.changeset/dull-seals-march.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/core-api': patch -'@backstage/core': patch ---- - -Add `FlatRoutes` component to replace the top-level `Routes` component from `react-router` within apps, removing the need for manually appending `/*` to paths or sorting routes. diff --git a/.changeset/eight-experts-visit.md b/.changeset/eight-experts-visit.md deleted file mode 100644 index d1a6da1bdf..0000000000 --- a/.changeset/eight-experts-visit.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Add missing `yarn clean` for app. - -For users with existing Backstage installations, add the following under the `scripts` section in `packages/app/package.json`, after the "lint" entry: - -```json -"clean": "backstage-cli clean", -``` - -This will add the missing `yarn clean` for the generated frontend. diff --git a/.changeset/famous-eagles-swim.md b/.changeset/famous-eagles-swim.md deleted file mode 100644 index 49f2724b5b..0000000000 --- a/.changeset/famous-eagles-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-register-component': patch ---- - -Register component plugin is deprecated in favor of @backstage/plugin-catalog-import diff --git a/.changeset/friendly-shoes-compare.md b/.changeset/friendly-shoes-compare.md deleted file mode 100644 index 0b242511c0..0000000000 --- a/.changeset/friendly-shoes-compare.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Add `CatalogIndexPage` and `CatalogEntityPage`, two new extensions that replace the existing `Router` component. - -Add `EntityLayout` to replace `EntityPageLayout`, using children instead of an element property, and allowing for collection of all `RouteRef` mount points used within tabs. - -Add `EntitySwitch` to be used to select components based on entity data, along with accompanying `isKind`, `isNamespace`, and `isComponentType` filters. diff --git a/.changeset/gentle-dragons-marry.md b/.changeset/gentle-dragons-marry.md deleted file mode 100644 index d9ef443932..0000000000 --- a/.changeset/gentle-dragons-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Link register API to catalog-import plugin diff --git a/.changeset/late-crabs-itch.md b/.changeset/late-crabs-itch.md deleted file mode 100644 index 8d49d0ecf9..0000000000 --- a/.changeset/late-crabs-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fix typo in .app.listen.port config schema diff --git a/.changeset/little-plums-beg.md b/.changeset/little-plums-beg.md deleted file mode 100644 index 351545fd6b..0000000000 --- a/.changeset/little-plums-beg.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/techdocs-common': patch -'@backstage/plugin-techdocs-backend': patch ---- - -Using @backstage/integration package for GitHub/GitLab/Azure tokens and request options. - -Most probably you do not have to make any changes in the app because of this change. -However, if you are using the `DirectoryPreparer` or `CommonGitPreparer` exported by -`@backstage/techdocs-common` package, you now need to add pass in a `config` (from `@backstage/config`) -instance as argument. - -``` - - const directoryPreparer = new DirectoryPreparer(logger); - const commonGitPreparer = new CommonGitPreparer(logger); - - const directoryPreparer = new DirectoryPreparer(config, logger); - const commonGitPreparer = new CommonGitPreparer(config, logger); -``` diff --git a/.changeset/loud-days-breathe.md b/.changeset/loud-days-breathe.md deleted file mode 100644 index f8eb561f31..0000000000 --- a/.changeset/loud-days-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/dev-utils': patch ---- - -Add new `addPage` method for use with extensions, as well as an `EntityGridItem` to easily create different test cases for entity overview cards. diff --git a/.changeset/lucky-fans-wait.md b/.changeset/lucky-fans-wait.md deleted file mode 100644 index 439d943c65..0000000000 --- a/.changeset/lucky-fans-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Fix links in sample instructions diff --git a/.changeset/modern-timers-obey.md b/.changeset/modern-timers-obey.md deleted file mode 100644 index 7268d4961d..0000000000 --- a/.changeset/modern-timers-obey.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch -'@backstage/plugin-techdocs-backend': patch ---- - -Added configuration schema for the commonly used properties of techdocs and techdocs-backend plugins diff --git a/.changeset/neat-maps-return.md b/.changeset/neat-maps-return.md deleted file mode 100644 index 9ff2ebe845..0000000000 --- a/.changeset/neat-maps-return.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-fossa': patch ---- - -Bump dependency versions of @backstage/core, cli and test-utils diff --git a/.changeset/polite-glasses-occur.md b/.changeset/polite-glasses-occur.md deleted file mode 100644 index bec533caad..0000000000 --- a/.changeset/polite-glasses-occur.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Add new `EntityProvider` component, which can be used to provide an entity for the `useEntity` hook. diff --git a/.changeset/polite-turtles-prove.md b/.changeset/polite-turtles-prove.md deleted file mode 100644 index 094617026c..0000000000 --- a/.changeset/polite-turtles-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Deprecate `RouteRef` path parameter and member, and remove deprecated `routeRef.createSubRouteRef`. diff --git a/.changeset/purple-turtles-float.md b/.changeset/purple-turtles-float.md deleted file mode 100644 index 8736a7315f..0000000000 --- a/.changeset/purple-turtles-float.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-api': patch ---- - -Delay auth loginPopup close to avoid race condition with callers of authFlowHelpers. diff --git a/.changeset/sweet-ears-move.md b/.changeset/sweet-ears-move.md deleted file mode 100644 index 10eaf1f649..0000000000 --- a/.changeset/sweet-ears-move.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Added `"start-backend"` script to root `package.json`. - -To apply this change to an existing app, add the following script to the root `package.json`: - -```json -"start-backend": "yarn workspace backend start" -``` diff --git a/.changeset/warm-pets-sin.md b/.changeset/warm-pets-sin.md deleted file mode 100644 index 3a9197e7f2..0000000000 --- a/.changeset/warm-pets-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -fix bug in token expiration date diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 256480bf70..d88220cc23 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli +## 0.4.4 + +### Patch Changes + +- d45efbc9b: Fix typo in .app.listen.port config schema + ## 0.4.3 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index f46314bbb6..6da871e74c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.4.3", + "version": "0.4.4", "private": false, "publishConfig": { "access": "public" @@ -113,8 +113,8 @@ "devDependencies": { "@backstage/backend-common": "^0.4.1", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.2", - "@backstage/dev-utils": "^0.1.6", + "@backstage/core": "^0.4.3", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@backstage/theme": "^0.2.2", "@types/diff": "^4.0.2", diff --git a/packages/core-api/CHANGELOG.md b/packages/core-api/CHANGELOG.md index 2d8915e7f1..3f412f3e17 100644 --- a/packages/core-api/CHANGELOG.md +++ b/packages/core-api/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core-api +## 0.2.8 + +### Patch Changes + +- a08c32ced: Add `FlatRoutes` component to replace the top-level `Routes` component from `react-router` within apps, removing the need for manually appending `/*` to paths or sorting routes. +- 86c3c652a: Deprecate `RouteRef` path parameter and member, and remove deprecated `routeRef.createSubRouteRef`. +- 27f2af935: Delay auth loginPopup close to avoid race condition with callers of authFlowHelpers. + ## 0.2.7 ### Patch Changes diff --git a/packages/core-api/package.json b/packages/core-api/package.json index f02520d170..a818d38143 100644 --- a/packages/core-api/package.json +++ b/packages/core-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-api", "description": "Internal Core API used by Backstage plugins and apps", - "version": "0.2.7", + "version": "0.2.8", "private": false, "publishConfig": { "access": "public", @@ -43,7 +43,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.3", + "@backstage/cli": "^0.4.4", "@backstage/test-utils-core": "^0.1.1", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 6b59bb7fbb..bb13447f94 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core +## 0.4.3 + +### Patch Changes + +- a08c32ced: Add `FlatRoutes` component to replace the top-level `Routes` component from `react-router` within apps, removing the need for manually appending `/*` to paths or sorting routes. +- Updated dependencies [a08c32ced] +- Updated dependencies [86c3c652a] +- Updated dependencies [27f2af935] + - @backstage/core-api@0.2.8 + ## 0.4.2 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 71f2daceb8..b84eb4ff7b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core", "description": "Core API used by Backstage plugins and apps", - "version": "0.4.2", + "version": "0.4.3", "private": false, "publishConfig": { "access": "public", @@ -30,7 +30,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core-api": "^0.2.7", + "@backstage/core-api": "^0.2.8", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -65,7 +65,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.4.3", + "@backstage/cli": "^0.4.4", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index e589cab0ae..94260dcec9 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/create-app +## 0.3.1 + +### Patch Changes + +- 4e0e3b1bf: Add missing `yarn clean` for app. + + For users with existing Backstage installations, add the following under the `scripts` section in `packages/app/package.json`, after the "lint" entry: + + ```json + "clean": "backstage-cli clean", + ``` + + This will add the missing `yarn clean` for the generated frontend. + +- 352a6581f: Added `"start-backend"` script to root `package.json`. + + To apply this change to an existing app, add the following script to the root `package.json`: + + ```json + "start-backend": "yarn workspace backend start" + ``` + ## 0.3.0 ### Minor Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 1f6f65d730..ac29dc1431 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "Create app package for Backstage", - "version": "0.3.0", + "version": "0.3.1", "private": false, "publishConfig": { "access": "public" @@ -39,27 +39,27 @@ "devDependencies": { "@backstage/backend-common": "^0.4.1", "@backstage/catalog-model": "^0.6.0", - "@backstage/cli": "^0.4.3", + "@backstage/cli": "^0.4.4", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.2", - "@backstage/plugin-api-docs": "^0.4.1", + "@backstage/core": "^0.4.3", + "@backstage/plugin-api-docs": "^0.4.2", "@backstage/plugin-app-backend": "^0.3.3", - "@backstage/plugin-auth-backend": "^0.2.7", - "@backstage/plugin-catalog": "^0.2.8", + "@backstage/plugin-auth-backend": "^0.2.8", + "@backstage/plugin-catalog": "^0.2.9", "@backstage/plugin-catalog-backend": "^0.5.1", "@backstage/plugin-circleci": "^0.2.5", "@backstage/plugin-explore": "^0.2.2", "@backstage/plugin-github-actions": "^0.2.6", "@backstage/plugin-lighthouse": "^0.2.6", "@backstage/plugin-proxy-backend": "^0.2.3", - "@backstage/plugin-register-component": "^0.2.5", + "@backstage/plugin-register-component": "^0.2.6", "@backstage/plugin-rollbar-backend": "^0.1.5", "@backstage/plugin-scaffolder": "^0.3.5", "@backstage/plugin-search": "^0.2.4", "@backstage/plugin-scaffolder-backend": "^0.3.6", "@backstage/plugin-tech-radar": "^0.3.1", - "@backstage/plugin-techdocs": "^0.5.1", - "@backstage/plugin-techdocs-backend": "^0.5.0", + "@backstage/plugin-techdocs": "^0.5.2", + "@backstage/plugin-techdocs-backend": "^0.5.1", "@backstage/plugin-user-settings": "^0.2.3", "@backstage/test-utils": "^0.1.6", "@backstage/theme": "^0.2.2", diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index e634a09c20..1938754169 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/dev-utils +## 0.1.7 + +### Patch Changes + +- 696b8ce74: Add new `addPage` method for use with extensions, as well as an `EntityGridItem` to easily create different test cases for entity overview cards. +- Updated dependencies [a08c32ced] +- Updated dependencies [7e0b8cac5] +- Updated dependencies [87c0c53c2] + - @backstage/core@0.4.3 + - @backstage/plugin-catalog@0.2.9 + ## 0.1.6 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 1e0304a5a9..785607c6d3 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.1.6", + "version": "0.1.7", "private": false, "publishConfig": { "access": "public", @@ -29,9 +29,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.0", + "@backstage/core": "^0.4.3", "@backstage/catalog-model": "^0.6.0", - "@backstage/plugin-catalog": "^0.2.8", + "@backstage/plugin-catalog": "^0.2.9", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -47,7 +47,7 @@ "react-router-dom": "6.0.0-beta.0" }, "devDependencies": { - "@backstage/cli": "^0.4.1", + "@backstage/cli": "^0.4.4", "@types/jest": "^26.0.7", "@types/node": "^12.0.0" }, diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 40bac7ce7f..1672e5a61b 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/techdocs-common +## 0.3.1 + +### Patch Changes + +- 8804e8981: Using @backstage/integration package for GitHub/GitLab/Azure tokens and request options. + + Most probably you do not have to make any changes in the app because of this change. + However, if you are using the `DirectoryPreparer` or `CommonGitPreparer` exported by + `@backstage/techdocs-common` package, you now need to add pass in a `config` (from `@backstage/config`) + instance as argument. + + ``` + + const directoryPreparer = new DirectoryPreparer(logger); + const commonGitPreparer = new CommonGitPreparer(logger); + + const directoryPreparer = new DirectoryPreparer(config, logger); + const commonGitPreparer = new CommonGitPreparer(config, logger); + ``` + ## 0.3.0 ### Minor Changes diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index 20d0f68a98..e7244c4a87 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.3.0", + "version": "0.3.1", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -56,7 +56,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.3", + "@backstage/cli": "^0.4.4", "@types/fs-extra": "^9.0.5", "@types/git-url-parse": "^9.0.0", "@types/js-yaml": "^3.12.5", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index dc1c38ef49..995dfdc175 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-api-docs +## 0.4.2 + +### Patch Changes + +- 9161531b2: Link register API to catalog-import plugin +- Updated dependencies [a08c32ced] +- Updated dependencies [7e0b8cac5] +- Updated dependencies [87c0c53c2] + - @backstage/core@0.4.3 + - @backstage/plugin-catalog@0.2.9 + ## 0.4.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index c907288424..23dd66a9a9 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.4.1", + "version": "0.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,8 +30,8 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", - "@backstage/plugin-catalog": "^0.2.7", + "@backstage/core": "^0.4.3", + "@backstage/plugin-catalog": "^0.2.9", "@backstage/theme": "^0.2.2", "@kyma-project/asyncapi-react": "^0.14.2", "@material-icons/font": "^1.0.2", @@ -49,8 +49,8 @@ "swagger-ui-react": "^3.37.2" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index f011d224b4..7d67ec0273 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-auth-backend +## 0.2.8 + +### Patch Changes + +- cc046682e: fix bug in token expiration date + ## 0.2.7 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index c55d4e508f..38aed2f792 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.2.7", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -64,7 +64,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.4.2", + "@backstage/cli": "^0.4.4", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 144627d838..a51001d585 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/plugin-catalog-backend": "^0.5.0", "@backstage/integration": "^0.1.4", @@ -50,8 +50,8 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index a2b8d7e1a4..ce5b978e7d 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog +## 0.2.9 + +### Patch Changes + +- 7e0b8cac5: Add `CatalogIndexPage` and `CatalogEntityPage`, two new extensions that replace the existing `Router` component. + + Add `EntityLayout` to replace `EntityPageLayout`, using children instead of an element property, and allowing for collection of all `RouteRef` mount points used within tabs. + + Add `EntitySwitch` to be used to select components based on entity data, along with accompanying `isKind`, `isNamespace`, and `isComponentType` filters. + +- 87c0c53c2: Add new `EntityProvider` component, which can be used to provide an entity for the `useEntity` hook. +- Updated dependencies [a08c32ced] +- Updated dependencies [359f9d2d8] + - @backstage/core@0.4.3 + - @backstage/plugin-techdocs@0.5.2 + ## 0.2.8 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 8bdc1fecd0..e8d2309a90 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "0.2.8", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "dependencies": { "@backstage/catalog-client": "^0.3.4", "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-scaffolder": "^0.3.5", - "@backstage/plugin-techdocs": "^0.5.1", + "@backstage/plugin-techdocs": "^0.5.2", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -52,8 +52,8 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@microsoft/microsoft-graph-types": "^1.25.0", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index a4aca24f3a..f117c660f0 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -50,8 +50,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 41072c9922..b559ca6a86 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -49,8 +49,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 87f5e89a9b..5e71d54073 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-cost-insights +## 0.5.4 + +### Patch Changes + +- 3fca9adb9: Fix links in sample instructions +- Updated dependencies [a08c32ced] + - @backstage/core@0.4.3 + ## 0.5.3 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index a85862eed7..a38a07a3a0 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-cost-insights", - "version": "0.5.3", + "version": "0.5.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -56,8 +56,8 @@ "yup": "^0.29.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 76358cf438..4ec76ad812 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -42,8 +42,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md new file mode 100644 index 0000000000..e1c9ef1717 --- /dev/null +++ b/plugins/fossa/CHANGELOG.md @@ -0,0 +1,9 @@ +# @backstage/plugin-fossa + +## 0.1.1 + +### Patch Changes + +- 7afdfef98: Bump dependency versions of @backstage/core, cli and test-utils +- Updated dependencies [a08c32ced] + - @backstage/core@0.4.3 diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 820092c241..b7878b5b29 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-fossa", - "version": "0.1.0", + "version": "0.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,8 +43,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 4fe8613e46..823a2fa37c 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,8 +41,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index a5612568e7..b9b0e93d6f 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/core-api": "^0.2.7", "@backstage/plugin-catalog": "^0.2.8", "@backstage/theme": "^0.2.2", @@ -51,8 +51,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index a92956d6fa..e6a1092b47 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -42,8 +42,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 310dc96de1..0c42b824fb 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -43,8 +43,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index d42282d738..631e394d71 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -46,8 +46,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 144786d58c..4404b5e845 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-kubernetes-backend": "^0.2.3", "@backstage/theme": "^0.2.2", "@kubernetes/client-node": "^0.12.1", @@ -46,8 +46,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index a567410290..7bb1427930 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -33,7 +33,7 @@ "dependencies": { "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/core-api": "^0.2.6", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", @@ -47,8 +47,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index e5c1c70ba2..03b2d83d65 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,8 +41,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/org/package.json b/plugins/org/package.json index a8d8f908fb..391311454b 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -33,8 +33,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 6ee51ad1e9..5c8890034f 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -44,8 +44,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/register-component/CHANGELOG.md b/plugins/register-component/CHANGELOG.md index 488d45ec0e..949ac77b56 100644 --- a/plugins/register-component/CHANGELOG.md +++ b/plugins/register-component/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-register-component +## 0.2.6 + +### Patch Changes + +- 1517876fd: Register component plugin is deprecated in favor of @backstage/plugin-catalog-import +- Updated dependencies [a08c32ced] +- Updated dependencies [7e0b8cac5] +- Updated dependencies [87c0c53c2] + - @backstage/core@0.4.3 + - @backstage/plugin-catalog@0.2.9 + ## 0.2.5 ### Patch Changes diff --git a/plugins/register-component/package.json b/plugins/register-component/package.json index dcf981365f..4f161a7398 100644 --- a/plugins/register-component/package.json +++ b/plugins/register-component/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-register-component", - "version": "0.2.5", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,8 +31,8 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", - "@backstage/plugin-catalog": "^0.2.7", + "@backstage/core": "^0.4.3", + "@backstage/plugin-catalog": "^0.2.9", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,8 +45,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 6e668df250..90a2d1b218 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -47,8 +47,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index afebecceac..8cd45779e1 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -31,7 +31,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.8", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -50,8 +50,8 @@ "swr": "^0.3.0" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/search/package.json b/plugins/search/package.json index 9f31c0fd0e..1111e67abe 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/plugin-catalog": "^0.2.7", "@backstage/catalog-model": "^0.6.0", "@backstage/theme": "^0.2.2", @@ -43,8 +43,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 630e735bb7..56736d83a3 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -32,7 +32,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -45,8 +45,8 @@ "timeago.js": "^4.0.2" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index bc8cd02691..05cc32d681 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -33,7 +33,7 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -46,8 +46,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index abcd48a43f..ea30f15a67 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/test-utils": "^0.1.5", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", @@ -44,8 +44,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 5db8bfdada..a16449d9e3 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-techdocs-backend +## 0.5.1 + +### Patch Changes + +- 8804e8981: Using @backstage/integration package for GitHub/GitLab/Azure tokens and request options. + + Most probably you do not have to make any changes in the app because of this change. + However, if you are using the `DirectoryPreparer` or `CommonGitPreparer` exported by + `@backstage/techdocs-common` package, you now need to add pass in a `config` (from `@backstage/config`) + instance as argument. + + ``` + + const directoryPreparer = new DirectoryPreparer(logger); + const commonGitPreparer = new CommonGitPreparer(logger); + + const directoryPreparer = new DirectoryPreparer(config, logger); + const commonGitPreparer = new CommonGitPreparer(config, logger); + ``` + +- 359f9d2d8: Added configuration schema for the commonly used properties of techdocs and techdocs-backend plugins +- Updated dependencies [8804e8981] + - @backstage/techdocs-common@0.3.1 + ## 0.5.0 ### Minor Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index b0dfcf90f1..ed19e4e23a 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "0.5.0", + "version": "0.5.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "@backstage/backend-common": "^0.4.1", "@backstage/catalog-model": "^0.6.0", "@backstage/config": "^0.1.2", - "@backstage/techdocs-common": "^0.3.0", + "@backstage/techdocs-common": "^0.3.1", "@types/dockerode": "^3.2.1", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -44,7 +44,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.4.3", + "@backstage/cli": "^0.4.4", "supertest": "^4.0.2" }, "files": [ diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 932f551914..8bd79e4139 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-techdocs +## 0.5.2 + +### Patch Changes + +- 359f9d2d8: Added configuration schema for the commonly used properties of techdocs and techdocs-backend plugins +- Updated dependencies [a08c32ced] +- Updated dependencies [7e0b8cac5] +- Updated dependencies [8804e8981] +- Updated dependencies [87c0c53c2] +- Updated dependencies [86c3c652a] +- Updated dependencies [27f2af935] + - @backstage/core-api@0.2.8 + - @backstage/core@0.4.3 + - @backstage/plugin-catalog@0.2.9 + - @backstage/techdocs-common@0.3.1 + ## 0.5.1 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index b3841129fc..b87c158bc4 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "0.5.1", + "version": "0.5.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ }, "dependencies": { "@backstage/catalog-model": "^0.6.0", - "@backstage/core": "^0.4.2", - "@backstage/core-api": "^0.2.7", - "@backstage/plugin-catalog": "^0.2.8", + "@backstage/core": "^0.4.3", + "@backstage/core-api": "^0.2.8", + "@backstage/plugin-catalog": "^0.2.9", "@backstage/test-utils": "^0.1.6", "@backstage/theme": "^0.2.2", - "@backstage/techdocs-common": "^0.3.0", + "@backstage/techdocs-common": "^0.3.1", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", @@ -50,8 +50,8 @@ "sanitize-html": "^1.27.0" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 4c9e8ac4fc..d238242a65 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -30,7 +30,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,8 +41,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json index 2986dbe7bf..21ee3787df 100644 --- a/plugins/welcome/package.json +++ b/plugins/welcome/package.json @@ -30,7 +30,7 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core": "^0.4.2", + "@backstage/core": "^0.4.3", "@backstage/theme": "^0.2.2", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -41,8 +41,8 @@ "react-use": "^15.3.3" }, "devDependencies": { - "@backstage/cli": "^0.4.3", - "@backstage/dev-utils": "^0.1.6", + "@backstage/cli": "^0.4.4", + "@backstage/dev-utils": "^0.1.7", "@backstage/test-utils": "^0.1.6", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^10.4.1", From b9f90951e11a7d3ec478f6c8c24862c2f78f3e9c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Dec 2020 12:44:13 +0100 Subject: [PATCH 74/80] scripts: make all scripts executable --- scripts/create-github-release.js | 0 scripts/migrate-location-types.js | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/create-github-release.js mode change 100644 => 100755 scripts/migrate-location-types.js diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js old mode 100644 new mode 100755 diff --git a/scripts/migrate-location-types.js b/scripts/migrate-location-types.js old mode 100644 new mode 100755 From f5ad8ee03dfe67b51b5f459172b5452318cfa448 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Dec 2020 13:07:12 +0100 Subject: [PATCH 75/80] workflows: use service account for pushing tag in master build --- .github/workflows/master.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index ca63e627e9..4de1ed060a 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -81,7 +81,7 @@ jobs: - uses: Klemensas/action-autotag@1.2.3 if: matrix.node-version == '12.x' with: - GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' + GITHUB_TOKEN: '${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}' package_root: 'packages/core' tag_prefix: 'v' From 8bccc6bec034ac5f21e7303823bffb09ab020585 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 13:32:24 +0100 Subject: [PATCH 76/80] chore: refactor variable names for isomorphic git. --- packages/backend-common/src/scm/git.test.ts | 26 ++++++++-------- packages/backend-common/src/scm/git.ts | 31 ++++++++++--------- packages/techdocs-common/src/helpers.ts | 4 +-- .../src/scaffolder/stages/publish/helpers.ts | 4 +-- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index 96c0f919a7..9af080a782 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -46,15 +46,15 @@ describe('Git', () => { it('should call isomorphic-git with the correct arguments', async () => { const git = Git.fromAuth({}); const dir = 'mockdirectory'; - const remoteName = 'origin'; + const remote = 'origin'; const url = 'git@github.com/something/sads'; - await git.addRemote({ dir, remoteName, url }); + await git.addRemote({ dir, remote, url }); expect(isomorphic.addRemote).toHaveBeenCalledWith({ fs, dir, - remote: remoteName, + remote, url, }); }); @@ -224,18 +224,18 @@ describe('Git', () => { name: 'comitter', email: 'test@backstage.io', }; - const headBranch = 'master'; - const baseBranch = 'production'; + const theirs = 'master'; + const ours = 'production'; const git = Git.fromAuth({}); - await git.merge({ dir, headBranch, baseBranch, author, committer }); + await git.merge({ dir, theirs, ours, author, committer }); expect(isomorphic.merge).toHaveBeenCalledWith({ fs, dir, - ours: baseBranch, - theirs: headBranch, + ours, + theirs, author, committer, }); @@ -244,7 +244,7 @@ describe('Git', () => { describe('push', () => { it('should call isomorphic-git with the correct arguments', async () => { - const remoteName = 'origin'; + const remote = 'origin'; const dir = '/some/mock/dir'; const auth = { username: 'blob', @@ -252,12 +252,12 @@ describe('Git', () => { }; const git = Git.fromAuth(auth); - await git.push({ dir, remoteName }); + await git.push({ dir, remote }); expect(isomorphic.push).toHaveBeenCalledWith({ fs, http, - remote: remoteName, + remote, dir, onProgress: expect.any(Function), headers: { @@ -267,7 +267,7 @@ describe('Git', () => { }); }); it('should pass a function that returns the authorization as the onAuth handler', async () => { - const remoteName = 'origin'; + const remote = 'origin'; const dir = '/some/mock/dir'; const auth = { username: 'blob', @@ -275,7 +275,7 @@ describe('Git', () => { }; const git = Git.fromAuth(auth); - await git.push({ remoteName, dir }); + await git.push({ remote, dir }); const { onAuth } = ((isomorphic.push as unknown) as jest.Mock< typeof isomorphic['push'] diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 690f464d35..31b19ac327 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -46,16 +46,16 @@ export class Git { async addRemote({ dir, url, - remoteName, + remote, }: { dir: string; - remoteName: string; + remote: string; url: string; }) { this.config.logger?.info( - `Creating new remote {dir=${dir},remoteName=${remoteName},url=${url}}`, + `Creating new remote {dir=${dir},remote=${remote},url=${url}}`, ); - return git.addRemote({ fs, dir, remote: remoteName, url }); + return git.addRemote({ fs, dir, remote, url }); } async commit({ @@ -130,34 +130,35 @@ export class Git { // https://isomorphic-git.org/docs/en/merge async merge({ dir, - headBranch, - baseBranch, + theirs, + ours, author, committer, }: { dir: string; - headBranch: string; - baseBranch?: string; + theirs: string; + ours?: string; author: { name: string; email: string }; committer: { name: string; email: string }; }) { this.config.logger?.info( - `Merging branch '${headBranch}' into '${baseBranch}' for repository {dir=${dir}}`, + `Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`, ); - // If baseBranch is undefined, current branch is used. + + // If ours is undefined, current branch is used. return git.merge({ fs, dir, - ours: baseBranch, - theirs: headBranch, + ours, + theirs, author, committer, }); } - async push({ dir, remoteName }: { dir: string; remoteName: string }) { + async push({ dir, remote }: { dir: string; remote: string }) { this.config.logger?.info( - `Pushing directory to remote {dir=${dir},remoteName=${remoteName}}`, + `Pushing directory to remote {dir=${dir},remote=${remote}}`, ); return git.push({ fs, @@ -167,7 +168,7 @@ export class Git { headers: { 'user-agent': 'git/@isomorphic-git', }, - remote: remoteName, + remote: remote, onAuth: this.onAuth, }); } diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts index 8f59ead6fc..f70b0f3840 100644 --- a/packages/techdocs-common/src/helpers.ts +++ b/packages/techdocs-common/src/helpers.ts @@ -170,8 +170,8 @@ export const checkoutGitRepository = async ( await git.fetch({ dir: repositoryTmpPath, remote: 'origin' }); await git.merge({ dir: repositoryTmpPath, - headBranch: `origin/${currentBranchName}`, - baseBranch: currentBranchName || undefined, + theirs: `origin/${currentBranchName}`, + ours: currentBranchName || undefined, author: { name: 'Backstage TechDocs', email: 'techdocs@backstage.io' }, committer: { name: 'Backstage TechDocs', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index bf19c2f56d..796e48b8f8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -59,11 +59,11 @@ export async function initRepoAndPush({ await git.addRemote({ dir, url: remoteUrl, - remoteName: 'origin', + remote: 'origin', }); await git.push({ dir, - remoteName: 'origin', + remote: 'origin', }); } From 00042e73c0b13e445d5847d98e2c9081d83a4951 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 13:37:12 +0100 Subject: [PATCH 77/80] chore: added changeset for changed files --- .changeset/kind-buses-change.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/kind-buses-change.md diff --git a/.changeset/kind-buses-change.md b/.changeset/kind-buses-change.md new file mode 100644 index 0000000000..1d93e27dff --- /dev/null +++ b/.changeset/kind-buses-change.md @@ -0,0 +1,7 @@ +--- +'@backstage/backend-common': patch +'@backstage/techdocs-common': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Moving the Git actions to isomorphic-git instead of the node binding version of nodegit From 3af133465a89528c6cb81bc670ab8ffdcaa8764a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 13:42:54 +0100 Subject: [PATCH 78/80] chore: update value dictionary --- .github/styles/vocab.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index b4be37c057..e2b7f36067 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -134,6 +134,7 @@ neuro newrelic nginx Niklas +nodegit nohoist nonces npm From 82469a5d5a686c0a14da1d2a4712c54184b1a1f0 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 14:13:07 +0100 Subject: [PATCH 79/80] chore: explicitly set the types returned from the functions --- packages/backend-common/src/scm/git.ts | 58 ++++++++++++++++++++------ 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 31b19ac327..9007449d8b 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -13,7 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import git, { ProgressCallback } from 'isomorphic-git'; +import git, { + ProgressCallback, + MergeResult, + ReadCommitResult, +} from 'isomorphic-git'; import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; import { Logger } from 'winston'; @@ -37,7 +41,13 @@ export class Git { }, ) {} - async add({ dir, filepath }: { dir: string; filepath: string }) { + async add({ + dir, + filepath, + }: { + dir: string; + filepath: string; + }): Promise { this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`); return git.add({ fs, dir, filepath }); @@ -51,7 +61,7 @@ export class Git { dir: string; remote: string; url: string; - }) { + }): Promise { this.config.logger?.info( `Creating new remote {dir=${dir},remote=${remote},url=${url}}`, ); @@ -68,7 +78,7 @@ export class Git { message: string; author: { name: string; email: string }; committer: { name: string; email: string }; - }) { + }): Promise { this.config.logger?.info( `Committing file to repo {dir=${dir},message=${message}}`, ); @@ -76,7 +86,7 @@ export class Git { return git.commit({ fs, dir, message, author, committer }); } - async clone({ url, dir }: { url: string; dir: string }) { + async clone({ url, dir }: { url: string; dir: string }): Promise { this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`); return git.clone({ fs, @@ -94,18 +104,30 @@ export class Git { } // https://isomorphic-git.org/docs/en/currentBranch - async currentBranch({ dir, fullName }: { dir: string; fullName?: boolean }) { + async currentBranch({ + dir, + fullName, + }: { + dir: string; + fullName?: boolean; + }): Promise { const fullname = fullName ?? false; return git.currentBranch({ fs, dir, fullname }); } // https://isomorphic-git.org/docs/en/fetch - async fetch({ dir, remote }: { dir: string; remote?: string }) { + async fetch({ + dir, + remote, + }: { + dir: string; + remote?: string; + }): Promise { const remoteValue = remote ?? 'origin'; this.config.logger?.info( `Fetching remote=${remoteValue} for repository {dir=${dir}}`, ); - return git.fetch({ + await git.fetch({ fs, http, dir, @@ -118,7 +140,7 @@ export class Git { }); } - async init({ dir }: { dir: string }) { + async init({ dir }: { dir: string }): Promise { this.config.logger?.info(`Init git repository {dir=${dir}}`); return git.init({ @@ -140,7 +162,7 @@ export class Git { ours?: string; author: { name: string; email: string }; committer: { name: string; email: string }; - }) { + }): Promise { this.config.logger?.info( `Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`, ); @@ -174,12 +196,24 @@ export class Git { } // https://isomorphic-git.org/docs/en/readCommit - async readCommit({ dir, sha }: { dir: string; sha: string }) { + async readCommit({ + dir, + sha, + }: { + dir: string; + sha: string; + }): Promise { return git.readCommit({ fs, dir, oid: sha }); } // https://isomorphic-git.org/docs/en/resolveRef - async resolveRef({ dir, ref }: { dir: string; ref: string }) { + async resolveRef({ + dir, + ref, + }: { + dir: string; + ref: string; + }): Promise { return git.resolveRef({ fs, dir, ref }); } From 28bdc0328c084caaef95c5621f27046398339b7a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 29 Dec 2020 14:26:28 +0100 Subject: [PATCH 80/80] chore: rework types slightly for string or undefined instead of void --- packages/backend-common/src/scm/git.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 9007449d8b..b0a1df6541 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -110,9 +110,11 @@ export class Git { }: { dir: string; fullName?: boolean; - }): Promise { + }): Promise { const fullname = fullName ?? false; - return git.currentBranch({ fs, dir, fullname }); + return git.currentBranch({ fs, dir, fullname }) as Promise< + string | undefined + >; } // https://isomorphic-git.org/docs/en/fetch