From d5ab1b32dbb159b67ba6916a8384e64e01672ebd Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 4 Dec 2023 14:50:33 +0100 Subject: [PATCH 01/15] fix: scaffolder module should depend on -node library Signed-off-by: blam --- packages/cli/templates/scaffolder-module/package.json.hbs | 2 +- .../templates/scaffolder-module/src/actions/example/example.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/templates/scaffolder-module/package.json.hbs b/packages/cli/templates/scaffolder-module/package.json.hbs index 618e953b74..0ebe5dd5f4 100644 --- a/packages/cli/templates/scaffolder-module/package.json.hbs +++ b/packages/cli/templates/scaffolder-module/package.json.hbs @@ -29,7 +29,7 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/plugin-scaffolder-backend": "{{versionQuery '@backstage/plugin-scaffolder-backend'}}" + "@backstage/plugin-scaffolder-node": "{{versionQuery '@backstage/plugin-scaffolder-node'}}" }, "devDependencies": { "@backstage/backend-common": "{{versionQuery '@backstage/backend-common'}}", diff --git a/packages/cli/templates/scaffolder-module/src/actions/example/example.ts b/packages/cli/templates/scaffolder-module/src/actions/example/example.ts index c04132e755..2b05c7fe38 100644 --- a/packages/cli/templates/scaffolder-module/src/actions/example/example.ts +++ b/packages/cli/templates/scaffolder-module/src/actions/example/example.ts @@ -1,4 +1,4 @@ -import { createTemplateAction } from '@backstage/plugin-scaffolder-backend'; +import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; /** * Creates an `acme:example` Scaffolder action. From 8ecb0b9a20e090af6a462c51ab3f773fd3ddad5f Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:31:05 +0100 Subject: [PATCH 02/15] chore: created github module Signed-off-by: blam --- .../.eslintrc.js | 1 + .../README.md | 5 + .../package.json | 49 ++++++ .../src/actions/gitHelpers.ts | 143 ++++++++++++++++++ .../actions}/gitHubEnvironment.examples.ts | 0 .../src/actions}/github.examples.test.ts | 28 +++- .../src/actions}/github.examples.ts | 0 .../src/actions}/github.test.ts | 28 +++- .../src/actions}/github.ts | 12 +- .../githubActionsDispatch.examples.test.ts | 0 .../githubActionsDispatch.examples.ts | 0 .../actions}/githubActionsDispatch.test.ts | 0 .../src/actions}/githubActionsDispatch.ts | 6 +- .../actions}/githubDeployKey.examples.test.ts | 0 .../src/actions}/githubDeployKey.examples.ts | 0 .../src/actions}/githubDeployKey.test.ts | 0 .../src/actions}/githubDeployKey.ts | 6 +- .../githubEnvironment.examples.test.ts | 0 .../src/actions}/githubEnvironment.test.ts | 0 .../src/actions}/githubEnvironment.ts | 6 +- .../githubIssuesLabel.examples.test.ts | 0 .../actions}/githubIssuesLabel.examples.ts | 0 .../src/actions}/githubIssuesLabel.test.ts | 0 .../src/actions}/githubIssuesLabel.ts | 6 +- .../githubPullRequest.examples.test.ts | 0 .../actions}/githubPullRequest.examples.ts | 0 .../src/actions}/githubPullRequest.test.ts | 0 .../src/actions}/githubPullRequest.ts | 14 +- .../githubRepoCreate.examples.test.ts | 9 +- .../src/actions}/githubRepoCreate.examples.ts | 0 .../src/actions}/githubRepoCreate.test.ts | 9 +- .../src/actions}/githubRepoCreate.ts | 6 +- .../actions}/githubRepoPush.examples.test.ts | 26 +++- .../src/actions}/githubRepoPush.examples.ts | 0 .../src/actions}/githubRepoPush.test.ts | 30 +++- .../src/actions}/githubRepoPush.ts | 6 +- .../actions}/githubWebhook.examples.test.ts | 0 .../src/actions}/githubWebhook.examples.ts | 0 .../src/actions}/githubWebhook.test.ts | 0 .../src/actions}/githubWebhook.ts | 6 +- .../src/actions}/helpers.ts | 24 ++- .../src/actions}/index.ts | 3 + .../src/actions}/inputProperties.ts | 0 .../src/actions}/outputProperties.ts | 0 .../src/index.ts | 23 +++ 45 files changed, 393 insertions(+), 53 deletions(-) create mode 100644 plugins/scaffolder-backend-module-github/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-github/README.md create mode 100644 plugins/scaffolder-backend-module-github/package.json create mode 100644 plugins/scaffolder-backend-module-github/src/actions/gitHelpers.ts rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/gitHubEnvironment.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/github.examples.test.ts (85%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/github.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/github.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/github.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubActionsDispatch.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubActionsDispatch.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubActionsDispatch.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubActionsDispatch.ts (96%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubDeployKey.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubDeployKey.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubDeployKey.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubDeployKey.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubEnvironment.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubEnvironment.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubEnvironment.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubIssuesLabel.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubIssuesLabel.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubIssuesLabel.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubIssuesLabel.ts (96%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/githubPullRequest.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/githubPullRequest.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/githubPullRequest.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-github/src/actions}/githubPullRequest.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoCreate.examples.test.ts (96%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoCreate.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoCreate.test.ts (99%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoCreate.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoPush.examples.test.ts (85%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoPush.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoPush.test.ts (96%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubRepoPush.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubWebhook.examples.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubWebhook.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubWebhook.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/githubWebhook.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/helpers.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/index.ts (89%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/inputProperties.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/github => scaffolder-backend-module-github/src/actions}/outputProperties.ts (100%) create mode 100644 plugins/scaffolder-backend-module-github/src/index.ts diff --git a/plugins/scaffolder-backend-module-github/.eslintrc.js b/plugins/scaffolder-backend-module-github/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-backend-module-github/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend-module-github/README.md b/plugins/scaffolder-backend-module-github/README.md new file mode 100644 index 0000000000..ba4b3a8787 --- /dev/null +++ b/plugins/scaffolder-backend-module-github/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-scaffolder-backend-module-github + +The github module for [@backstage/plugin-scaffolder-backend](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend). + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json new file mode 100644 index 0000000000..9779ea8040 --- /dev/null +++ b/plugins/scaffolder-backend-module-github/package.json @@ -0,0 +1,49 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-github", + "description": "The github module for @backstage/plugin-scaffolder-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/plugin-scaffolder-node": "workspace:^", + "@octokit/webhooks": "^10.0.0", + "libsodium-wrappers": "^0.7.11", + "octokit": "^2.0.0", + "octokit-plugin-create-pull-request": "^3.10.0", + "winston": "^3.2.1", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@types/libsodium-wrappers": "^0.7.10", + "fs-extra": "10.1.0", + "jest-when": "^3.1.0", + "jsonschema": "^1.2.6" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend-module-github/src/actions/gitHelpers.ts b/plugins/scaffolder-backend-module-github/src/actions/gitHelpers.ts new file mode 100644 index 0000000000..f94cf1e71c --- /dev/null +++ b/plugins/scaffolder-backend-module-github/src/actions/gitHelpers.ts @@ -0,0 +1,143 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { Config } from '@backstage/config'; +import { assertError } from '@backstage/errors'; +import { Octokit } from 'octokit'; +import { Logger } from 'winston'; + +type BranchProtectionOptions = { + client: Octokit; + owner: string; + repoName: string; + logger: Logger; + requireCodeOwnerReviews: boolean; + requiredStatusCheckContexts?: string[]; + bypassPullRequestAllowances?: { + users?: string[]; + teams?: string[]; + apps?: string[]; + }; + requiredApprovingReviewCount?: number; + restrictions?: { + users: string[]; + teams: string[]; + apps?: string[]; + }; + requireBranchesToBeUpToDate?: boolean; + requiredConversationResolution?: boolean; + defaultBranch?: string; + enforceAdmins?: boolean; + dismissStaleReviews?: boolean; + requiredCommitSigning?: boolean; +}; + +export const enableBranchProtectionOnDefaultRepoBranch = async ({ + repoName, + client, + owner, + logger, + requireCodeOwnerReviews, + bypassPullRequestAllowances, + requiredApprovingReviewCount, + restrictions, + requiredStatusCheckContexts = [], + requireBranchesToBeUpToDate = true, + requiredConversationResolution = false, + defaultBranch = 'master', + enforceAdmins = true, + dismissStaleReviews = false, + requiredCommitSigning = false, +}: BranchProtectionOptions): Promise => { + const tryOnce = async () => { + try { + await client.rest.repos.updateBranchProtection({ + mediaType: { + /** + * 👇 we need this preview because allowing a custom + * reviewer count on branch protection is a preview + * feature + * + * More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews + */ + previews: ['luke-cage-preview'], + }, + owner, + repo: repoName, + branch: defaultBranch, + required_status_checks: { + strict: requireBranchesToBeUpToDate, + contexts: requiredStatusCheckContexts, + }, + restrictions: restrictions ?? null, + enforce_admins: enforceAdmins, + required_pull_request_reviews: { + required_approving_review_count: requiredApprovingReviewCount, + require_code_owner_reviews: requireCodeOwnerReviews, + bypass_pull_request_allowances: bypassPullRequestAllowances, + dismiss_stale_reviews: dismissStaleReviews, + }, + required_conversation_resolution: requiredConversationResolution, + }); + + if (requiredCommitSigning) { + await client.rest.repos.createCommitSignatureProtection({ + owner, + repo: repoName, + branch: defaultBranch, + }); + } + } catch (e) { + assertError(e); + if ( + e.message.includes( + 'Upgrade to GitHub Pro or make this repository public to enable this feature', + ) + ) { + logger.warn( + 'Branch protection was not enabled as it requires GitHub Pro for private repositories', + ); + } else { + throw e; + } + } + }; + + try { + await tryOnce(); + } catch (e) { + if (!e.message.includes('Branch not found')) { + throw e; + } + + // GitHub has eventual consistency. Fail silently, wait, and try again. + await new Promise(resolve => setTimeout(resolve, 600)); + await tryOnce(); + } +}; + +export function getGitCommitMessage( + gitCommitMessage: string | undefined, + config: Config, +): string | undefined { + return gitCommitMessage + ? gitCommitMessage + : config.getOptionalString('scaffolder.defaultCommitMessage'); +} + +export function entityRefToName(name: string): string { + return name.replace(/^.*[:/]/g, ''); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/gitHubEnvironment.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/gitHubEnvironment.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/gitHubEnvironment.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts similarity index 85% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts index 4d87ec97c4..7ea5e025ce 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts @@ -13,9 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../helpers'); +jest.mock('./gitHelpers', () => { + return { + ...jest.requireActual('./gitHelpers'), + entityRefToName: jest.fn(), + }; +}); -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); + +import { + TemplateAction, + initRepoAndPush, +} from '@backstage/plugin-scaffolder-node'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { @@ -24,10 +44,10 @@ import { ScmIntegrations, } from '@backstage/integration'; import { PassThrough } from 'stream'; -import { entityRefToName, initRepoAndPush } from '../helpers'; import { createPublishGithubAction } from './github'; import { examples } from './github.examples'; import yaml from 'yaml'; +import { entityRefToName } from './gitHelpers'; const publicKey = '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU='; @@ -76,7 +96,7 @@ describe('publish:github', () => { }); const { entityRefToName: realFamiliarizeEntityName } = - jest.requireActual('../helpers'); + jest.requireActual('./helpers'); const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/github.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend-module-github/src/actions/github.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/github.test.ts index e15d085cbf..c22d8ca7c3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/github.test.ts @@ -13,7 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../helpers'); +jest.mock('./gitHelpers', () => { + return { + ...jest.requireActual('./gitHelpers'), + enableBranchProtectionOnDefaultRepoBranch: jest.fn(), + entityRefToName: jest.fn(), + }; +}); + +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { getVoidLogger } from '@backstage/backend-common'; @@ -25,12 +43,12 @@ import { } from '@backstage/integration'; import { when } from 'jest-when'; import { PassThrough } from 'stream'; +import { createPublishGithubAction } from './github'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { enableBranchProtectionOnDefaultRepoBranch, entityRefToName, - initRepoAndPush, -} from '../helpers'; -import { createPublishGithubAction } from './github'; +} from './gitHelpers'; const publicKey = '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU='; @@ -79,7 +97,7 @@ describe('publish:github', () => { }); const { entityRefToName: realFamiliarizeEntityName } = - jest.requireActual('../helpers'); + jest.requireActual('./gitHelpers'); const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend-module-github/src/actions/github.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts rename to plugins/scaffolder-backend-module-github/src/actions/github.ts index e5b6071863..62f657b01c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/github.ts @@ -21,15 +21,17 @@ import { ScmIntegrationRegistry, } from '@backstage/integration'; import { Octokit } from 'octokit'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { createGithubRepoWithCollaboratorsAndTopics, getOctokitOptions, initRepoPushAndProtect, -} from '../github/helpers'; -import * as inputProps from '../github/inputProperties'; -import * as outputProps from '../github/outputProperties'; -import { parseRepoUrl } from './util'; +} from './helpers'; +import * as inputProps from './inputProperties'; +import * as outputProps from './outputProperties'; import { examples } from './github.examples'; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.ts similarity index 96% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.ts index 6623ee1f27..0d24b74927 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubActionsDispatch.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubActionsDispatch.ts @@ -19,9 +19,11 @@ import { GithubCredentialsProvider, ScmIntegrations, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { Octokit } from 'octokit'; -import { parseRepoUrl } from '../publish/util'; import { getOctokitOptions } from './helpers'; import { examples } from './githubActionsDispatch.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts index 1db9746bb4..ba55b6a1fb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubDeployKey.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts @@ -15,9 +15,11 @@ */ import { InputError } from '@backstage/errors'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { parseRepoUrl } from '../publish/util'; import { getOctokitOptions } from './helpers'; import { Octokit } from 'octokit'; import Sodium from 'libsodium-wrappers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.ts index 16859d9a26..7f6f9f7fa3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubEnvironment.ts @@ -15,9 +15,11 @@ */ import { InputError } from '@backstage/errors'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { parseRepoUrl } from '../publish/util'; import { getOctokitOptions } from './helpers'; import { Octokit } from 'octokit'; import Sodium from 'libsodium-wrappers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.ts similarity index 96% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.ts index 73a65ffb14..90f5a89dc7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubIssuesLabel.ts @@ -18,11 +18,13 @@ import { GithubCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { assertError, InputError } from '@backstage/errors'; import { Octokit } from 'octokit'; import { getOctokitOptions } from './helpers'; -import { parseRepoUrl } from '../publish/util'; import { examples } from './githubIssuesLabel.examples'; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts index 3b6e7c3ced..00e584226f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts @@ -15,21 +15,21 @@ */ import path from 'path'; -import { parseRepoUrl } from './util'; import { GithubCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, + SerializedFile, + serializeDirectoryContents, +} from '@backstage/plugin-scaffolder-node'; import { Octokit } from 'octokit'; import { InputError, CustomErrorBase } from '@backstage/errors'; import { resolveSafeChildPath } from '@backstage/backend-common'; import { createPullRequest } from 'octokit-plugin-create-pull-request'; -import { getOctokitOptions } from '../github/helpers'; -import { - SerializedFile, - serializeDirectoryContents, -} from '../../../../lib/files'; +import { getOctokitOptions } from './helpers'; import { Logger } from 'winston'; import { examples } from './githubPullRequest.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts similarity index 96% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts index 71bbc7c1c6..2377e9a7eb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.test.ts @@ -16,7 +16,12 @@ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -jest.mock('../helpers'); +jest.mock('./gitHelpers', () => { + return { + ...jest.requireActual('./gitHelpers'), + entityRefToName: jest.fn(), + }; +}); import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; @@ -27,7 +32,7 @@ import { } from '@backstage/integration'; import { PassThrough } from 'stream'; import { createGithubRepoCreateAction } from './githubRepoCreate'; -import { entityRefToName } from '../helpers'; +import { entityRefToName } from './gitHelpers'; import yaml from 'yaml'; import { examples } from './githubRepoCreate.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts similarity index 99% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts index b5b31d0773..4cb007275e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.test.ts @@ -16,7 +16,12 @@ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -jest.mock('../helpers'); +jest.mock('./gitHelpers', () => { + return { + ...jest.requireActual('./gitHelpers'), + entityRefToName: jest.fn(), + }; +}); import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; @@ -28,7 +33,7 @@ import { import { when } from 'jest-when'; import { PassThrough } from 'stream'; import { createGithubRepoCreateAction } from './githubRepoCreate'; -import { entityRefToName } from '../helpers'; +import { entityRefToName } from './gitHelpers'; const publicKey = '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvvcCU='; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.ts index e0fde3b193..735919794f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoCreate.ts @@ -20,8 +20,10 @@ import { ScmIntegrationRegistry, } from '@backstage/integration'; import { Octokit } from 'octokit'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; -import { parseRepoUrl } from '../publish/util'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { createGithubRepoWithCollaboratorsAndTopics, getOctokitOptions, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts similarity index 85% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts index 84d489272d..8f8c9bf8af 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.test.ts @@ -13,7 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); + +import { + TemplateAction, + initRepoAndPush, +} from '@backstage/plugin-scaffolder-node'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { @@ -22,7 +37,6 @@ import { ScmIntegrations, } from '@backstage/integration'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; import { createGithubRepoPushAction } from './githubRepoPush'; import { examples } from './githubRepoPush.examples'; import yaml from 'yaml'; @@ -48,7 +62,12 @@ jest.mock('@backstage/backend-common', () => ({ getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger, })); -jest.mock('../helpers'); +jest.mock('./helpers', () => { + return { + ...jest.requireActual('./helpers'), + entityRefToName: jest.fn(), + }; +}); const initRepoAndPushMocked = initRepoAndPush as jest.Mock< Promise<{ commitHash: string }> @@ -98,6 +117,7 @@ describe('github:repo:push examples', () => { githubCredentialsProvider = DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubRepoPushAction({ integrations, config, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts similarity index 96% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts index 8630dfab56..e16da0981d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.test.ts @@ -35,9 +35,30 @@ jest.mock('@backstage/backend-common', () => ({ getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger, })); -jest.mock('../helpers'); +jest.mock('./gitHelpers', () => { + return { + ...jest.requireActual('./gitHelpers'), + entityRefToName: jest.fn(), + enableBranchProtectionOnDefaultRepoBranch: jest.fn(), + }; +}); -import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); + +import { + TemplateAction, + initRepoAndPush, +} from '@backstage/plugin-scaffolder-node'; import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { @@ -46,10 +67,7 @@ import { ScmIntegrations, } from '@backstage/integration'; import { PassThrough } from 'stream'; -import { - enableBranchProtectionOnDefaultRepoBranch, - initRepoAndPush, -} from '../helpers'; +import { enableBranchProtectionOnDefaultRepoBranch } from './gitHelpers'; import { createGithubRepoPushAction } from './githubRepoPush'; const initRepoAndPushMocked = initRepoAndPush as jest.Mock< diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.ts index e30eedad02..5b9db78f48 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoPush.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubRepoPush.ts @@ -21,8 +21,10 @@ import { ScmIntegrationRegistry, } from '@backstage/integration'; import { Octokit } from 'octokit'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; -import { parseRepoUrl } from '../publish/util'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { getOctokitOptions, initRepoPushAndProtect } from './helpers'; import * as inputProps from './inputProperties'; import * as outputProps from './outputProperties'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.examples.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubWebhook.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.test.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubWebhook.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts rename to plugins/scaffolder-backend-module-github/src/actions/githubWebhook.ts index 5589c951a5..984029076e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubWebhook.ts @@ -18,12 +18,14 @@ import { GithubCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { emitterEventNames } from '@octokit/webhooks'; import { assertError, InputError } from '@backstage/errors'; import { Octokit } from 'octokit'; import { getOctokitOptions } from './helpers'; -import { parseRepoUrl } from '../publish/util'; import { examples } from './githubWebhook.examples'; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend-module-github/src/actions/helpers.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts rename to plugins/scaffolder-backend-module-github/src/actions/helpers.ts index d91f3bf3a2..c6c4bd4ce5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/helpers.ts @@ -24,13 +24,18 @@ import { import { OctokitOptions } from '@octokit/core/dist-types/types'; import { Octokit } from 'octokit'; import { Logger } from 'winston'; + +import { + getRepoSourceDirectory, + initRepoAndPush, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; + +import Sodium from 'libsodium-wrappers'; import { enableBranchProtectionOnDefaultRepoBranch, - initRepoAndPush, -} from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from '../publish/util'; -import { entityRefToName } from '../../builtin/helpers'; -import Sodium from 'libsodium-wrappers'; + entityRefToName, +} from './gitHelpers'; const DEFAULT_TIMEOUT_MS = 60_000; @@ -422,3 +427,12 @@ async function validateAccessTeam(client: Octokit, access: string) { } } } + +export function getGitCommitMessage( + gitCommitMessage: string | undefined, + config: Config, +): string | undefined { + return gitCommitMessage + ? gitCommitMessage + : config.getOptionalString('scaffolder.defaultCommitMessage'); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts b/plugins/scaffolder-backend-module-github/src/actions/index.ts similarity index 89% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts rename to plugins/scaffolder-backend-module-github/src/actions/index.ts index ecc8ce59f2..9c3927f31d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/index.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/index.ts @@ -21,3 +21,6 @@ export { createGithubRepoPushAction } from './githubRepoPush'; export { createGithubWebhookAction } from './githubWebhook'; export { createGithubDeployKeyAction } from './githubDeployKey'; export { createGithubEnvironmentAction } from './githubEnvironment'; + +export { createPublishGithubPullRequestAction } from './githubPullRequest'; +export { createPublishGithubAction } from './github'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/inputProperties.ts b/plugins/scaffolder-backend-module-github/src/actions/inputProperties.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/inputProperties.ts rename to plugins/scaffolder-backend-module-github/src/actions/inputProperties.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/outputProperties.ts b/plugins/scaffolder-backend-module-github/src/actions/outputProperties.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/outputProperties.ts rename to plugins/scaffolder-backend-module-github/src/actions/outputProperties.ts diff --git a/plugins/scaffolder-backend-module-github/src/index.ts b/plugins/scaffolder-backend-module-github/src/index.ts new file mode 100644 index 0000000000..b4d8dbcb6d --- /dev/null +++ b/plugins/scaffolder-backend-module-github/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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. + */ + +/** + * The github module for @backstage/plugin-scaffolder-backend. + * + * @packageDocumentation + */ + +export * from './actions'; From f212ff40a97f166caf904bf93f18c125e859fcd1 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:32:28 +0100 Subject: [PATCH 03/15] chore: create azure module Signed-off-by: blam --- .../.eslintrc.js | 1 + .../scaffolder-backend-module-azure/README.md | 5 +++ .../package.json | 40 +++++++++++++++++++ .../src/actions}/azure.examples.test.ts | 5 ++- .../src/actions}/azure.examples.ts | 0 .../src/actions}/azure.test.ts | 5 ++- .../src/actions}/azure.ts | 9 +++-- .../src/actions/index.ts | 16 ++++++++ .../src/index.ts | 23 +++++++++++ 9 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 plugins/scaffolder-backend-module-azure/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-azure/README.md create mode 100644 plugins/scaffolder-backend-module-azure/package.json rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-azure/src/actions}/azure.examples.test.ts (95%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-azure/src/actions}/azure.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-azure/src/actions}/azure.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-azure/src/actions}/azure.ts (97%) create mode 100644 plugins/scaffolder-backend-module-azure/src/actions/index.ts create mode 100644 plugins/scaffolder-backend-module-azure/src/index.ts diff --git a/plugins/scaffolder-backend-module-azure/.eslintrc.js b/plugins/scaffolder-backend-module-azure/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend-module-azure/README.md b/plugins/scaffolder-backend-module-azure/README.md new file mode 100644 index 0000000000..505ef36db1 --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-scaffolder-backend-module-azure + +The azure module for [@backstage/plugin-scaffolder-backend](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend). + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/scaffolder-backend-module-azure/package.json b/plugins/scaffolder-backend-module-azure/package.json new file mode 100644 index 0000000000..4bc4209dee --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/package.json @@ -0,0 +1,40 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-azure", + "description": "The azure module for @backstage/plugin-scaffolder-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/plugin-scaffolder-node": "workspace:^", + "azure-devops-node-api": "^11.0.1", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts similarity index 95% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts rename to plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts index e4fd18ef59..27989650ce 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts +++ b/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.test.ts @@ -21,7 +21,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { getVoidLogger } from '@backstage/backend-common'; import { WebApi } from 'azure-devops-node-api'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { examples } from './azure.examples'; jest.mock('azure-devops-node-api', () => ({ @@ -29,8 +29,9 @@ jest.mock('azure-devops-node-api', () => ({ getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}), })); -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.ts rename to plugins/scaffolder-backend-module-azure/src/actions/azure.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts rename to plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts index 9b7673ea29..4401e01007 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend-module-azure/src/actions/azure.test.ts @@ -19,8 +19,9 @@ jest.mock('azure-devops-node-api', () => ({ getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}), })); -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -36,7 +37,7 @@ import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { WebApi } from 'azure-devops-node-api'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; describe('publish:azure', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend-module-azure/src/actions/azure.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts rename to plugins/scaffolder-backend-module-azure/src/actions/azure.ts index a7df154687..e90cfeade4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend-module-azure/src/actions/azure.ts @@ -19,15 +19,18 @@ import { DefaultAzureDevOpsCredentialsProvider, ScmIntegrationRegistry, } from '@backstage/integration'; -import { initRepoAndPush } from '../helpers'; +import { + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, + createTemplateAction, +} from '@backstage/plugin-scaffolder-node'; import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { getBearerHandler, getPersonalAccessTokenHandler, WebApi, } from 'azure-devops-node-api'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { Config } from '@backstage/config'; import { examples } from './azure.examples'; diff --git a/plugins/scaffolder-backend-module-azure/src/actions/index.ts b/plugins/scaffolder-backend-module-azure/src/actions/index.ts new file mode 100644 index 0000000000..76ea7c2f07 --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/src/actions/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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 * from './azure'; diff --git a/plugins/scaffolder-backend-module-azure/src/index.ts b/plugins/scaffolder-backend-module-azure/src/index.ts new file mode 100644 index 0000000000..d64ca54077 --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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. + */ + +/** + * The azure module for @backstage/plugin-scaffolder-backend. + * + * @packageDocumentation + */ + +export * from './actions'; From fbb1071987616a783baf117a91d7d8317ffb46f5 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:33:02 +0100 Subject: [PATCH 04/15] chore: create bitbucket modules Signed-off-by: blam --- .../.eslintrc.js | 1 + .../README.md | 5 +++ .../package.json | 42 +++++++++++++++++++ .../src/actions}/bitbucket.examples.test.ts | 5 ++- .../src/actions}/bitbucket.examples.ts | 0 .../src/actions}/bitbucket.test.ts | 6 +-- .../src/actions}/bitbucket.ts | 9 ++-- .../src/actions}/bitbucketCloud.test.ts | 5 ++- .../src/actions}/bitbucketCloud.ts | 10 +++-- .../src/actions}/bitbucketServer.test.ts | 5 ++- .../src/actions}/bitbucketServer.ts | 10 +++-- .../bitbucketServerPullRequest.test.ts | 3 +- .../actions}/bitbucketServerPullRequest.ts | 6 ++- .../src/actions/index.ts | 19 +++++++++ .../src/index.ts | 23 ++++++++++ 15 files changed, 128 insertions(+), 21 deletions(-) create mode 100644 plugins/scaffolder-backend-module-bitbucket/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-bitbucket/README.md create mode 100644 plugins/scaffolder-backend-module-bitbucket/package.json rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucket.examples.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucket.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucket.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucket.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketCloud.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketCloud.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketServer.test.ts (99%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketServer.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketServerPullRequest.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-bitbucket/src/actions}/bitbucketServerPullRequest.ts (98%) create mode 100644 plugins/scaffolder-backend-module-bitbucket/src/actions/index.ts create mode 100644 plugins/scaffolder-backend-module-bitbucket/src/index.ts diff --git a/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js b/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend-module-bitbucket/README.md b/plugins/scaffolder-backend-module-bitbucket/README.md new file mode 100644 index 0000000000..90b8680e80 --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-scaffolder-backend-module-bitbucket + +The bitbucket module for [@backstage/plugin-scaffolder-backend](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend). + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/scaffolder-backend-module-bitbucket/package.json b/plugins/scaffolder-backend-module-bitbucket/package.json new file mode 100644 index 0000000000..4c92ce01a2 --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/package.json @@ -0,0 +1,42 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-bitbucket", + "description": "The bitbucket module for @backstage/plugin-scaffolder-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/plugin-scaffolder-node": "workspace:^", + "node-fetch": "^2.6.7", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "msw": "^1.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.examples.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.examples.test.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts index a1564d0498..73325ab5bf 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.examples.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -33,7 +34,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import yaml from 'yaml'; import { sep } from 'path'; import { examples } from './bitbucket.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.examples.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.examples.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts index 5d46a28a60..d6e068c039 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -24,7 +25,6 @@ jest.mock('../helpers', () => { }), }; }); - import { createPublishBitbucketAction } from './bitbucket'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -33,7 +33,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; describe('publish:bitbucket', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts index a4d664e0e7..76fe1de5df 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucket.ts @@ -19,10 +19,13 @@ import { BitbucketIntegrationConfig, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import fetch, { Response, RequestInit } from 'node-fetch'; -import { initRepoAndPush } from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; import { examples } from './bitbucket.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.test.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.test.ts index 3159bfc562..7045d58e01 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -33,7 +34,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; describe('publish:bitbucketCloud', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.ts index 00529d5856..c69ae0b147 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketCloud.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketCloud.ts @@ -16,10 +16,14 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import fetch, { Response, RequestInit } from 'node-fetch'; -import { initRepoAndPush } from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; + import { Config } from '@backstage/config'; const createRepository = async (opts: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.test.ts similarity index 99% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.test.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.test.ts index 67a29210fc..ab7b52996f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -33,7 +34,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; describe('publish:bitbucketServer', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.ts index 66b7a46f77..31125deab2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServer.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServer.ts @@ -19,10 +19,14 @@ import { getBitbucketServerRequestOptions, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import fetch, { Response, RequestInit } from 'node-fetch'; -import { initRepoAndPush } from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; + import { Config } from '@backstage/config'; const createRepository = async (opts: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.test.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.test.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.test.ts index af3999097f..3af47853c3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.test.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.ts rename to plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.ts index 79711b9d69..dc75145ebc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucketServerPullRequest.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/bitbucketServerPullRequest.ts @@ -19,9 +19,11 @@ import { getBitbucketServerRequestOptions, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import fetch, { RequestInit, Response } from 'node-fetch'; -import { parseRepoUrl } from './util'; import { Config } from '@backstage/config'; const createPullRequest = async (opts: { diff --git a/plugins/scaffolder-backend-module-bitbucket/src/actions/index.ts b/plugins/scaffolder-backend-module-bitbucket/src/actions/index.ts new file mode 100644 index 0000000000..1093b07785 --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/src/actions/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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 * from './bitbucket'; +export * from './bitbucketCloud'; +export * from './bitbucketServer'; +export * from './bitbucketServerPullRequest'; diff --git a/plugins/scaffolder-backend-module-bitbucket/src/index.ts b/plugins/scaffolder-backend-module-bitbucket/src/index.ts new file mode 100644 index 0000000000..6448b82c8b --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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. + */ + +/** + * The bitbucket module for @backstage/plugin-scaffolder-backend. + * + * @packageDocumentation + */ + +export * from './actions'; From 88c9a158c2adbb2374d29835359bda05dfd0b6ce Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:45:30 +0100 Subject: [PATCH 05/15] chore: added gitlab module Signed-off-by: blam --- .../package.json | 6 ++++-- .../src/actions}/gitlab.examples.test.ts | 5 +++-- .../src/actions}/gitlab.examples.ts | 0 .../src/actions}/gitlab.test.ts | 5 +++-- .../src/actions}/gitlab.ts | 7 +++++-- .../src/actions}/gitlabMergeRequest.test.ts | 0 .../src/actions}/gitlabMergeRequest.ts | 8 ++++--- .../src/actions/index.ts | 21 +++++++++++++++++++ .../src/index.ts | 5 +---- 9 files changed, 42 insertions(+), 15 deletions(-) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlab.examples.test.ts (94%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlab.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlab.test.ts (98%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlab.ts (99%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlabMergeRequest.test.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gitlab/src/actions}/gitlabMergeRequest.ts (97%) create mode 100644 plugins/scaffolder-backend-module-gitlab/src/actions/index.ts diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 94641be81c..d67aefbd27 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -31,16 +31,18 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { + "@backstage/backend-common": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", - "@gitbeaker/node": "^35.8.0", + "@gitbeaker/core": "^35.8.0", + "@gitbeaker/node": "^35.1.0", "yaml": "^2.0.0", "zod": "^3.21.4" }, "devDependencies": { - "@backstage/backend-common": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^" }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts similarity index 94% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.test.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts index 5d58431c61..e5aa610ebc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.test.ts @@ -15,8 +15,9 @@ */ import yaml from 'yaml'; -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -27,11 +28,11 @@ jest.mock('../helpers', () => { }); import { createPublishGitlabAction } from './gitlab'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; import { examples } from './gitlab.examples'; const mockGitlabClient = { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts similarity index 98% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts index b2f3dc6480..5aca0a73e5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -30,7 +31,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; const mockGitlabClient = { Namespaces: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.ts similarity index 99% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.ts index 6d86841a20..22f875ca8d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlab.ts @@ -18,8 +18,11 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { Gitlab } from '@gitbeaker/node'; -import { initRepoAndPush } from '../helpers'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; +import { + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import { Config } from '@backstage/config'; import { examples } from './gitlab.examples'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts rename to plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.ts index 8abb53288c..f6c4734729 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/gitlabMergeRequest.ts @@ -14,15 +14,17 @@ * limitations under the License. */ -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { + createTemplateAction, + parseRepoUrl, + serializeDirectoryContents, +} from '@backstage/plugin-scaffolder-node'; import { Gitlab } from '@gitbeaker/node'; import { Types } from '@gitbeaker/core'; import path from 'path'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { InputError } from '@backstage/errors'; -import { parseRepoUrl } from './util'; import { resolveSafeChildPath } from '@backstage/backend-common'; -import { serializeDirectoryContents } from '../../../../lib/files'; /** * Create a new action that creates a gitlab merge request. diff --git a/plugins/scaffolder-backend-module-gitlab/src/actions/index.ts b/plugins/scaffolder-backend-module-gitlab/src/actions/index.ts new file mode 100644 index 0000000000..e915293860 --- /dev/null +++ b/plugins/scaffolder-backend-module-gitlab/src/actions/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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 * from './createGitlabGroupEnsureExistsAction'; +export * from './createGitlabProjectDeployTokenAction'; +export * from './createGitlabProjectAccessTokenAction'; +export * from './createGitlabProjectVariableAction'; +export * from './gitlab'; +export * from './gitlabMergeRequest'; diff --git a/plugins/scaffolder-backend-module-gitlab/src/index.ts b/plugins/scaffolder-backend-module-gitlab/src/index.ts index 4fd4dee35b..844f753344 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/index.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/index.ts @@ -19,7 +19,4 @@ * * @packageDocumentation */ -export * from './actions/createGitlabGroupEnsureExistsAction'; -export * from './actions/createGitlabProjectDeployTokenAction'; -export * from './actions/createGitlabProjectAccessTokenAction'; -export * from './actions/createGitlabProjectVariableAction'; +export * from './actions'; From 81f57ff279193aca741dfcb0c8822f7401e64218 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:45:46 +0100 Subject: [PATCH 06/15] chore: move some other things around a little bit Signed-off-by: blam --- plugins/scaffolder-backend/package.json | 11 +- .../actions/builtin/publish/util.ts | 119 +--------------- plugins/scaffolder-node/src/actions/index.ts | 2 + .../src/actions/repoHelpers.ts | 127 ++++++++++++++++++ plugins/scaffolder-node/src/actions/util.ts | 112 +++++++++++++++ .../deserializeDirectoryContents.test.ts | 0 .../files/deserializeDirectoryContents.ts | 0 .../src}/files/index.ts | 0 .../files/serializeDirectoryContents.test.ts | 0 .../src}/files/serializeDirectoryContents.ts | 0 .../src}/files/types.ts | 0 plugins/scaffolder-node/src/index.ts | 1 + .../scaffolder-react/src/components/types.ts | 1 + 13 files changed, 249 insertions(+), 124 deletions(-) create mode 100644 plugins/scaffolder-node/src/actions/repoHelpers.ts create mode 100644 plugins/scaffolder-node/src/actions/util.ts rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/deserializeDirectoryContents.test.ts (100%) rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/deserializeDirectoryContents.ts (100%) rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/index.ts (100%) rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/serializeDirectoryContents.test.ts (100%) rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/serializeDirectoryContents.ts (100%) rename plugins/{scaffolder-backend/src/lib => scaffolder-node/src}/files/types.ts (100%) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index f1ea2a3517..d89fc2f3ca 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -64,9 +64,6 @@ "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "@backstage/types": "workspace:^", - "@gitbeaker/core": "^35.6.0", - "@gitbeaker/node": "^35.1.0", - "@octokit/webhooks": "^10.0.0", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", "azure-devops-node-api": "^11.0.1", @@ -83,14 +80,11 @@ "isomorphic-git": "^1.23.0", "jsonschema": "^1.2.6", "knex": "^3.0.0", - "libsodium-wrappers": "^0.7.11", "lodash": "^4.17.21", "luxon": "^3.0.0", "morgan": "^1.10.0", "node-fetch": "^2.6.7", "nunjucks": "^3.2.3", - "octokit": "^2.0.0", - "octokit-plugin-create-pull-request": "^3.10.0", "p-limit": "^3.1.0", "p-queue": "^6.6.2", "prom-client": "^14.0.1", @@ -101,12 +95,10 @@ "zod": "^3.21.4" }, "devDependencies": { - "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", - "@types/libsodium-wrappers": "^0.7.10", "@types/nunjucks": "^3.1.4", "@types/supertest": "^2.0.8", "@types/zen-observable": "^0.8.0", @@ -115,8 +107,7 @@ "msw": "^1.0.0", "strip-ansi": "^7.1.0", "supertest": "^6.1.3", - "wait-for-expect": "^3.0.2", - "yaml": "^2.0.0" + "wait-for-expect": "^3.0.2" }, "files": [ "dist", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts index 61bd704a0b..7ad21e34ba 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2023 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,116 +14,7 @@ * limitations under the License. */ -import { InputError } from '@backstage/errors'; -import { isChildPath } from '@backstage/backend-common'; -import { join as joinPath, normalize as normalizePath } from 'path'; -import { ScmIntegrationRegistry } from '@backstage/integration'; - -export const getRepoSourceDirectory = ( - workspacePath: string, - sourcePath: string | undefined, -) => { - if (sourcePath) { - const safeSuffix = normalizePath(sourcePath).replace( - /^(\.\.(\/|\\|$))+/, - '', - ); - const path = joinPath(workspacePath, safeSuffix); - if (!isChildPath(workspacePath, path)) { - throw new Error('Invalid source path'); - } - return path; - } - return workspacePath; -}; -export type RepoSpec = { - repo: string; - host: string; - owner?: string; - organization?: string; - workspace?: string; - project?: string; -}; - -export const parseRepoUrl = ( - repoUrl: string, - integrations: ScmIntegrationRegistry, -): RepoSpec => { - let parsed; - try { - parsed = new URL(`https://${repoUrl}`); - } catch (error) { - throw new InputError( - `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`, - ); - } - const host = parsed.host; - const owner = parsed.searchParams.get('owner') ?? undefined; - const organization = parsed.searchParams.get('organization') ?? undefined; - const workspace = parsed.searchParams.get('workspace') ?? undefined; - const project = parsed.searchParams.get('project') ?? undefined; - - const type = integrations.byHost(host)?.type; - - if (!type) { - throw new InputError( - `No matching integration configuration for host ${host}, please check your integrations config`, - ); - } - - const repo: string = parsed.searchParams.get('repo')!; - switch (type) { - case 'bitbucket': { - if (host === 'www.bitbucket.org') { - checkRequiredParams(parsed, 'workspace'); - } - checkRequiredParams(parsed, 'project', 'repo'); - break; - } - case 'gitlab': { - // project is the projectID, and if defined, owner and repo won't be needed. - if (!project) { - checkRequiredParams(parsed, 'owner', 'repo'); - } - break; - } - case 'gerrit': { - checkRequiredParams(parsed, 'repo'); - break; - } - default: { - checkRequiredParams(parsed, 'repo', 'owner'); - break; - } - } - - return { host, owner, repo, organization, workspace, project }; -}; -export const isExecutable = (fileMode: number) => { - const executeBitMask = 0o000111; - const res = fileMode & executeBitMask; - return res > 0; -}; - -/** - * This function checks if the required parameters (given as the `params` argument) are present in the URL - * - * @param repoUrl - the URL for the repository - * @param params - a variadic list of URL query parameter names - * - * @throws - * An InputError exception is thrown if any of the required parameters is not in the URL. - * - * @public - */ -function checkRequiredParams(repoUrl: URL, ...params: string[]) { - for (let i = 0; i < params.length; i++) { - if (!repoUrl.searchParams.get(params[i])) { - throw new InputError( - `Invalid repo URL passed to publisher: ${repoUrl.toString()}, missing ${ - params[i] - }`, - ); - } - } -} +// const executeBitMask = 0o000111; +// const res = fileMode & executeBitMask; +// return res > 0; +// }; diff --git a/plugins/scaffolder-node/src/actions/index.ts b/plugins/scaffolder-node/src/actions/index.ts index 47af320ccb..27046bebaf 100644 --- a/plugins/scaffolder-node/src/actions/index.ts +++ b/plugins/scaffolder-node/src/actions/index.ts @@ -25,3 +25,5 @@ export { } from './executeShellCommand'; export { fetchContents, fetchFile } from './fetch'; export { type ActionContext, type TemplateAction } from './types'; +export { initRepoAndPush, commitAndPushRepo } from './repoHelpers'; +export { parseRepoUrl, getRepoSourceDirectory } from './util'; diff --git a/plugins/scaffolder-node/src/actions/repoHelpers.ts b/plugins/scaffolder-node/src/actions/repoHelpers.ts new file mode 100644 index 0000000000..a814ca38ed --- /dev/null +++ b/plugins/scaffolder-node/src/actions/repoHelpers.ts @@ -0,0 +1,127 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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 '@backstage/backend-common'; +import { Logger } from 'winston'; + +export async function initRepoAndPush({ + dir, + remoteUrl, + auth, + logger, + defaultBranch = 'master', + commitMessage = 'Initial commit', + gitAuthorInfo, +}: { + dir: string; + remoteUrl: string; + // For use cases where token has to be used with Basic Auth + // it has to be provided as password together with a username + // which may be a fixed value defined by the provider. + auth: { username: string; password: string } | { token: string }; + logger: Logger; + defaultBranch?: string; + commitMessage?: string; + gitAuthorInfo?: { name?: string; email?: string }; +}): Promise<{ commitHash: string }> { + const git = Git.fromAuth({ + ...auth, + logger, + }); + + await git.init({ + dir, + defaultBranch, + }); + + await git.add({ dir, filepath: '.' }); + + // use provided info if possible, otherwise use fallbacks + const authorInfo = { + name: gitAuthorInfo?.name ?? 'Scaffolder', + email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io', + }; + + const commitHash = await git.commit({ + dir, + message: commitMessage, + author: authorInfo, + committer: authorInfo, + }); + await git.addRemote({ + dir, + url: remoteUrl, + remote: 'origin', + }); + + await git.push({ + dir, + remote: 'origin', + }); + + return { commitHash }; +} + +export async function commitAndPushRepo({ + dir, + auth, + logger, + commitMessage, + gitAuthorInfo, + branch = 'master', + remoteRef, +}: { + dir: string; + // For use cases where token has to be used with Basic Auth + // it has to be provided as password together with a username + // which may be a fixed value defined by the provider. + auth: { username: string; password: string } | { token: string }; + logger: Logger; + commitMessage: string; + gitAuthorInfo?: { name?: string; email?: string }; + branch?: string; + remoteRef?: string; +}): Promise<{ commitHash: string }> { + const git = Git.fromAuth({ + ...auth, + logger, + }); + + await git.fetch({ dir }); + await git.checkout({ dir, ref: branch }); + await git.add({ dir, filepath: '.' }); + + // use provided info if possible, otherwise use fallbacks + const authorInfo = { + name: gitAuthorInfo?.name ?? 'Scaffolder', + email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io', + }; + + const commitHash = await git.commit({ + dir, + message: commitMessage, + author: authorInfo, + committer: authorInfo, + }); + + await git.push({ + dir, + remote: 'origin', + remoteRef: remoteRef ?? `refs/heads/${branch}`, + }); + + return { commitHash }; +} diff --git a/plugins/scaffolder-node/src/actions/util.ts b/plugins/scaffolder-node/src/actions/util.ts new file mode 100644 index 0000000000..cdd8512e63 --- /dev/null +++ b/plugins/scaffolder-node/src/actions/util.ts @@ -0,0 +1,112 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { InputError } from '@backstage/errors'; +import { isChildPath } from '@backstage/backend-common'; +import { join as joinPath, normalize as normalizePath } from 'path'; +import { ScmIntegrationRegistry } from '@backstage/integration'; + +export const getRepoSourceDirectory = ( + workspacePath: string, + sourcePath: string | undefined, +) => { + if (sourcePath) { + const safeSuffix = normalizePath(sourcePath).replace( + /^(\.\.(\/|\\|$))+/, + '', + ); + const path = joinPath(workspacePath, safeSuffix); + if (!isChildPath(workspacePath, path)) { + throw new Error('Invalid source path'); + } + return path; + } + return workspacePath; +}; + +export const parseRepoUrl = ( + repoUrl: string, + integrations: ScmIntegrationRegistry, +): { + repo: string; + host: string; + owner?: string; + organization?: string; + workspace?: string; + project?: string; +} => { + let parsed; + try { + parsed = new URL(`https://${repoUrl}`); + } catch (error) { + throw new InputError( + `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`, + ); + } + const host = parsed.host; + const owner = parsed.searchParams.get('owner') ?? undefined; + const organization = parsed.searchParams.get('organization') ?? undefined; + const workspace = parsed.searchParams.get('workspace') ?? undefined; + const project = parsed.searchParams.get('project') ?? undefined; + + const type = integrations.byHost(host)?.type; + + if (!type) { + throw new InputError( + `No matching integration configuration for host ${host}, please check your integrations config`, + ); + } + + const repo: string = parsed.searchParams.get('repo')!; + switch (type) { + case 'bitbucket': { + if (host === 'www.bitbucket.org') { + checkRequiredParams(parsed, 'workspace'); + } + checkRequiredParams(parsed, 'project', 'repo'); + break; + } + case 'gitlab': { + // project is the projectID, and if defined, owner and repo won't be needed. + if (!project) { + checkRequiredParams(parsed, 'owner', 'repo'); + } + break; + } + case 'gerrit': { + checkRequiredParams(parsed, 'repo'); + break; + } + default: { + checkRequiredParams(parsed, 'repo', 'owner'); + break; + } + } + + return { host, owner, repo, organization, workspace, project }; +}; + +function checkRequiredParams(repoUrl: URL, ...params: string[]) { + for (let i = 0; i < params.length; i++) { + if (!repoUrl.searchParams.get(params[i])) { + throw new InputError( + `Invalid repo URL passed to publisher: ${repoUrl.toString()}, missing ${ + params[i] + }`, + ); + } + } +} diff --git a/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts b/plugins/scaffolder-node/src/files/deserializeDirectoryContents.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts rename to plugins/scaffolder-node/src/files/deserializeDirectoryContents.test.ts diff --git a/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.ts b/plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.ts rename to plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts diff --git a/plugins/scaffolder-backend/src/lib/files/index.ts b/plugins/scaffolder-node/src/files/index.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/index.ts rename to plugins/scaffolder-node/src/files/index.ts diff --git a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts b/plugins/scaffolder-node/src/files/serializeDirectoryContents.test.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts rename to plugins/scaffolder-node/src/files/serializeDirectoryContents.test.ts diff --git a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts b/plugins/scaffolder-node/src/files/serializeDirectoryContents.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.ts rename to plugins/scaffolder-node/src/files/serializeDirectoryContents.ts diff --git a/plugins/scaffolder-backend/src/lib/files/types.ts b/plugins/scaffolder-node/src/files/types.ts similarity index 100% rename from plugins/scaffolder-backend/src/lib/files/types.ts rename to plugins/scaffolder-node/src/files/types.ts diff --git a/plugins/scaffolder-node/src/index.ts b/plugins/scaffolder-node/src/index.ts index 98691c2afa..0ec492dd32 100644 --- a/plugins/scaffolder-node/src/index.ts +++ b/plugins/scaffolder-node/src/index.ts @@ -22,4 +22,5 @@ export * from './actions'; export * from './tasks'; +export * from './files'; export type { TemplateFilter, TemplateGlobal } from './types'; diff --git a/plugins/scaffolder-react/src/components/types.ts b/plugins/scaffolder-react/src/components/types.ts index 597998bac4..e9ec3bf711 100644 --- a/plugins/scaffolder-react/src/components/types.ts +++ b/plugins/scaffolder-react/src/components/types.ts @@ -23,6 +23,7 @@ import { JsonObject } from '@backstage/types'; export type TemplateGroupFilter = { title?: React.ReactNode; filter: (entity: TemplateEntityV1beta3) => boolean; + sort?: (a: TemplateEntityV1beta3, b: TemplateEntityV1beta3) => number; }; /** From 823dee3b23a41e5c3904dedf5e9262fb9b3e5dd4 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 12:56:44 +0100 Subject: [PATCH 07/15] chore: create gerrit module Signed-off-by: blam --- .../.eslintrc.js | 1 + .../README.md | 5 + .../package.json | 42 +++ .../src/actions}/gerrit.examples.ts | 0 .../src/actions}/gerrit.test.ts | 5 +- .../src/actions}/gerrit.ts | 9 +- .../src/actions}/gerritReview.test.ts | 9 +- .../src/actions}/gerritReview.ts | 9 +- .../src/actions/index.ts} | 7 +- .../src/index.ts | 23 ++ .../actions/builtin/helpers.test.ts | 319 ------------------ .../src/scaffolder/actions/builtin/helpers.ts | 253 -------------- .../actions/builtin/publish/index.ts | 32 -- .../actions/builtin/publish/util.test.ts | 181 ---------- plugins/scaffolder-node/package.json | 3 + 15 files changed, 98 insertions(+), 800 deletions(-) create mode 100644 plugins/scaffolder-backend-module-gerrit/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-gerrit/README.md create mode 100644 plugins/scaffolder-backend-module-gerrit/package.json rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gerrit/src/actions}/gerrit.examples.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gerrit/src/actions}/gerrit.test.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gerrit/src/actions}/gerrit.ts (97%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gerrit/src/actions}/gerritReview.test.ts (93%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish => scaffolder-backend-module-gerrit/src/actions}/gerritReview.ts (96%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts => scaffolder-backend-module-gerrit/src/actions/index.ts} (84%) create mode 100644 plugins/scaffolder-backend-module-gerrit/src/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts diff --git a/plugins/scaffolder-backend-module-gerrit/.eslintrc.js b/plugins/scaffolder-backend-module-gerrit/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-backend-module-gerrit/README.md b/plugins/scaffolder-backend-module-gerrit/README.md new file mode 100644 index 0000000000..f1492f5b35 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-scaffolder-backend-module-gerrit + +The gerrit module for [@backstage/plugin-scaffolder-backend](https://www.npmjs.com/package/@backstage/plugin-scaffolder-backend). + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json new file mode 100644 index 0000000000..f3797accb3 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -0,0 +1,42 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-gerrit", + "description": "The gerrit module for @backstage/plugin-scaffolder-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/plugin-scaffolder-node": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/integration": "workspace:^", + "@backstage/config": "workspace:^", + "node-fetch": "^2.6.7", + "yaml": "^2.0.0" + }, + "devDependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "msw": "^1.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.examples.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.examples.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.examples.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.examples.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.test.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.test.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts index 73dcc47225..b56c27f59e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.test.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.test.ts @@ -14,8 +14,9 @@ * limitations under the License. */ -jest.mock('../helpers', () => { +jest.mock('@backstage/plugin-scaffolder-node', () => { return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), initRepoAndPush: jest.fn().mockResolvedValue({ commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', }), @@ -34,7 +35,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../helpers'; +import { initRepoAndPush } from '@backstage/plugin-scaffolder-node'; describe('publish:gerrit', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.ts similarity index 97% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.ts index 67ed868c4c..b7369fd5d8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerrit.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerrit.ts @@ -22,10 +22,13 @@ import { getGerritRequestOptions, ScmIntegrationRegistry, } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; +import { + createTemplateAction, + initRepoAndPush, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; import fetch, { Response, RequestInit } from 'node-fetch'; -import { initRepoAndPush } from '../helpers'; import { examples } from './gerrit.examples'; const createGerritProject = async ( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.test.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts similarity index 93% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.test.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts index 55d7bde5a7..eeae3871ee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.test.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.test.ts @@ -14,14 +14,19 @@ * limitations under the License. */ -jest.mock('../helpers'); +jest.mock('@backstage/plugin-scaffolder-node', () => { + return { + ...jest.requireActual('@backstage/plugin-scaffolder-node'), + commitAndPushRepo: jest.fn(), + }; +}); import { createPublishGerritReviewAction } from './gerritReview'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { commitAndPushRepo } from '../helpers'; +import { commitAndPushRepo } from '@backstage/plugin-scaffolder-node'; describe('publish:gerrit:review', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.ts similarity index 96% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.ts index 73e74f5cbc..bd8d0321ab 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gerritReview.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/gerritReview.ts @@ -18,9 +18,12 @@ import crypto from 'crypto'; import { InputError } from '@backstage/errors'; import { Config } from '@backstage/config'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; -import { getRepoSourceDirectory, parseRepoUrl } from './util'; -import { commitAndPushRepo } from '../helpers'; +import { + createTemplateAction, + commitAndPushRepo, + getRepoSourceDirectory, + parseRepoUrl, +} from '@backstage/plugin-scaffolder-node'; const generateGerritChangeId = (): string => { const changeId = crypto.randomBytes(20).toString('hex'); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts b/plugins/scaffolder-backend-module-gerrit/src/actions/index.ts similarity index 84% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts rename to plugins/scaffolder-backend-module-gerrit/src/actions/index.ts index 7ad21e34ba..1918679320 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/actions/index.ts @@ -13,8 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// const executeBitMask = 0o000111; -// const res = fileMode & executeBitMask; -// return res > 0; -// }; +export * from './gerrit'; +export * from './gerritReview'; diff --git a/plugins/scaffolder-backend-module-gerrit/src/index.ts b/plugins/scaffolder-backend-module-gerrit/src/index.ts new file mode 100644 index 0000000000..21fdd116e7 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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. + */ + +/** + * The gerrit module for @backstage/plugin-scaffolder-backend. + * + * @packageDocumentation + */ + +export * from './actions'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.test.ts deleted file mode 100644 index 7362e99892..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.test.ts +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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, getVoidLogger } from '@backstage/backend-common'; -import { commitAndPushRepo, entityRefToName, initRepoAndPush } from './helpers'; - -jest.mock('@backstage/backend-common', () => ({ - Git: { - fromAuth: jest.fn().mockReturnValue({ - init: jest.fn(), - add: jest.fn(), - checkout: jest.fn(), - commit: jest - .fn() - .mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'), - fetch: jest.fn(), - addRemote: jest.fn(), - push: jest.fn(), - }), - }, - getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger, -})); - -const mockedGit = Git.fromAuth({ - logger: getVoidLogger(), -}); - -describe('initRepoAndPush', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('with minimal parameters', () => { - beforeEach(async () => { - await initRepoAndPush({ - dir: '/test/repo/dir/', - remoteUrl: 'git@github.com:test/repo.git', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - }); - }); - - it('initializes the repo', () => { - expect(mockedGit.init).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - defaultBranch: 'master', - }); - }); - - it('stages all files in the repo', () => { - expect(mockedGit.add).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - filepath: '.', - }); - }); - - it('creates an initial commit', () => { - expect(mockedGit.commit).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - message: 'Initial commit', - author: { - name: 'Scaffolder', - email: 'scaffolder@backstage.io', - }, - committer: { - name: 'Scaffolder', - email: 'scaffolder@backstage.io', - }, - }); - }); - - it('adds the appropriate remote', () => { - expect(mockedGit.addRemote).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - url: 'git@github.com:test/repo.git', - remote: 'origin', - }); - }); - - it('pushes to the remote', () => { - expect(mockedGit.push).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - remote: 'origin', - }); - }); - }); - - it('with token', async () => { - await initRepoAndPush({ - dir: '/test/repo/dir/', - remoteUrl: 'git@github.com:test/repo.git', - auth: { - token: 'test-token', - }, - logger: getVoidLogger(), - }); - - expect(mockedGit.init).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - defaultBranch: 'master', - }); - }); - - it('allows overriding the default branch', async () => { - await initRepoAndPush({ - dir: '/test/repo/dir/', - defaultBranch: 'trunk', - remoteUrl: 'git@github.com:test/repo.git', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - }); - - expect(mockedGit.init).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - defaultBranch: 'trunk', - }); - }); - - it('allows overriding the author', async () => { - await initRepoAndPush({ - dir: '/test/repo/dir/', - gitAuthorInfo: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - remoteUrl: 'git@github.com:test/repo.git', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - }); - - expect(mockedGit.commit).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - message: 'Initial commit', - author: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - committer: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - }); - }); -}); - -describe('commitAndPushRepo', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - describe('with minimal parameters', () => { - beforeEach(async () => { - await commitAndPushRepo({ - dir: '/test/repo/dir/', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - commitMessage: 'commit message', - }); - }); - - it('fetches commits', () => { - expect(mockedGit.fetch).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - }); - }); - - it('checkouts to master', () => { - expect(mockedGit.checkout).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - ref: 'master', - }); - }); - - it('stages all files in the repo', () => { - expect(mockedGit.add).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - filepath: '.', - }); - }); - - it('creates a commit', () => { - expect(mockedGit.commit).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - message: 'commit message', - author: { - name: 'Scaffolder', - email: 'scaffolder@backstage.io', - }, - committer: { - name: 'Scaffolder', - email: 'scaffolder@backstage.io', - }, - }); - }); - - it('pushes to the remote', () => { - expect(mockedGit.push).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - remote: 'origin', - remoteRef: 'refs/heads/master', - }); - }); - }); - - it('allows overriding the default branch', async () => { - await commitAndPushRepo({ - dir: '/test/repo/dir/', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - commitMessage: 'commit message', - branch: 'otherbranch', - }); - - expect(mockedGit.checkout).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - ref: 'otherbranch', - }); - expect(mockedGit.push).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - remote: 'origin', - remoteRef: 'refs/heads/otherbranch', - }); - }); - - it('allows overriding the remote ref', async () => { - await commitAndPushRepo({ - dir: '/test/repo/dir/', - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - commitMessage: 'commit message', - remoteRef: 'refs/for/master', - }); - - expect(mockedGit.checkout).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - ref: 'master', - }); - expect(mockedGit.push).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - remote: 'origin', - remoteRef: 'refs/for/master', - }); - }); - - it('allows overriding the author', async () => { - await commitAndPushRepo({ - dir: '/test/repo/dir/', - commitMessage: 'commit message', - gitAuthorInfo: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - auth: { - username: 'test-user', - password: 'test-password', - }, - logger: getVoidLogger(), - branch: 'master', - }); - - expect(mockedGit.commit).toHaveBeenCalledWith({ - dir: '/test/repo/dir/', - message: 'commit message', - author: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - committer: { - name: 'Custom Scaffolder Author', - email: 'scaffolder@example.org', - }, - }); - }); -}); - -describe('entityRefToName', () => { - it.each([ - 'user:default/catpants', - 'group:default/catpants', - 'user:catpants', - 'default/catpants', - 'user:custom/catpants', - 'group:custom/catpants', - 'catpants', - ])('should parse: "%s"', (entityName: string) => { - expect(entityRefToName(entityName)).toEqual('catpants'); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts deleted file mode 100644 index 5ac92128ca..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 '@backstage/backend-common'; -import { Config } from '@backstage/config'; -import { assertError } from '@backstage/errors'; -import { Octokit } from 'octokit'; -import { Logger } from 'winston'; - -export async function initRepoAndPush({ - dir, - remoteUrl, - auth, - logger, - defaultBranch = 'master', - commitMessage = 'Initial commit', - gitAuthorInfo, -}: { - dir: string; - remoteUrl: string; - // For use cases where token has to be used with Basic Auth - // it has to be provided as password together with a username - // which may be a fixed value defined by the provider. - auth: { username: string; password: string } | { token: string }; - logger: Logger; - defaultBranch?: string; - commitMessage?: string; - gitAuthorInfo?: { name?: string; email?: string }; -}): Promise<{ commitHash: string }> { - const git = Git.fromAuth({ - ...auth, - logger, - }); - - await git.init({ - dir, - defaultBranch, - }); - - await git.add({ dir, filepath: '.' }); - - // use provided info if possible, otherwise use fallbacks - const authorInfo = { - name: gitAuthorInfo?.name ?? 'Scaffolder', - email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io', - }; - - const commitHash = await git.commit({ - dir, - message: commitMessage, - author: authorInfo, - committer: authorInfo, - }); - await git.addRemote({ - dir, - url: remoteUrl, - remote: 'origin', - }); - - await git.push({ - dir, - remote: 'origin', - }); - - return { commitHash }; -} - -export async function commitAndPushRepo({ - dir, - auth, - logger, - commitMessage, - gitAuthorInfo, - branch = 'master', - remoteRef, -}: { - dir: string; - // For use cases where token has to be used with Basic Auth - // it has to be provided as password together with a username - // which may be a fixed value defined by the provider. - auth: { username: string; password: string } | { token: string }; - logger: Logger; - commitMessage: string; - gitAuthorInfo?: { name?: string; email?: string }; - branch?: string; - remoteRef?: string; -}): Promise<{ commitHash: string }> { - const git = Git.fromAuth({ - ...auth, - logger, - }); - - await git.fetch({ dir }); - await git.checkout({ dir, ref: branch }); - await git.add({ dir, filepath: '.' }); - - // use provided info if possible, otherwise use fallbacks - const authorInfo = { - name: gitAuthorInfo?.name ?? 'Scaffolder', - email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io', - }; - - const commitHash = await git.commit({ - dir, - message: commitMessage, - author: authorInfo, - committer: authorInfo, - }); - - await git.push({ - dir, - remote: 'origin', - remoteRef: remoteRef ?? `refs/heads/${branch}`, - }); - - return { commitHash }; -} - -type BranchProtectionOptions = { - client: Octokit; - owner: string; - repoName: string; - logger: Logger; - requireCodeOwnerReviews: boolean; - requiredStatusCheckContexts?: string[]; - bypassPullRequestAllowances?: { - users?: string[]; - teams?: string[]; - apps?: string[]; - }; - requiredApprovingReviewCount?: number; - restrictions?: { - users: string[]; - teams: string[]; - apps?: string[]; - }; - requireBranchesToBeUpToDate?: boolean; - requiredConversationResolution?: boolean; - defaultBranch?: string; - enforceAdmins?: boolean; - dismissStaleReviews?: boolean; - requiredCommitSigning?: boolean; -}; - -export const enableBranchProtectionOnDefaultRepoBranch = async ({ - repoName, - client, - owner, - logger, - requireCodeOwnerReviews, - bypassPullRequestAllowances, - requiredApprovingReviewCount, - restrictions, - requiredStatusCheckContexts = [], - requireBranchesToBeUpToDate = true, - requiredConversationResolution = false, - defaultBranch = 'master', - enforceAdmins = true, - dismissStaleReviews = false, - requiredCommitSigning = false, -}: BranchProtectionOptions): Promise => { - const tryOnce = async () => { - try { - await client.rest.repos.updateBranchProtection({ - mediaType: { - /** - * 👇 we need this preview because allowing a custom - * reviewer count on branch protection is a preview - * feature - * - * More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews - */ - previews: ['luke-cage-preview'], - }, - owner, - repo: repoName, - branch: defaultBranch, - required_status_checks: { - strict: requireBranchesToBeUpToDate, - contexts: requiredStatusCheckContexts, - }, - restrictions: restrictions ?? null, - enforce_admins: enforceAdmins, - required_pull_request_reviews: { - required_approving_review_count: requiredApprovingReviewCount, - require_code_owner_reviews: requireCodeOwnerReviews, - bypass_pull_request_allowances: bypassPullRequestAllowances, - dismiss_stale_reviews: dismissStaleReviews, - }, - required_conversation_resolution: requiredConversationResolution, - }); - - if (requiredCommitSigning) { - await client.rest.repos.createCommitSignatureProtection({ - owner, - repo: repoName, - branch: defaultBranch, - }); - } - } catch (e) { - assertError(e); - if ( - e.message.includes( - 'Upgrade to GitHub Pro or make this repository public to enable this feature', - ) - ) { - logger.warn( - 'Branch protection was not enabled as it requires GitHub Pro for private repositories', - ); - } else { - throw e; - } - } - }; - - try { - await tryOnce(); - } catch (e) { - if (!e.message.includes('Branch not found')) { - throw e; - } - - // GitHub has eventual consistency. Fail silently, wait, and try again. - await new Promise(resolve => setTimeout(resolve, 600)); - await tryOnce(); - } -}; - -export function getGitCommitMessage( - gitCommitMessage: string | undefined, - config: Config, -): string | undefined { - return gitCommitMessage - ? gitCommitMessage - : config.getOptionalString('scaffolder.defaultCommitMessage'); -} - -export function entityRefToName(name: string): string { - return name.replace(/^.*[:/]/g, ''); -} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts deleted file mode 100644 index bed3a2316c..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { createPublishAzureAction } from './azure'; -export { createPublishBitbucketAction } from './bitbucket'; -export { createPublishBitbucketCloudAction } from './bitbucketCloud'; -export { createPublishBitbucketServerAction } from './bitbucketServer'; -export { createPublishBitbucketServerPullRequestAction } from './bitbucketServerPullRequest'; -export { createPublishGerritAction } from './gerrit'; -export { createPublishGerritReviewAction } from './gerritReview'; -export { createPublishGithubAction } from './github'; -export { createPublishGithubPullRequestAction } from './githubPullRequest'; -export type { - CreateGithubPullRequestClientFactoryInput, - CreateGithubPullRequestActionOptions, - OctokitWithPullRequestPluginClient, -} from './githubPullRequest'; -export { createPublishGitlabAction } from './gitlab'; -export { createPublishGitlabMergeRequestAction } from './gitlabMergeRequest'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts deleted file mode 100644 index 5446109056..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 path from 'path'; -import { getRepoSourceDirectory, isExecutable, parseRepoUrl } from './util'; -import { ScmIntegrations } from '@backstage/integration'; -import { ConfigReader } from '@backstage/config'; - -describe('getRepoSourceDirectory', () => { - it('should return workspace root if no sub folder is given', () => { - expect( - getRepoSourceDirectory(path.join('/', 'var', 'workspace'), undefined), - ).toEqual(path.join('/', 'var', 'workspace')); - }); - - it('should return path in workspace if sub folder is given', () => { - expect( - getRepoSourceDirectory( - path.join('/', 'var', 'workspace'), - path.join('path', 'of', 'subfolder'), - ), - ).toEqual(path.join('/', 'var', 'workspace', 'path', 'of', 'subfolder')); - }); - - it('should not allow traversal outside the workspace root', () => { - // We have to construct the path manually here, as path.join would mitigate the path traversal - expect( - getRepoSourceDirectory( - path.join('/', 'var', 'workspace'), - `..${path.sep}secret`, - ), - ).toEqual(path.join('/', 'var', 'workspace', 'secret')); - expect( - getRepoSourceDirectory( - path.join('/', 'var', 'workspace'), - `.${path.sep}path${path.sep}..${path.sep}..${path.sep}secret`, - ), - ).toEqual(path.join('/', 'var', 'workspace', 'secret')); - expect( - getRepoSourceDirectory( - path.join('/', 'var', 'workspace'), - path.join('/', 'absolute', 'secret'), - ), - ).toEqual(path.join('/', 'var', 'workspace', 'absolute', 'secret')); - }); -}); - -describe('isExecutable', () => { - it('should return true for file mode 777', () => { - expect(isExecutable(0o100777)).toBe(true); - }); - it('should return true for file mode 775', () => { - expect(isExecutable(0o100775)).toBe(true); - }); - it('should return true for file mode 755', () => { - expect(isExecutable(0o100755)).toBe(true); - }); - it('should return true for file mode 700', () => { - expect(isExecutable(0o100700)).toBe(true); - }); - it('should return true for file mode 770', () => { - expect(isExecutable(0o100770)).toBe(true); - }); - it('should return true for file mode 670', () => { - expect(isExecutable(0o100670)).toBe(true); - }); - it('should return false for file mode 644', () => { - expect(isExecutable(0o100644)).toBe(false); - }); - it('should return false for file mode 600', () => { - expect(isExecutable(0o100600)).toBe(false); - }); - it('should return false for file mode 640', () => { - expect(isExecutable(0o100640)).toBe(false); - }); -}); - -describe('parseRepoUrl', () => { - const config = new ConfigReader({ - integrations: { - gitlab: [ - { - host: 'www.gitlab.com', - token: 'token', - apiBaseUrl: 'https://api.gitlab.com', - }, - ], - bitbucket: [ - { - host: 'www.bitbucket.net', - apiBaseUrl: 'https://api.hosted.bitbucket.net', - }, - { - host: 'www.bitbucket.org', - username: 'username', - appPassword: 'password', - apiBaseUrl: 'https://api.hosted.bitbucket.org', - }, - ], - }, - }); - const integrations = ScmIntegrations.fromConfig(config); - it('should throw an exception if no parameters are passed (gitlab)', () => { - expect(() => parseRepoUrl('www.gitlab.com', integrations)).toThrow( - 'Invalid repo URL passed to publisher: https://www.gitlab.com/, missing owner', - ); - }); - it('should return the project ID in the `project` parameter (gitlab)', () => { - expect( - parseRepoUrl('www.gitlab.com?project=234', integrations), - ).toStrictEqual({ - host: 'www.gitlab.com', - organization: undefined, - owner: undefined, - project: '234', - repo: null, - workspace: undefined, - }); - }); - it('should throw an exception if the repo parameter is missing, but owner parameter is set', () => { - expect(() => - parseRepoUrl('www.gitlab.com?owner=owner', integrations), - ).toThrow( - 'Invalid repo URL passed to publisher: https://www.gitlab.com/?owner=owner, missing repo', - ); - }); - it('should throw an exception if the owner parameter is missing, but repo parameter is set (gitlab)', () => { - expect(() => - parseRepoUrl('www.gitlab.com?repo=repo', integrations), - ).toThrow( - 'Invalid repo URL passed to publisher: https://www.gitlab.com/?repo=repo, missing owner', - ); - }); - it('should return the workspace, project and repo (bitbucket.org)', () => { - expect( - parseRepoUrl( - 'www.bitbucket.org?project=project&workspace=workspace&repo=repo', - integrations, - ), - ).toStrictEqual({ - host: 'www.bitbucket.org', - organization: undefined, - owner: undefined, - project: 'project', - repo: 'repo', - workspace: 'workspace', - }); - }); - it('should return the project and repo (another bitbucket instance)', () => { - expect( - parseRepoUrl('www.bitbucket.net?project=project&repo=repo', integrations), - ).toStrictEqual({ - host: 'www.bitbucket.net', - organization: undefined, - owner: undefined, - project: 'project', - repo: 'repo', - workspace: undefined, - }); - }); - it('should throw an exception if the workspace parameter is missing for bitbucket.org instance (bitbucket.org)', () => { - expect(() => - parseRepoUrl('www.bitbucket.org?project=project&repo=repo', integrations), - ).toThrow( - 'Invalid repo URL passed to publisher: https://www.bitbucket.org/?project=project&repo=repo, missing workspace', - ); - }); -}); diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 5f5702a035..877a465052 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -50,12 +50,15 @@ "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/types": "workspace:^", "fs-extra": "10.1.0", + "globby": "^11.0.0", "jsonschema": "^1.2.6", + "p-limit": "^3.1.0", "winston": "^3.2.1", "zod": "^3.21.4", "zod-to-json-schema": "^3.20.4" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/config": "workspace:^" }, From 480d3b209d49a34bea36e1e2e731d0ee61db8856 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 13:35:12 +0100 Subject: [PATCH 08/15] chore: update imports Signed-off-by: blam --- packages/cli/src/lib/version.ts | 4 +- plugins/scaffolder-backend/package.json | 5 + .../src/lib/templating/filters.ts | 2 +- .../actions/builtin/createBuiltinActions.ts | 21 +++- .../src/scaffolder/actions/builtin/index.ts | 2 - .../src/scaffolder/dryrun/createDryRunner.ts | 11 +-- yarn.lock | 99 ++++++++++++++++--- 7 files changed, 116 insertions(+), 28 deletions(-) diff --git a/packages/cli/src/lib/version.ts b/packages/cli/src/lib/version.ts index 96b42fcfb7..9c19a3a8c4 100644 --- a/packages/cli/src/lib/version.ts +++ b/packages/cli/src/lib/version.ts @@ -44,8 +44,8 @@ import { version as coreComponents } from '../../../../packages/core-components/ import { version as corePluginApi } from '../../../../packages/core-plugin-api/package.json'; import { version as devUtils } from '../../../../packages/dev-utils/package.json'; import { version as testUtils } from '../../../../packages/test-utils/package.json'; +import { version as scaffolderNode } from '../../../../plugins/scaffolder-node/package.json'; import { version as theme } from '../../../../packages/theme/package.json'; -import { version as scaffolderBackend } from '../../../../plugins/scaffolder-backend/package.json'; export const packageVersions: Record = { '@backstage/backend-common': backendCommon, @@ -59,7 +59,7 @@ export const packageVersions: Record = { '@backstage/dev-utils': devUtils, '@backstage/test-utils': testUtils, '@backstage/theme': theme, - '@backstage/plugin-scaffolder-backend': scaffolderBackend, + '@backstage/plugin-scaffolder-node': scaffolderNode, }; export function findVersion() { diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index d89fc2f3ca..17f293f313 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -61,6 +61,11 @@ "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-azure": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-bitbucket": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-gerrit": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-github": "workspace:^", + "@backstage/plugin-scaffolder-backend-module-gitlab": "workspace:^", "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/scaffolder-backend/src/lib/templating/filters.ts b/plugins/scaffolder-backend/src/lib/templating/filters.ts index 7808d6d136..21b43a6164 100644 --- a/plugins/scaffolder-backend/src/lib/templating/filters.ts +++ b/plugins/scaffolder-backend/src/lib/templating/filters.ts @@ -17,7 +17,7 @@ import { parseEntityRef } from '@backstage/catalog-model'; import { ScmIntegrations } from '@backstage/integration'; import type { JsonObject, JsonValue } from '@backstage/types'; import { TemplateFilter } from '..'; -import { parseRepoUrl } from '../../scaffolder/actions/builtin/publish/util'; +import { parseRepoUrl } from '@backstage/plugin-scaffolder-node'; import get from 'lodash/get'; export const createDefaultFilters = ({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 4dcd2c2a0d..6fc50c6453 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -48,20 +48,28 @@ import { createGithubRepoCreateAction, createGithubRepoPushAction, createGithubWebhookAction, -} from './github'; + createPublishGithubAction, + createPublishGithubPullRequestAction, +} from '@backstage/plugin-scaffolder-backend-module-github'; + +import { createPublishAzureAction } from '@backstage/plugin-scaffolder-backend-module-azure'; + import { - createPublishAzureAction, createPublishBitbucketAction, createPublishBitbucketCloudAction, createPublishBitbucketServerAction, createPublishBitbucketServerPullRequestAction, +} from '@backstage/plugin-scaffolder-backend-module-bitbucket'; + +import { createPublishGerritAction, createPublishGerritReviewAction, - createPublishGithubAction, - createPublishGithubPullRequestAction, +} from '@backstage/plugin-scaffolder-backend-module-gerrit'; + +import { createPublishGitlabAction, createPublishGitlabMergeRequestAction, -} from './publish'; +} from '@backstage/plugin-scaffolder-backend-module-gitlab'; /** * The options passed to {@link createBuiltinActions} @@ -96,8 +104,11 @@ export interface CreateBuiltInActionsOptions { * A function to generate create a list of default actions that the scaffolder provides. * Is called internally in the default setup, but can be used when adding your own actions or overriding the default ones * + * TODO(blam): version 2 of the scaffolder shouldn't ship with the additional modules. We should ship the basics, and let people install + * modules for the providers they want to use. * @public * @returns A list of actions that can be used in the scaffolder + * */ export const createBuiltinActions = ( options: CreateBuiltInActionsOptions, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts index 7ab98482ff..6fdbb24484 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts @@ -19,5 +19,3 @@ export * from './createBuiltinActions'; export * from './debug'; export * from './fetch'; export * from './filesystem'; -export * from './publish'; -export * from './github'; diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts index 655c485a6d..e202111d79 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts @@ -21,20 +21,19 @@ import { v4 as uuid } from 'uuid'; import { pathToFileURL } from 'url'; import { Logger } from 'winston'; import { + createTemplateAction, + TaskSecrets, + TemplateFilter, + TemplateGlobal, deserializeDirectoryContents, SerializedFile, serializeDirectoryContents, -} from '../../lib/files'; -import { TemplateFilter, TemplateGlobal } from '../../lib'; +} from '@backstage/plugin-scaffolder-node'; import { TemplateActionRegistry } from '../actions'; import { NunjucksWorkflowRunner } from '../tasks/NunjucksWorkflowRunner'; import { DecoratedActionsRegistry } from './DecoratedActionsRegistry'; import fs from 'fs-extra'; import { resolveSafeChildPath } from '@backstage/backend-common'; -import { - createTemplateAction, - TaskSecrets, -} from '@backstage/plugin-scaffolder-node'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; interface DryRunInput { diff --git a/yarn.lock b/yarn.lock index 2fd28cd48c..cc201b6204 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8611,6 +8611,38 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-scaffolder-backend-module-azure@workspace:^, @backstage/plugin-scaffolder-backend-module-azure@workspace:plugins/scaffolder-backend-module-azure": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-backend-module-azure@workspace:plugins/scaffolder-backend-module-azure" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + azure-devops-node-api: ^11.0.1 + yaml: ^2.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-scaffolder-backend-module-bitbucket@workspace:^, @backstage/plugin-scaffolder-backend-module-bitbucket@workspace:plugins/scaffolder-backend-module-bitbucket": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-backend-module-bitbucket@workspace:plugins/scaffolder-backend-module-bitbucket" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + msw: ^1.0.0 + node-fetch: ^2.6.7 + yaml: ^2.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:^, @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown@workspace:plugins/scaffolder-backend-module-confluence-to-markdown" @@ -8655,18 +8687,61 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend-module-gitlab@workspace:plugins/scaffolder-backend-module-gitlab": +"@backstage/plugin-scaffolder-backend-module-gerrit@workspace:^, @backstage/plugin-scaffolder-backend-module-gerrit@workspace:plugins/scaffolder-backend-module-gerrit": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-backend-module-gerrit@workspace:plugins/scaffolder-backend-module-gerrit" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + msw: ^1.0.0 + node-fetch: ^2.6.7 + yaml: ^2.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-scaffolder-backend-module-github@workspace:^, @backstage/plugin-scaffolder-backend-module-github@workspace:plugins/scaffolder-backend-module-github": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-backend-module-github@workspace:plugins/scaffolder-backend-module-github" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/integration": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^" + "@octokit/webhooks": ^10.0.0 + "@types/libsodium-wrappers": ^0.7.10 + fs-extra: 10.1.0 + jest-when: ^3.1.0 + jsonschema: ^1.2.6 + libsodium-wrappers: ^0.7.11 + octokit: ^2.0.0 + octokit-plugin-create-pull-request: ^3.10.0 + winston: ^3.2.1 + yaml: ^2.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-scaffolder-backend-module-gitlab@workspace:^, @backstage/plugin-scaffolder-backend-module-gitlab@workspace:plugins/scaffolder-backend-module-gitlab": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-gitlab@workspace:plugins/scaffolder-backend-module-gitlab" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" - "@gitbeaker/node": ^35.8.0 + "@gitbeaker/core": ^35.8.0 + "@gitbeaker/node": ^35.1.0 yaml: ^2.0.0 zod: ^3.21.4 languageName: unknown @@ -8729,7 +8804,6 @@ __metadata: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" - "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -8743,17 +8817,18 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-azure": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-bitbucket": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-gerrit": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-github": "workspace:^" + "@backstage/plugin-scaffolder-backend-module-gitlab": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@backstage/types": "workspace:^" - "@gitbeaker/core": ^35.6.0 - "@gitbeaker/node": ^35.1.0 - "@octokit/webhooks": ^10.0.0 "@types/command-exists": ^1.2.0 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 "@types/git-url-parse": ^9.0.0 - "@types/libsodium-wrappers": ^0.7.10 "@types/luxon": ^3.0.0 "@types/nunjucks": ^3.1.4 "@types/supertest": ^2.0.8 @@ -8774,15 +8849,12 @@ __metadata: jest-when: ^3.1.0 jsonschema: ^1.2.6 knex: ^3.0.0 - libsodium-wrappers: ^0.7.11 lodash: ^4.17.21 luxon: ^3.0.0 morgan: ^1.10.0 msw: ^1.0.0 node-fetch: ^2.6.7 nunjucks: ^3.2.3 - octokit: ^2.0.0 - octokit-plugin-create-pull-request: ^3.10.0 p-limit: ^3.1.0 p-queue: ^6.6.2 prom-client: ^14.0.1 @@ -8814,6 +8886,7 @@ __metadata: dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -8822,7 +8895,9 @@ __metadata: "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/types": "workspace:^" fs-extra: 10.1.0 + globby: ^11.0.0 jsonschema: ^1.2.6 + p-limit: ^3.1.0 winston: ^3.2.1 zod: ^3.21.4 zod-to-json-schema: ^3.20.4 @@ -11555,7 +11630,7 @@ __metadata: languageName: node linkType: hard -"@gitbeaker/core@npm:^35.6.0, @gitbeaker/core@npm:^35.8.1": +"@gitbeaker/core@npm:^35.6.0, @gitbeaker/core@npm:^35.8.0, @gitbeaker/core@npm:^35.8.1": version: 35.8.1 resolution: "@gitbeaker/core@npm:35.8.1" dependencies: @@ -11569,7 +11644,7 @@ __metadata: languageName: node linkType: hard -"@gitbeaker/node@npm:^35.1.0, @gitbeaker/node@npm:^35.8.0": +"@gitbeaker/node@npm:^35.1.0": version: 35.8.1 resolution: "@gitbeaker/node@npm:35.8.1" dependencies: From 04559e342286e4b4360d054d708c0ec4bc5df76b Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 14:29:03 +0100 Subject: [PATCH 09/15] chore: update API reports Signed-off-by: blam --- .../api-report.md | 28 + .../src/index.ts | 2 +- .../api-report.md | 82 +++ .../src/index.ts | 2 +- .../api-report.md | 43 ++ .../package.json | 4 +- .../src/index.ts | 2 +- .../api-report.md | 365 ++++++++++++ .../githubPullRequest.examples.test.ts | 9 +- .../src/actions/githubPullRequest.test.ts | 9 +- .../src/actions/githubPullRequest.ts | 94 ++- .../src/actions/index.ts | 5 +- .../src/index.ts | 2 +- .../api-report.md | 72 +++ .../src/index.ts | 3 +- plugins/scaffolder-backend/api-report.md | 555 ------------------ plugins/scaffolder-node/api-report.md | 109 ++++ .../actions/{repoHelpers.ts => gitHelpers.ts} | 6 + plugins/scaffolder-node/src/actions/index.ts | 2 +- plugins/scaffolder-node/src/actions/util.ts | 6 + .../src/files/deserializeDirectoryContents.ts | 2 +- .../src/files/serializeDirectoryContents.ts | 3 + plugins/scaffolder-node/src/files/types.ts | 3 + .../scaffolder-react/src/components/types.ts | 1 - 24 files changed, 778 insertions(+), 631 deletions(-) create mode 100644 plugins/scaffolder-backend-module-azure/api-report.md create mode 100644 plugins/scaffolder-backend-module-bitbucket/api-report.md create mode 100644 plugins/scaffolder-backend-module-gerrit/api-report.md create mode 100644 plugins/scaffolder-backend-module-github/api-report.md rename plugins/scaffolder-node/src/actions/{repoHelpers.ts => gitHelpers.ts} (98%) diff --git a/plugins/scaffolder-backend-module-azure/api-report.md b/plugins/scaffolder-backend-module-azure/api-report.md new file mode 100644 index 0000000000..427ed2d1bf --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/api-report.md @@ -0,0 +1,28 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-azure" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { JsonObject } from '@backstage/types'; +import { ScmIntegrationRegistry } from '@backstage/integration'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; + +// @public +export function createPublishAzureAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + }, + JsonObject +>; +``` diff --git a/plugins/scaffolder-backend-module-azure/src/index.ts b/plugins/scaffolder-backend-module-azure/src/index.ts index d64ca54077..e804f1a504 100644 --- a/plugins/scaffolder-backend-module-azure/src/index.ts +++ b/plugins/scaffolder-backend-module-azure/src/index.ts @@ -15,7 +15,7 @@ */ /** - * The azure module for @backstage/plugin-scaffolder-backend. + * A module for the scaffolder backend that lets you interact with azure * * @packageDocumentation */ diff --git a/plugins/scaffolder-backend-module-bitbucket/api-report.md b/plugins/scaffolder-backend-module-bitbucket/api-report.md new file mode 100644 index 0000000000..8e58c5fe7e --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/api-report.md @@ -0,0 +1,82 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-bitbucket" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { JsonObject } from '@backstage/types'; +import { ScmIntegrationRegistry } from '@backstage/integration'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; + +// @public @deprecated +export function createPublishBitbucketAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + repoVisibility?: 'private' | 'public' | undefined; + sourcePath?: string | undefined; + enableLFS?: boolean | undefined; + token?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + }, + JsonObject +>; + +// @public +export function createPublishBitbucketCloudAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + repoVisibility?: 'private' | 'public' | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export function createPublishBitbucketServerAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + repoVisibility?: 'private' | 'public' | undefined; + sourcePath?: string | undefined; + enableLFS?: boolean | undefined; + token?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + }, + JsonObject +>; + +// @public +export function createPublishBitbucketServerPullRequestAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + title: string; + description?: string | undefined; + targetBranch?: string | undefined; + sourceBranch: string; + token?: string | undefined; + }, + JsonObject +>; +``` diff --git a/plugins/scaffolder-backend-module-bitbucket/src/index.ts b/plugins/scaffolder-backend-module-bitbucket/src/index.ts index 6448b82c8b..38d973efb8 100644 --- a/plugins/scaffolder-backend-module-bitbucket/src/index.ts +++ b/plugins/scaffolder-backend-module-bitbucket/src/index.ts @@ -15,7 +15,7 @@ */ /** - * The bitbucket module for @backstage/plugin-scaffolder-backend. + * A module for the scaffolder backend that lets you interact with bitbucket * * @packageDocumentation */ diff --git a/plugins/scaffolder-backend-module-gerrit/api-report.md b/plugins/scaffolder-backend-module-gerrit/api-report.md new file mode 100644 index 0000000000..309de08574 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/api-report.md @@ -0,0 +1,43 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-gerrit" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { JsonObject } from '@backstage/types'; +import { ScmIntegrationRegistry } from '@backstage/integration'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; + +// @public +export function createPublishGerritAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + description: string; + defaultBranch?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + sourcePath?: string | undefined; + }, + JsonObject +>; + +// @public +export function createPublishGerritReviewAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + branch?: string | undefined; + sourcePath?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + }, + JsonObject +>; +``` diff --git a/plugins/scaffolder-backend-module-gerrit/package.json b/plugins/scaffolder-backend-module-gerrit/package.json index f3797accb3..9502d9967d 100644 --- a/plugins/scaffolder-backend-module-gerrit/package.json +++ b/plugins/scaffolder-backend-module-gerrit/package.json @@ -23,10 +23,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/plugin-scaffolder-node": "workspace:^", + "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", - "@backstage/config": "workspace:^", + "@backstage/plugin-scaffolder-node": "workspace:^", "node-fetch": "^2.6.7", "yaml": "^2.0.0" }, diff --git a/plugins/scaffolder-backend-module-gerrit/src/index.ts b/plugins/scaffolder-backend-module-gerrit/src/index.ts index 21fdd116e7..b00c307fa5 100644 --- a/plugins/scaffolder-backend-module-gerrit/src/index.ts +++ b/plugins/scaffolder-backend-module-gerrit/src/index.ts @@ -15,7 +15,7 @@ */ /** - * The gerrit module for @backstage/plugin-scaffolder-backend. + * A module for the scaffolder backend that lets you interact with gerrit * * @packageDocumentation */ diff --git a/plugins/scaffolder-backend-module-github/api-report.md b/plugins/scaffolder-backend-module-github/api-report.md new file mode 100644 index 0000000000..bb3ec4e7c4 --- /dev/null +++ b/plugins/scaffolder-backend-module-github/api-report.md @@ -0,0 +1,365 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-github" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { createPullRequest } from 'octokit-plugin-create-pull-request'; +import { GithubCredentialsProvider } from '@backstage/integration'; +import { JsonObject } from '@backstage/types'; +import { Octokit } from 'octokit'; +import { ScmIntegrationRegistry } from '@backstage/integration'; +import { ScmIntegrations } from '@backstage/integration'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; + +// @public +export function createGithubActionsDispatchAction(options: { + integrations: ScmIntegrations; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + workflowId: string; + branchOrTagName: string; + workflowInputs?: + | { + [key: string]: string; + } + | undefined; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export function createGithubDeployKeyAction(options: { + integrations: ScmIntegrationRegistry; +}): TemplateAction< + { + repoUrl: string; + publicKey: string; + privateKey: string; + deployKeyName: string; + privateKeySecretName?: string | undefined; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export function createGithubEnvironmentAction(options: { + integrations: ScmIntegrationRegistry; +}): TemplateAction< + { + repoUrl: string; + name: string; + deploymentBranchPolicy?: + | { + protected_branches: boolean; + custom_branch_policies: boolean; + } + | undefined; + customBranchPolicyNames?: string[] | undefined; + environmentVariables?: + | { + [key: string]: string; + } + | undefined; + secrets?: + | { + [key: string]: string; + } + | undefined; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export function createGithubIssuesLabelAction(options: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + number: number; + labels: string[]; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export interface CreateGithubPullRequestActionOptions { + clientFactory?: (input: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; + host: string; + owner: string; + repo: string; + token?: string; + }) => Promise< + Octokit & { + createPullRequest(options: createPullRequest.Options): Promise<{ + data: { + html_url: string; + number: number; + base: { + ref: string; + }; + }; + } | null>; + } + >; + githubCredentialsProvider?: GithubCredentialsProvider; + integrations: ScmIntegrationRegistry; +} + +// @public +export function createGithubRepoCreateAction(options: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + homepage?: string | undefined; + access?: string | undefined; + deleteBranchOnMerge?: boolean | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + allowRebaseMerge?: boolean | undefined; + allowSquashMerge?: boolean | undefined; + squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined; + squashMergeCommitMessage?: + | 'PR_BODY' + | 'COMMIT_MESSAGES' + | 'BLANK' + | undefined; + allowMergeCommit?: boolean | undefined; + allowAutoMerge?: boolean | undefined; + requireCodeOwnerReviews?: boolean | undefined; + bypassPullRequestAllowances?: + | { + users?: string[] | undefined; + teams?: string[] | undefined; + apps?: string[] | undefined; + } + | undefined; + requiredApprovingReviewCount?: number | undefined; + restrictions?: + | { + users: string[]; + teams: string[]; + apps?: string[] | undefined; + } + | undefined; + requiredStatusCheckContexts?: string[] | undefined; + requireBranchesToBeUpToDate?: boolean | undefined; + requiredConversationResolution?: boolean | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + collaborators?: + | ( + | { + user: string; + access: string; + } + | { + team: string; + access: string; + } + | { + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + )[] + | undefined; + hasProjects?: boolean | undefined; + hasWiki?: boolean | undefined; + hasIssues?: boolean | undefined; + token?: string | undefined; + topics?: string[] | undefined; + repoVariables?: + | { + [key: string]: string; + } + | undefined; + secrets?: + | { + [key: string]: string; + } + | undefined; + requireCommitSigning?: boolean | undefined; + }, + JsonObject +>; + +// @public +export function createGithubRepoPushAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + protectDefaultBranch?: boolean | undefined; + protectEnforceAdmins?: boolean | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + requireCodeOwnerReviews?: boolean | undefined; + dismissStaleReviews?: boolean | undefined; + bypassPullRequestAllowances?: + | { + users?: string[]; + teams?: string[]; + apps?: string[]; + } + | undefined; + requiredApprovingReviewCount?: number | undefined; + restrictions?: + | { + users: string[]; + teams: string[]; + apps?: string[]; + } + | undefined; + requiredStatusCheckContexts?: string[] | undefined; + requireBranchesToBeUpToDate?: boolean | undefined; + requiredConversationResolution?: boolean | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + requiredCommitSigning?: boolean | undefined; + }, + JsonObject +>; + +// @public +export function createGithubWebhookAction(options: { + integrations: ScmIntegrationRegistry; + defaultWebhookSecret?: string; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + webhookUrl: string; + webhookSecret?: string | undefined; + events?: string[] | undefined; + active?: boolean | undefined; + contentType?: 'form' | 'json' | undefined; + insecureSsl?: boolean | undefined; + token?: string | undefined; + }, + JsonObject +>; + +// @public +export function createPublishGithubAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; + githubCredentialsProvider?: GithubCredentialsProvider; +}): TemplateAction< + { + repoUrl: string; + description?: string | undefined; + homepage?: string | undefined; + access?: string | undefined; + defaultBranch?: string | undefined; + protectDefaultBranch?: boolean | undefined; + protectEnforceAdmins?: boolean | undefined; + deleteBranchOnMerge?: boolean | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + allowRebaseMerge?: boolean | undefined; + allowSquashMerge?: boolean | undefined; + squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined; + squashMergeCommitMessage?: + | 'PR_BODY' + | 'COMMIT_MESSAGES' + | 'BLANK' + | undefined; + allowMergeCommit?: boolean | undefined; + allowAutoMerge?: boolean | undefined; + sourcePath?: string | undefined; + bypassPullRequestAllowances?: + | { + users?: string[]; + teams?: string[]; + apps?: string[]; + } + | undefined; + requiredApprovingReviewCount?: number | undefined; + restrictions?: + | { + users: string[]; + teams: string[]; + apps?: string[]; + } + | undefined; + requireCodeOwnerReviews?: boolean | undefined; + dismissStaleReviews?: boolean | undefined; + requiredStatusCheckContexts?: string[] | undefined; + requireBranchesToBeUpToDate?: boolean | undefined; + requiredConversationResolution?: boolean | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + collaborators?: + | ( + | { + user: string; + access: string; + } + | { + team: string; + access: string; + } + | { + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + } + )[] + | undefined; + hasProjects?: boolean | undefined; + hasWiki?: boolean | undefined; + hasIssues?: boolean | undefined; + token?: string | undefined; + topics?: string[] | undefined; + repoVariables?: + | { + [key: string]: string; + } + | undefined; + secrets?: + | { + [key: string]: string; + } + | undefined; + requiredCommitSigning?: boolean | undefined; + }, + JsonObject +>; + +// @public +export const createPublishGithubPullRequestAction: ( + options: CreateGithubPullRequestActionOptions, +) => TemplateAction< + { + title: string; + branchName: string; + targetBranchName?: string | undefined; + description: string; + repoUrl: string; + draft?: boolean | undefined; + targetPath?: string | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + reviewers?: string[] | undefined; + teamReviewers?: string[] | undefined; + commitMessage?: string | undefined; + update?: boolean | undefined; + }, + JsonObject +>; +``` diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts index 3f13f2ab67..7e5d107026 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.examples.test.ts @@ -23,10 +23,7 @@ import { ScmIntegrations, } from '@backstage/integration'; import { PassThrough } from 'stream'; -import { - OctokitWithPullRequestPluginClient, - createPublishGithubPullRequestAction, -} from './githubPullRequest'; +import { createPublishGithubPullRequestAction } from './githubPullRequest'; import yaml from 'yaml'; import { examples } from './githubPullRequest.examples'; import { createMockDirectory } from '@backstage/backend-test-utils'; @@ -103,9 +100,7 @@ describe('publish:github:pull-request examples', () => { }, }; - const clientFactory = jest.fn( - async () => fakeClient as unknown as OctokitWithPullRequestPluginClient, - ); + const clientFactory = jest.fn(async () => fakeClient as any); mockDir.setContent({ [workspacePath]: { 'file.txt': 'Hello there!' }, diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts index a1f3712a9d..23ac4bda45 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.test.ts @@ -26,10 +26,7 @@ import { } from '@backstage/plugin-scaffolder-node'; import fs from 'fs-extra'; import { Writable } from 'stream'; -import { - createPublishGithubPullRequestAction, - OctokitWithPullRequestPluginClient, -} from './githubPullRequest'; +import { createPublishGithubPullRequestAction } from './githubPullRequest'; import { createMockDirectory } from '@backstage/backend-test-utils'; // Make sure root logger is initialized ahead of FS mock @@ -78,9 +75,7 @@ describe('createPublishGithubPullRequestAction', () => { }, }, }; - const clientFactory = jest.fn( - async () => fakeClient as unknown as OctokitWithPullRequestPluginClient, - ); + const clientFactory = jest.fn(async () => fakeClient as any); const githubCredentialsProvider: GithubCredentialsProvider = { getCredentials: jest.fn(), }; diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts index 00e584226f..0763d4a474 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubPullRequest.ts @@ -37,57 +37,32 @@ export type Encoding = 'utf-8' | 'base64'; class GithubResponseError extends CustomErrorBase {} -/** @public */ -export type OctokitWithPullRequestPluginClient = Octokit & { - createPullRequest(options: createPullRequest.Options): Promise<{ - data: { - html_url: string; - number: number; - base: { - ref: string; - }; - }; - } | null>; -}; - -/** - * The options passed to the client factory function. - * @public - */ -export type CreateGithubPullRequestClientFactoryInput = { - integrations: ScmIntegrationRegistry; - githubCredentialsProvider?: GithubCredentialsProvider; - host: string; - owner: string; - repo: string; - token?: string; -}; - -export const defaultClientFactory = async ({ - integrations, - githubCredentialsProvider, - owner, - repo, - host = 'github.com', - token: providedToken, -}: CreateGithubPullRequestClientFactoryInput): Promise => { - const [encodedHost, encodedOwner, encodedRepo] = [host, owner, repo].map( - encodeURIComponent, - ); - - const octokitOptions = await getOctokitOptions({ +export const defaultClientFactory: CreateGithubPullRequestActionOptions['clientFactory'] = + async ({ integrations, - credentialsProvider: githubCredentialsProvider, - repoUrl: `${encodedHost}?owner=${encodedOwner}&repo=${encodedRepo}`, + githubCredentialsProvider, + owner, + repo, + host = 'github.com', token: providedToken, - }); + }) => { + const [encodedHost, encodedOwner, encodedRepo] = [host, owner, repo].map( + encodeURIComponent, + ); - const OctokitPR = Octokit.plugin(createPullRequest); - return new OctokitPR({ - ...octokitOptions, - ...{ throttle: { enabled: false } }, - }); -}; + const octokitOptions = await getOctokitOptions({ + integrations, + credentialsProvider: githubCredentialsProvider, + repoUrl: `${encodedHost}?owner=${encodedOwner}&repo=${encodedRepo}`, + token: providedToken, + }); + + const OctokitPR = Octokit.plugin(createPullRequest); + return new OctokitPR({ + ...octokitOptions, + ...{ throttle: { enabled: false } }, + }); + }; /** * The options passed to {@link createPublishGithubPullRequestAction} method @@ -105,9 +80,26 @@ export interface CreateGithubPullRequestActionOptions { /** * A method to return the Octokit client with the Pull Request Plugin. */ - clientFactory?: ( - input: CreateGithubPullRequestClientFactoryInput, - ) => Promise; + clientFactory?: (input: { + integrations: ScmIntegrationRegistry; + githubCredentialsProvider?: GithubCredentialsProvider; + host: string; + owner: string; + repo: string; + token?: string; + }) => Promise< + Octokit & { + createPullRequest(options: createPullRequest.Options): Promise<{ + data: { + html_url: string; + number: number; + base: { + ref: string; + }; + }; + } | null>; + } + >; } type GithubPullRequest = { diff --git a/plugins/scaffolder-backend-module-github/src/actions/index.ts b/plugins/scaffolder-backend-module-github/src/actions/index.ts index 9c3927f31d..ebcda41d93 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/index.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/index.ts @@ -22,5 +22,8 @@ export { createGithubWebhookAction } from './githubWebhook'; export { createGithubDeployKeyAction } from './githubDeployKey'; export { createGithubEnvironmentAction } from './githubEnvironment'; -export { createPublishGithubPullRequestAction } from './githubPullRequest'; +export { + createPublishGithubPullRequestAction, + type CreateGithubPullRequestActionOptions, +} from './githubPullRequest'; export { createPublishGithubAction } from './github'; diff --git a/plugins/scaffolder-backend-module-github/src/index.ts b/plugins/scaffolder-backend-module-github/src/index.ts index b4d8dbcb6d..948a79d957 100644 --- a/plugins/scaffolder-backend-module-github/src/index.ts +++ b/plugins/scaffolder-backend-module-github/src/index.ts @@ -15,7 +15,7 @@ */ /** - * The github module for @backstage/plugin-scaffolder-backend. + * A module for the scaffolder backend that lets you interact with github * * @packageDocumentation */ diff --git a/plugins/scaffolder-backend-module-gitlab/api-report.md b/plugins/scaffolder-backend-module-gitlab/api-report.md index eccada5d51..debc31412a 100644 --- a/plugins/scaffolder-backend-module-gitlab/api-report.md +++ b/plugins/scaffolder-backend-module-gitlab/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { Config } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; @@ -74,4 +75,75 @@ export const createGitlabProjectVariableAction: (options: { }, JsonObject >; + +// @public +export function createPublishGitlabAction(options: { + integrations: ScmIntegrationRegistry; + config: Config; +}): TemplateAction< + { + repoUrl: string; + defaultBranch?: string | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + gitCommitMessage?: string | undefined; + gitAuthorName?: string | undefined; + gitAuthorEmail?: string | undefined; + setUserAsOwner?: boolean | undefined; + topics?: string[] | undefined; + settings?: + | { + path?: string | undefined; + auto_devops_enabled?: boolean | undefined; + ci_config_path?: string | undefined; + description?: string | undefined; + topics?: string[] | undefined; + visibility?: 'internal' | 'private' | 'public' | undefined; + } + | undefined; + branches?: + | { + name: string; + protect?: boolean | undefined; + create?: boolean | undefined; + ref?: string | undefined; + }[] + | undefined; + projectVariables?: + | { + key: string; + value: string; + description?: string | undefined; + variable_type?: string | undefined; + protected?: boolean | undefined; + masked?: boolean | undefined; + raw?: boolean | undefined; + environment_scope?: string | undefined; + }[] + | undefined; + }, + JsonObject +>; + +// @public +export const createPublishGitlabMergeRequestAction: (options: { + integrations: ScmIntegrationRegistry; +}) => TemplateAction< + { + repoUrl: string; + title: string; + description: string; + branchName: string; + targetBranchName?: string | undefined; + sourcePath?: string | undefined; + targetPath?: string | undefined; + token?: string | undefined; + commitAction?: 'update' | 'delete' | 'create' | undefined; + projectid?: string | undefined; + removeSourceBranch?: boolean | undefined; + assignee?: string | undefined; + }, + JsonObject +>; ``` diff --git a/plugins/scaffolder-backend-module-gitlab/src/index.ts b/plugins/scaffolder-backend-module-gitlab/src/index.ts index 844f753344..11d4247569 100644 --- a/plugins/scaffolder-backend-module-gitlab/src/index.ts +++ b/plugins/scaffolder-backend-module-gitlab/src/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2023 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,4 +19,5 @@ * * @packageDocumentation */ + export * from './actions'; diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index b92b883767..72af83aa6b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -6,19 +6,16 @@ import { ActionContext as ActionContext_2 } from '@backstage/plugin-scaffolder-node'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; -import { createPullRequest } from 'octokit-plugin-create-pull-request'; import { Duration } from 'luxon'; import { executeShellCommand as executeShellCommand_2 } from '@backstage/plugin-scaffolder-node'; import { ExecuteShellCommandOptions } from '@backstage/plugin-scaffolder-node'; import express from 'express'; import { fetchContents as fetchContents_2 } from '@backstage/plugin-scaffolder-node'; -import { GithubCredentialsProvider } from '@backstage/integration'; import { HumanDuration } from '@backstage/types'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { JsonObject } from '@backstage/types'; import { Knex } from 'knex'; import { Logger } from 'winston'; -import { Octokit } from 'octokit'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; @@ -28,7 +25,6 @@ import { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-co import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha'; import { ScaffolderEntitiesProcessor as ScaffolderEntitiesProcessor_2 } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; import { Schema } from 'jsonschema'; -import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; import { SerializedTask as SerializedTask_2 } from '@backstage/plugin-scaffolder-node'; import { SerializedTaskEvent as SerializedTaskEvent_2 } from '@backstage/plugin-scaffolder-node'; @@ -197,544 +193,6 @@ export const createFilesystemRenameAction: () => TemplateAction_2< JsonObject >; -// @public -export function createGithubActionsDispatchAction(options: { - integrations: ScmIntegrations; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - workflowId: string; - branchOrTagName: string; - workflowInputs?: - | { - [key: string]: string; - } - | undefined; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createGithubDeployKeyAction(options: { - integrations: ScmIntegrationRegistry; -}): TemplateAction_2< - { - repoUrl: string; - publicKey: string; - privateKey: string; - deployKeyName: string; - privateKeySecretName?: string | undefined; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createGithubEnvironmentAction(options: { - integrations: ScmIntegrationRegistry; -}): TemplateAction_2< - { - repoUrl: string; - name: string; - deploymentBranchPolicy?: - | { - protected_branches: boolean; - custom_branch_policies: boolean; - } - | undefined; - customBranchPolicyNames?: string[] | undefined; - environmentVariables?: - | { - [key: string]: string; - } - | undefined; - secrets?: - | { - [key: string]: string; - } - | undefined; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createGithubIssuesLabelAction(options: { - integrations: ScmIntegrationRegistry; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - number: number; - labels: string[]; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export interface CreateGithubPullRequestActionOptions { - clientFactory?: ( - input: CreateGithubPullRequestClientFactoryInput, - ) => Promise; - githubCredentialsProvider?: GithubCredentialsProvider; - integrations: ScmIntegrationRegistry; -} - -// @public -export type CreateGithubPullRequestClientFactoryInput = { - integrations: ScmIntegrationRegistry; - githubCredentialsProvider?: GithubCredentialsProvider; - host: string; - owner: string; - repo: string; - token?: string; -}; - -// @public -export function createGithubRepoCreateAction(options: { - integrations: ScmIntegrationRegistry; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - homepage?: string | undefined; - access?: string | undefined; - deleteBranchOnMerge?: boolean | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - allowRebaseMerge?: boolean | undefined; - allowSquashMerge?: boolean | undefined; - squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined; - squashMergeCommitMessage?: - | 'PR_BODY' - | 'COMMIT_MESSAGES' - | 'BLANK' - | undefined; - allowMergeCommit?: boolean | undefined; - allowAutoMerge?: boolean | undefined; - requireCodeOwnerReviews?: boolean | undefined; - bypassPullRequestAllowances?: - | { - users?: string[] | undefined; - teams?: string[] | undefined; - apps?: string[] | undefined; - } - | undefined; - requiredApprovingReviewCount?: number | undefined; - restrictions?: - | { - users: string[]; - teams: string[]; - apps?: string[] | undefined; - } - | undefined; - requiredStatusCheckContexts?: string[] | undefined; - requireBranchesToBeUpToDate?: boolean | undefined; - requiredConversationResolution?: boolean | undefined; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; - collaborators?: - | ( - | { - user: string; - access: string; - } - | { - team: string; - access: string; - } - | { - username: string; - access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; - } - )[] - | undefined; - hasProjects?: boolean | undefined; - hasWiki?: boolean | undefined; - hasIssues?: boolean | undefined; - token?: string | undefined; - topics?: string[] | undefined; - repoVariables?: - | { - [key: string]: string; - } - | undefined; - secrets?: - | { - [key: string]: string; - } - | undefined; - requireCommitSigning?: boolean | undefined; - }, - JsonObject ->; - -// @public -export function createGithubRepoPushAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - defaultBranch?: string | undefined; - protectDefaultBranch?: boolean | undefined; - protectEnforceAdmins?: boolean | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - requireCodeOwnerReviews?: boolean | undefined; - dismissStaleReviews?: boolean | undefined; - bypassPullRequestAllowances?: - | { - users?: string[]; - teams?: string[]; - apps?: string[]; - } - | undefined; - requiredApprovingReviewCount?: number | undefined; - restrictions?: - | { - users: string[]; - teams: string[]; - apps?: string[]; - } - | undefined; - requiredStatusCheckContexts?: string[] | undefined; - requireBranchesToBeUpToDate?: boolean | undefined; - requiredConversationResolution?: boolean | undefined; - sourcePath?: string | undefined; - token?: string | undefined; - requiredCommitSigning?: boolean | undefined; - }, - JsonObject ->; - -// @public -export function createGithubWebhookAction(options: { - integrations: ScmIntegrationRegistry; - defaultWebhookSecret?: string; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - webhookUrl: string; - webhookSecret?: string | undefined; - events?: string[] | undefined; - active?: boolean | undefined; - contentType?: 'form' | 'json' | undefined; - insecureSsl?: boolean | undefined; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishAzureAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - defaultBranch?: string | undefined; - sourcePath?: string | undefined; - token?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - }, - JsonObject ->; - -// @public @deprecated -export function createPublishBitbucketAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - defaultBranch?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; - sourcePath?: string | undefined; - enableLFS?: boolean | undefined; - token?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishBitbucketCloudAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - defaultBranch?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; - sourcePath?: string | undefined; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishBitbucketServerAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - defaultBranch?: string | undefined; - repoVisibility?: 'private' | 'public' | undefined; - sourcePath?: string | undefined; - enableLFS?: boolean | undefined; - token?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishBitbucketServerPullRequestAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - title: string; - description?: string | undefined; - targetBranch?: string | undefined; - sourceBranch: string; - token?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishGerritAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - description: string; - defaultBranch?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - sourcePath?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishGerritReviewAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - branch?: string | undefined; - sourcePath?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - }, - JsonObject ->; - -// @public -export function createPublishGithubAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; - githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction_2< - { - repoUrl: string; - description?: string | undefined; - homepage?: string | undefined; - access?: string | undefined; - defaultBranch?: string | undefined; - protectDefaultBranch?: boolean | undefined; - protectEnforceAdmins?: boolean | undefined; - deleteBranchOnMerge?: boolean | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - allowRebaseMerge?: boolean | undefined; - allowSquashMerge?: boolean | undefined; - squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined; - squashMergeCommitMessage?: - | 'PR_BODY' - | 'COMMIT_MESSAGES' - | 'BLANK' - | undefined; - allowMergeCommit?: boolean | undefined; - allowAutoMerge?: boolean | undefined; - sourcePath?: string | undefined; - bypassPullRequestAllowances?: - | { - users?: string[]; - teams?: string[]; - apps?: string[]; - } - | undefined; - requiredApprovingReviewCount?: number | undefined; - restrictions?: - | { - users: string[]; - teams: string[]; - apps?: string[]; - } - | undefined; - requireCodeOwnerReviews?: boolean | undefined; - dismissStaleReviews?: boolean | undefined; - requiredStatusCheckContexts?: string[] | undefined; - requireBranchesToBeUpToDate?: boolean | undefined; - requiredConversationResolution?: boolean | undefined; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; - collaborators?: - | ( - | { - user: string; - access: string; - } - | { - team: string; - access: string; - } - | { - username: string; - access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; - } - )[] - | undefined; - hasProjects?: boolean | undefined; - hasWiki?: boolean | undefined; - hasIssues?: boolean | undefined; - token?: string | undefined; - topics?: string[] | undefined; - repoVariables?: - | { - [key: string]: string; - } - | undefined; - secrets?: - | { - [key: string]: string; - } - | undefined; - requiredCommitSigning?: boolean | undefined; - }, - JsonObject ->; - -// @public -export const createPublishGithubPullRequestAction: ( - options: CreateGithubPullRequestActionOptions, -) => TemplateAction_2< - { - title: string; - branchName: string; - targetBranchName?: string | undefined; - description: string; - repoUrl: string; - draft?: boolean | undefined; - targetPath?: string | undefined; - sourcePath?: string | undefined; - token?: string | undefined; - reviewers?: string[] | undefined; - teamReviewers?: string[] | undefined; - commitMessage?: string | undefined; - update?: boolean | undefined; - }, - JsonObject ->; - -// @public -export function createPublishGitlabAction(options: { - integrations: ScmIntegrationRegistry; - config: Config; -}): TemplateAction_2< - { - repoUrl: string; - defaultBranch?: string | undefined; - repoVisibility?: 'internal' | 'private' | 'public' | undefined; - sourcePath?: string | undefined; - token?: string | undefined; - gitCommitMessage?: string | undefined; - gitAuthorName?: string | undefined; - gitAuthorEmail?: string | undefined; - setUserAsOwner?: boolean | undefined; - topics?: string[] | undefined; - settings?: - | { - path?: string | undefined; - auto_devops_enabled?: boolean | undefined; - ci_config_path?: string | undefined; - description?: string | undefined; - topics?: string[] | undefined; - visibility?: 'internal' | 'private' | 'public' | undefined; - } - | undefined; - branches?: - | { - name: string; - protect?: boolean | undefined; - create?: boolean | undefined; - ref?: string | undefined; - }[] - | undefined; - projectVariables?: - | { - key: string; - value: string; - description?: string | undefined; - variable_type?: string | undefined; - protected?: boolean | undefined; - masked?: boolean | undefined; - raw?: boolean | undefined; - environment_scope?: string | undefined; - }[] - | undefined; - }, - JsonObject ->; - -// @public -export const createPublishGitlabMergeRequestAction: (options: { - integrations: ScmIntegrationRegistry; -}) => TemplateAction_2< - { - repoUrl: string; - title: string; - description: string; - branchName: string; - targetBranchName?: string | undefined; - sourcePath?: string | undefined; - targetPath?: string | undefined; - token?: string | undefined; - commitAction?: 'update' | 'delete' | 'create' | undefined; - projectid?: string | undefined; - removeSourceBranch?: boolean | undefined; - assignee?: string | undefined; - }, - JsonObject ->; - // @public export function createRouter(options: RouterOptions): Promise; @@ -858,19 +316,6 @@ export const executeShellCommand: typeof executeShellCommand_2; // @public @deprecated export const fetchContents: typeof fetchContents_2; -// @public (undocumented) -export type OctokitWithPullRequestPluginClient = Octokit & { - createPullRequest(options: createPullRequest.Options): Promise<{ - data: { - html_url: string; - number: number; - base: { - ref: string; - }; - }; - } | null>; -}; - // @public export interface RouterOptions { // (undocumented) diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index 08caf36812..ca1b9e8b4e 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -10,6 +10,7 @@ import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; import { Observable } from '@backstage/types'; import { Schema } from 'jsonschema'; +import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; import { SpawnOptionsWithoutStdio } from 'child_process'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; @@ -44,6 +45,37 @@ export type ActionContext< each?: JsonObject; }; +// @public (undocumented) +export function commitAndPushRepo({ + dir, + auth, + logger, + commitMessage, + gitAuthorInfo, + branch, + remoteRef, +}: { + dir: string; + auth: + | { + username: string; + password: string; + } + | { + token: string; + }; + logger: Logger; + commitMessage: string; + gitAuthorInfo?: { + name?: string; + email?: string; + }; + branch?: string; + remoteRef?: string; +}): Promise<{ + commitHash: string; +}>; + // @public export const createTemplateAction: < TInputParams extends JsonObject = JsonObject, @@ -73,6 +105,12 @@ export const createTemplateAction: < >, ) => TemplateAction; +// @public +export function deserializeDirectoryContents( + targetPath: string, + files: SerializedFile[], +): Promise; + // @public export function executeShellCommand( options: ExecuteShellCommandOptions, @@ -104,6 +142,77 @@ export function fetchFile(options: { outputPath: string; }): Promise; +// @public (undocumented) +export const getRepoSourceDirectory: ( + workspacePath: string, + sourcePath: string | undefined, +) => string; + +// @public (undocumented) +export function initRepoAndPush({ + dir, + remoteUrl, + auth, + logger, + defaultBranch, + commitMessage, + gitAuthorInfo, +}: { + dir: string; + remoteUrl: string; + auth: + | { + username: string; + password: string; + } + | { + token: string; + }; + logger: Logger; + defaultBranch?: string; + commitMessage?: string; + gitAuthorInfo?: { + name?: string; + email?: string; + }; +}): Promise<{ + commitHash: string; +}>; + +// @public (undocumented) +export const parseRepoUrl: ( + repoUrl: string, + integrations: ScmIntegrationRegistry, +) => { + repo: string; + host: string; + owner?: string | undefined; + organization?: string | undefined; + workspace?: string | undefined; + project?: string | undefined; +}; + +// @public (undocumented) +export interface SerializedFile { + // (undocumented) + content: Buffer; + // (undocumented) + executable?: boolean; + // (undocumented) + path: string; + // (undocumented) + symlink?: boolean; +} + +// @public (undocumented) +export function serializeDirectoryContents( + sourcePath: string, + options?: { + gitignore?: boolean; + globPatterns?: string[]; + }, +): Promise; + // @public export type SerializedTask = { id: string; diff --git a/plugins/scaffolder-node/src/actions/repoHelpers.ts b/plugins/scaffolder-node/src/actions/gitHelpers.ts similarity index 98% rename from plugins/scaffolder-node/src/actions/repoHelpers.ts rename to plugins/scaffolder-node/src/actions/gitHelpers.ts index a814ca38ed..770440dba3 100644 --- a/plugins/scaffolder-node/src/actions/repoHelpers.ts +++ b/plugins/scaffolder-node/src/actions/gitHelpers.ts @@ -17,6 +17,9 @@ import { Git } from '@backstage/backend-common'; import { Logger } from 'winston'; +/** + * @public + */ export async function initRepoAndPush({ dir, remoteUrl, @@ -75,6 +78,9 @@ export async function initRepoAndPush({ return { commitHash }; } +/** + * @public + */ export async function commitAndPushRepo({ dir, auth, diff --git a/plugins/scaffolder-node/src/actions/index.ts b/plugins/scaffolder-node/src/actions/index.ts index 27046bebaf..74a0bb61f9 100644 --- a/plugins/scaffolder-node/src/actions/index.ts +++ b/plugins/scaffolder-node/src/actions/index.ts @@ -25,5 +25,5 @@ export { } from './executeShellCommand'; export { fetchContents, fetchFile } from './fetch'; export { type ActionContext, type TemplateAction } from './types'; -export { initRepoAndPush, commitAndPushRepo } from './repoHelpers'; +export { initRepoAndPush, commitAndPushRepo } from './gitHelpers'; export { parseRepoUrl, getRepoSourceDirectory } from './util'; diff --git a/plugins/scaffolder-node/src/actions/util.ts b/plugins/scaffolder-node/src/actions/util.ts index cdd8512e63..327cfa9c2f 100644 --- a/plugins/scaffolder-node/src/actions/util.ts +++ b/plugins/scaffolder-node/src/actions/util.ts @@ -19,6 +19,9 @@ import { isChildPath } from '@backstage/backend-common'; import { join as joinPath, normalize as normalizePath } from 'path'; import { ScmIntegrationRegistry } from '@backstage/integration'; +/** + * @public + */ export const getRepoSourceDirectory = ( workspacePath: string, sourcePath: string | undefined, @@ -37,6 +40,9 @@ export const getRepoSourceDirectory = ( return workspacePath; }; +/** + * @public + */ export const parseRepoUrl = ( repoUrl: string, integrations: ScmIntegrationRegistry, diff --git a/plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts b/plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts index cb567eed9d..bdcecd99f1 100644 --- a/plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts +++ b/plugins/scaffolder-node/src/files/deserializeDirectoryContents.ts @@ -25,7 +25,7 @@ import { SerializedFile } from './types'; * This method uses `resolveSafeChildPath` to make sure that files are * not written outside of the target directory. * - * @internal + * @public */ export async function deserializeDirectoryContents( targetPath: string, diff --git a/plugins/scaffolder-node/src/files/serializeDirectoryContents.ts b/plugins/scaffolder-node/src/files/serializeDirectoryContents.ts index 1197db000a..7e52f6323b 100644 --- a/plugins/scaffolder-node/src/files/serializeDirectoryContents.ts +++ b/plugins/scaffolder-node/src/files/serializeDirectoryContents.ts @@ -41,6 +41,9 @@ async function asyncFilter( return array.filter((_value, index) => filterMap[index]); } +/** + * @public + */ export async function serializeDirectoryContents( sourcePath: string, options?: { diff --git a/plugins/scaffolder-node/src/files/types.ts b/plugins/scaffolder-node/src/files/types.ts index d3a1eaa008..cd471a7881 100644 --- a/plugins/scaffolder-node/src/files/types.ts +++ b/plugins/scaffolder-node/src/files/types.ts @@ -14,6 +14,9 @@ * limitations under the License. */ +/** + * @public + */ export interface SerializedFile { path: string; content: Buffer; diff --git a/plugins/scaffolder-react/src/components/types.ts b/plugins/scaffolder-react/src/components/types.ts index e9ec3bf711..597998bac4 100644 --- a/plugins/scaffolder-react/src/components/types.ts +++ b/plugins/scaffolder-react/src/components/types.ts @@ -23,7 +23,6 @@ import { JsonObject } from '@backstage/types'; export type TemplateGroupFilter = { title?: React.ReactNode; filter: (entity: TemplateEntityV1beta3) => boolean; - sort?: (a: TemplateEntityV1beta3, b: TemplateEntityV1beta3) => number; }; /** From 219d7f0ca77118632c42da5a0d16849fc2b1ba02 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 14:32:07 +0100 Subject: [PATCH 10/15] chore: add changesets Signed-off-by: blam --- .changeset/clever-rats-smoke.md | 5 +++++ .changeset/kind-eels-sing.md | 6 ++++++ .changeset/long-trainers-matter.md | 5 +++++ .changeset/shiny-cheetahs-vanish.md | 8 ++++++++ 4 files changed, 24 insertions(+) create mode 100644 .changeset/clever-rats-smoke.md create mode 100644 .changeset/kind-eels-sing.md create mode 100644 .changeset/long-trainers-matter.md create mode 100644 .changeset/shiny-cheetahs-vanish.md diff --git a/.changeset/clever-rats-smoke.md b/.changeset/clever-rats-smoke.md new file mode 100644 index 0000000000..9374e325f2 --- /dev/null +++ b/.changeset/clever-rats-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +--- + +Extract some more actions to this library diff --git a/.changeset/kind-eels-sing.md b/.changeset/kind-eels-sing.md new file mode 100644 index 0000000000..3f95a62d60 --- /dev/null +++ b/.changeset/kind-eels-sing.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-node': patch +--- + +Refactor some methods to `-node` instead and use the new external modules diff --git a/.changeset/long-trainers-matter.md b/.changeset/long-trainers-matter.md new file mode 100644 index 0000000000..92daf131b4 --- /dev/null +++ b/.changeset/long-trainers-matter.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updating template generation for scaffolder module diff --git a/.changeset/shiny-cheetahs-vanish.md b/.changeset/shiny-cheetahs-vanish.md new file mode 100644 index 0000000000..38c88bdb23 --- /dev/null +++ b/.changeset/shiny-cheetahs-vanish.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-scaffolder-backend-module-bitbucket': minor +'@backstage/plugin-scaffolder-backend-module-gerrit': minor +'@backstage/plugin-scaffolder-backend-module-github': minor +'@backstage/plugin-scaffolder-backend-module-azure': minor +--- + +Create new scaffolder module for external integrations From 5e0c1f36e21b229ab854f9b511aa02499dffb7de Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 14:44:54 +0100 Subject: [PATCH 11/15] chore: updating catalog-info.yaml Signed-off-by: blam --- .../scaffolder-backend-module-azure/catalog-info.yaml | 10 ++++++++++ .../catalog-info.yaml | 10 ++++++++++ .../scaffolder-backend-module-gerrit/catalog-info.yaml | 10 ++++++++++ .../scaffolder-backend-module-github/catalog-info.yaml | 10 ++++++++++ plugins/scaffolder-backend/package.json | 2 +- yarn.lock | 2 +- 6 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 plugins/scaffolder-backend-module-azure/catalog-info.yaml create mode 100644 plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml create mode 100644 plugins/scaffolder-backend-module-gerrit/catalog-info.yaml create mode 100644 plugins/scaffolder-backend-module-github/catalog-info.yaml diff --git a/plugins/scaffolder-backend-module-azure/catalog-info.yaml b/plugins/scaffolder-backend-module-azure/catalog-info.yaml new file mode 100644 index 0000000000..16ae855eae --- /dev/null +++ b/plugins/scaffolder-backend-module-azure/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-scaffolder-backend-module-azure + title: '@backstage/plugin-scaffolder-backend-module-azure' + description: The azure module for @backstage/plugin-scaffolder-backend +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml b/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml new file mode 100644 index 0000000000..b0a94d1c13 --- /dev/null +++ b/plugins/scaffolder-backend-module-bitbucket/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-scaffolder-backend-module-bitbucket + title: '@backstage/plugin-scaffolder-backend-module-bitbucket' + description: The bitbucket module for @backstage/plugin-scaffolder-backend +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/scaffolder-backend-module-gerrit/catalog-info.yaml b/plugins/scaffolder-backend-module-gerrit/catalog-info.yaml new file mode 100644 index 0000000000..3eeb8a9018 --- /dev/null +++ b/plugins/scaffolder-backend-module-gerrit/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-scaffolder-backend-module-gerrit + title: '@backstage/plugin-scaffolder-backend-module-gerrit' + description: The gerrit module for @backstage/plugin-scaffolder-backend +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/scaffolder-backend-module-github/catalog-info.yaml b/plugins/scaffolder-backend-module-github/catalog-info.yaml new file mode 100644 index 0000000000..5e70704940 --- /dev/null +++ b/plugins/scaffolder-backend-module-github/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-scaffolder-backend-module-github + title: '@backstage/plugin-scaffolder-backend-module-github' + description: The github module for @backstage/plugin-scaffolder-backend +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 17f293f313..796c177caa 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -71,7 +71,6 @@ "@backstage/types": "workspace:^", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", - "azure-devops-node-api": "^11.0.1", "command-exists": "^1.2.9", "compression": "^1.7.4", "cors": "^2.8.5", @@ -100,6 +99,7 @@ "zod": "^3.21.4" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", diff --git a/yarn.lock b/yarn.lock index cc201b6204..8931801fe7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8804,6 +8804,7 @@ __metadata: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -8833,7 +8834,6 @@ __metadata: "@types/nunjucks": ^3.1.4 "@types/supertest": ^2.0.8 "@types/zen-observable": ^0.8.0 - azure-devops-node-api: ^11.0.1 command-exists: ^1.2.9 compression: ^1.7.4 cors: ^2.8.5 From 7640fe49572387c60f18f0ca915377a7ba388ec7 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 6 Dec 2023 15:06:18 +0100 Subject: [PATCH 12/15] chore: re-exported of the types Signed-off-by: blam --- plugins/scaffolder-backend/api-report.md | 101 ++++++ .../src/scaffolder/actions/deprecated.ts | 126 ++++++++ .../src/scaffolder/actions/index.ts | 2 + .../src/actions/gitHelpers.test.ts | 305 ++++++++++++++++++ 4 files changed, 534 insertions(+) create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/deprecated.ts create mode 100644 plugins/scaffolder-node/src/actions/gitHelpers.test.ts diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 72af83aa6b..c928e5341e 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -4,6 +4,8 @@ ```ts import { ActionContext as ActionContext_2 } from '@backstage/plugin-scaffolder-node'; +import * as azure from '@backstage/plugin-scaffolder-backend-module-azure'; +import * as bitbucket from '@backstage/plugin-scaffolder-backend-module-bitbucket'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { Duration } from 'luxon'; @@ -11,6 +13,9 @@ import { executeShellCommand as executeShellCommand_2 } from '@backstage/plugin- import { ExecuteShellCommandOptions } from '@backstage/plugin-scaffolder-node'; import express from 'express'; import { fetchContents as fetchContents_2 } from '@backstage/plugin-scaffolder-node'; +import * as gerrit from '@backstage/plugin-scaffolder-backend-module-gerrit'; +import * as github from '@backstage/plugin-scaffolder-backend-module-github'; +import * as gitlab from '@backstage/plugin-scaffolder-backend-module-gitlab'; import { HumanDuration } from '@backstage/types'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { JsonObject } from '@backstage/types'; @@ -25,6 +30,7 @@ import { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-co import { RESOURCE_TYPE_SCAFFOLDER_TEMPLATE } from '@backstage/plugin-scaffolder-common/alpha'; import { ScaffolderEntitiesProcessor as ScaffolderEntitiesProcessor_2 } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; import { Schema } from 'jsonschema'; +import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; import { SerializedTask as SerializedTask_2 } from '@backstage/plugin-scaffolder-node'; import { SerializedTaskEvent as SerializedTaskEvent_2 } from '@backstage/plugin-scaffolder-node'; @@ -193,6 +199,101 @@ export const createFilesystemRenameAction: () => TemplateAction_2< JsonObject >; +// @public @deprecated (undocumented) +export const createGithubActionsDispatchAction: typeof github.createGithubActionsDispatchAction; + +// @public @deprecated (undocumented) +export const createGithubDeployKeyAction: typeof github.createGithubDeployKeyAction; + +// @public @deprecated (undocumented) +export const createGithubEnvironmentAction: typeof github.createGithubEnvironmentAction; + +// @public @deprecated (undocumented) +export const createGithubIssuesLabelAction: typeof github.createGithubIssuesLabelAction; + +// @public @deprecated (undocumented) +export type CreateGithubPullRequestActionOptions = + github.CreateGithubPullRequestActionOptions; + +// @public @deprecated (undocumented) +export const createGithubRepoCreateAction: typeof github.createGithubRepoCreateAction; + +// @public @deprecated (undocumented) +export const createGithubRepoPushAction: typeof github.createGithubRepoPushAction; + +// @public @deprecated (undocumented) +export const createGithubWebhookAction: typeof github.createGithubWebhookAction; + +// @public @deprecated (undocumented) +export const createPublishAzureAction: typeof azure.createPublishAzureAction; + +// @public @deprecated (undocumented) +export const createPublishBitbucketAction: typeof bitbucket.createPublishBitbucketAction; + +// @public @deprecated (undocumented) +export const createPublishBitbucketCloudAction: typeof bitbucket.createPublishBitbucketCloudAction; + +// @public @deprecated (undocumented) +export const createPublishBitbucketServerAction: typeof bitbucket.createPublishBitbucketServerAction; + +// @public @deprecated (undocumented) +export const createPublishBitbucketServerPullRequestAction: typeof bitbucket.createPublishBitbucketServerPullRequestAction; + +// @public @deprecated (undocumented) +export const createPublishGerritAction: typeof gerrit.createPublishGerritAction; + +// @public @deprecated (undocumented) +export const createPublishGerritReviewAction: typeof gerrit.createPublishGerritReviewAction; + +// @public @deprecated (undocumented) +export const createPublishGithubAction: typeof github.createPublishGithubAction; + +// @public @deprecated (undocumented) +export const createPublishGithubPullRequestAction: ( + options: github.CreateGithubPullRequestActionOptions, +) => TemplateAction_2< + { + title: string; + branchName: string; + targetBranchName?: string | undefined; + description: string; + repoUrl: string; + draft?: boolean | undefined; + targetPath?: string | undefined; + sourcePath?: string | undefined; + token?: string | undefined; + reviewers?: string[] | undefined; + teamReviewers?: string[] | undefined; + commitMessage?: string | undefined; + update?: boolean | undefined; + }, + JsonObject +>; + +// @public @deprecated (undocumented) +export const createPublishGitlabAction: typeof gitlab.createPublishGitlabAction; + +// @public @deprecated (undocumented) +export const createPublishGitlabMergeRequestAction: (options: { + integrations: ScmIntegrationRegistry; +}) => TemplateAction_2< + { + repoUrl: string; + title: string; + description: string; + branchName: string; + targetBranchName?: string | undefined; + sourcePath?: string | undefined; + targetPath?: string | undefined; + token?: string | undefined; + commitAction?: 'update' | 'delete' | 'create' | undefined; + projectid?: string | undefined; + removeSourceBranch?: boolean | undefined; + assignee?: string | undefined; + }, + JsonObject +>; + // @public export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/deprecated.ts b/plugins/scaffolder-backend/src/scaffolder/actions/deprecated.ts new file mode 100644 index 0000000000..d5a13fbf6d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/deprecated.ts @@ -0,0 +1,126 @@ +/* + * Copyright 2023 The Backstage Authors + * + * 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 * as github from '@backstage/plugin-scaffolder-backend-module-github'; +import * as gitlab from '@backstage/plugin-scaffolder-backend-module-gitlab'; +import * as azure from '@backstage/plugin-scaffolder-backend-module-azure'; +import * as bitbucket from '@backstage/plugin-scaffolder-backend-module-bitbucket'; +import * as gerrit from '@backstage/plugin-scaffolder-backend-module-gerrit'; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubActionsDispatchAction = + github.createGithubActionsDispatchAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubDeployKeyAction = github.createGithubDeployKeyAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubEnvironmentAction = + github.createGithubEnvironmentAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubIssuesLabelAction = + github.createGithubIssuesLabelAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export type CreateGithubPullRequestActionOptions = + github.CreateGithubPullRequestActionOptions; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubRepoCreateAction = github.createGithubRepoCreateAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubRepoPushAction = github.createGithubRepoPushAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createGithubWebhookAction = github.createGithubWebhookAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createPublishGithubAction = github.createPublishGithubAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-github instead + */ +export const createPublishGithubPullRequestAction = + github.createPublishGithubPullRequestAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-bitbucket instead + */ +export const createPublishBitbucketAction = + bitbucket.createPublishBitbucketAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-bitbucket instead + */ +export const createPublishBitbucketCloudAction = + bitbucket.createPublishBitbucketCloudAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-bitbucket instead + */ +export const createPublishBitbucketServerAction = + bitbucket.createPublishBitbucketServerAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-bitbucket instead + */ +export const createPublishBitbucketServerPullRequestAction = + bitbucket.createPublishBitbucketServerPullRequestAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-azure instead + */ +export const createPublishAzureAction = azure.createPublishAzureAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-gerrit instead + */ +export const createPublishGerritAction = gerrit.createPublishGerritAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-gerrit instead + */ +export const createPublishGerritReviewAction = + gerrit.createPublishGerritReviewAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-gitlab instead + */ +export const createPublishGitlabAction = gitlab.createPublishGitlabAction; + +/** + * @public @deprecated use import from \@backstage/plugin-scaffolder-backend-module-gitlab instead + */ +export const createPublishGitlabMergeRequestAction = + gitlab.createPublishGitlabMergeRequestAction; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/index.ts index 9ea0607f06..8fdad68499 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/index.ts @@ -15,4 +15,6 @@ */ export * from './builtin'; +export * from './deprecated'; + export { TemplateActionRegistry } from './TemplateActionRegistry'; diff --git a/plugins/scaffolder-node/src/actions/gitHelpers.test.ts b/plugins/scaffolder-node/src/actions/gitHelpers.test.ts new file mode 100644 index 0000000000..7bc3f64f46 --- /dev/null +++ b/plugins/scaffolder-node/src/actions/gitHelpers.test.ts @@ -0,0 +1,305 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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, getVoidLogger } from '@backstage/backend-common'; +import { commitAndPushRepo, initRepoAndPush } from './gitHelpers'; + +jest.mock('@backstage/backend-common', () => ({ + Git: { + fromAuth: jest.fn().mockReturnValue({ + init: jest.fn(), + add: jest.fn(), + checkout: jest.fn(), + commit: jest + .fn() + .mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'), + fetch: jest.fn(), + addRemote: jest.fn(), + push: jest.fn(), + }), + }, + getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger, +})); + +const mockedGit = Git.fromAuth({ + logger: getVoidLogger(), +}); + +describe('initRepoAndPush', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('with minimal parameters', () => { + beforeEach(async () => { + await initRepoAndPush({ + dir: '/test/repo/dir/', + remoteUrl: 'git@github.com:test/repo.git', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + }); + }); + + it('initializes the repo', () => { + expect(mockedGit.init).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + defaultBranch: 'master', + }); + }); + + it('stages all files in the repo', () => { + expect(mockedGit.add).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + filepath: '.', + }); + }); + + it('creates an initial commit', () => { + expect(mockedGit.commit).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + message: 'Initial commit', + author: { + name: 'Scaffolder', + email: 'scaffolder@backstage.io', + }, + committer: { + name: 'Scaffolder', + email: 'scaffolder@backstage.io', + }, + }); + }); + + it('adds the appropriate remote', () => { + expect(mockedGit.addRemote).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + url: 'git@github.com:test/repo.git', + remote: 'origin', + }); + }); + + it('pushes to the remote', () => { + expect(mockedGit.push).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + remote: 'origin', + }); + }); + }); + + it('with token', async () => { + await initRepoAndPush({ + dir: '/test/repo/dir/', + remoteUrl: 'git@github.com:test/repo.git', + auth: { + token: 'test-token', + }, + logger: getVoidLogger(), + }); + + expect(mockedGit.init).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + defaultBranch: 'master', + }); + }); + + it('allows overriding the default branch', async () => { + await initRepoAndPush({ + dir: '/test/repo/dir/', + defaultBranch: 'trunk', + remoteUrl: 'git@github.com:test/repo.git', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + }); + + expect(mockedGit.init).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + defaultBranch: 'trunk', + }); + }); + + it('allows overriding the author', async () => { + await initRepoAndPush({ + dir: '/test/repo/dir/', + gitAuthorInfo: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + remoteUrl: 'git@github.com:test/repo.git', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + }); + + expect(mockedGit.commit).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + message: 'Initial commit', + author: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + committer: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + }); + }); +}); + +describe('commitAndPushRepo', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('with minimal parameters', () => { + beforeEach(async () => { + await commitAndPushRepo({ + dir: '/test/repo/dir/', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + commitMessage: 'commit message', + }); + }); + + it('fetches commits', () => { + expect(mockedGit.fetch).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + }); + }); + + it('checkouts to master', () => { + expect(mockedGit.checkout).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + ref: 'master', + }); + }); + + it('stages all files in the repo', () => { + expect(mockedGit.add).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + filepath: '.', + }); + }); + + it('creates a commit', () => { + expect(mockedGit.commit).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + message: 'commit message', + author: { + name: 'Scaffolder', + email: 'scaffolder@backstage.io', + }, + committer: { + name: 'Scaffolder', + email: 'scaffolder@backstage.io', + }, + }); + }); + + it('pushes to the remote', () => { + expect(mockedGit.push).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + remote: 'origin', + remoteRef: 'refs/heads/master', + }); + }); + }); + + it('allows overriding the default branch', async () => { + await commitAndPushRepo({ + dir: '/test/repo/dir/', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + commitMessage: 'commit message', + branch: 'otherbranch', + }); + + expect(mockedGit.checkout).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + ref: 'otherbranch', + }); + expect(mockedGit.push).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + remote: 'origin', + remoteRef: 'refs/heads/otherbranch', + }); + }); + + it('allows overriding the remote ref', async () => { + await commitAndPushRepo({ + dir: '/test/repo/dir/', + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + commitMessage: 'commit message', + remoteRef: 'refs/for/master', + }); + + expect(mockedGit.checkout).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + ref: 'master', + }); + expect(mockedGit.push).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + remote: 'origin', + remoteRef: 'refs/for/master', + }); + }); + + it('allows overriding the author', async () => { + await commitAndPushRepo({ + dir: '/test/repo/dir/', + commitMessage: 'commit message', + gitAuthorInfo: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + auth: { + username: 'test-user', + password: 'test-password', + }, + logger: getVoidLogger(), + branch: 'master', + }); + + expect(mockedGit.commit).toHaveBeenCalledWith({ + dir: '/test/repo/dir/', + message: 'commit message', + author: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + committer: { + name: 'Custom Scaffolder Author', + email: 'scaffolder@example.org', + }, + }); + }); +}); From 4552aae04330851107a931fc559f480f9cdfb719 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 7 Dec 2023 09:59:21 +0100 Subject: [PATCH 13/15] chore: removing some packages not necessary Signed-off-by: blam --- plugins/scaffolder-backend/package.json | 13 ------------- yarn.lock | 13 ------------- 2 files changed, 26 deletions(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 796c177caa..1bc0617131 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -55,9 +55,7 @@ "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", - "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "workspace:^", - "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", @@ -71,23 +69,16 @@ "@backstage/types": "workspace:^", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", - "command-exists": "^1.2.9", - "compression": "^1.7.4", - "cors": "^2.8.5", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "10.1.0", - "git-url-parse": "^13.0.0", "globby": "^11.0.0", "isbinaryfile": "^5.0.0", "isolated-vm": "^4.5.0", - "isomorphic-git": "^1.23.0", "jsonschema": "^1.2.6", "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", - "morgan": "^1.10.0", - "node-fetch": "^2.6.7", "nunjucks": "^3.2.3", "p-limit": "^3.1.0", "p-queue": "^6.6.2", @@ -101,15 +92,11 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", - "@types/git-url-parse": "^9.0.0", "@types/nunjucks": "^3.1.4", "@types/supertest": "^2.0.8", "@types/zen-observable": "^0.8.0", "esbuild": "^0.19.0", - "jest-when": "^3.1.0", - "msw": "^1.0.0", "strip-ansi": "^7.1.0", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2" diff --git a/yarn.lock b/yarn.lock index 8931801fe7..f302329de7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8812,9 +8812,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" - "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "workspace:^" - "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" @@ -8826,34 +8824,23 @@ __metadata: "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@backstage/types": "workspace:^" - "@types/command-exists": ^1.2.0 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 - "@types/git-url-parse": ^9.0.0 "@types/luxon": ^3.0.0 "@types/nunjucks": ^3.1.4 "@types/supertest": ^2.0.8 "@types/zen-observable": ^0.8.0 - command-exists: ^1.2.9 - compression: ^1.7.4 - cors: ^2.8.5 esbuild: ^0.19.0 express: ^4.17.1 express-promise-router: ^4.1.0 fs-extra: 10.1.0 - git-url-parse: ^13.0.0 globby: ^11.0.0 isbinaryfile: ^5.0.0 isolated-vm: ^4.5.0 - isomorphic-git: ^1.23.0 - jest-when: ^3.1.0 jsonschema: ^1.2.6 knex: ^3.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - morgan: ^1.10.0 - msw: ^1.0.0 - node-fetch: ^2.6.7 nunjucks: ^3.2.3 p-limit: ^3.1.0 p-queue: ^6.6.2 From 57d84d922a912187004286048584f8066337ef1f Mon Sep 17 00:00:00 2001 From: blam Date: Sat, 9 Dec 2023 10:41:24 +0100 Subject: [PATCH 14/15] chore: codereview comments Signed-off-by: blam --- .../package.json | 2 +- .../scaffolder-node/src/actions/gitHelpers.ts | 39 ++++++++++--------- yarn.lock | 4 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index d67aefbd27..da7ee27c83 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -37,7 +37,7 @@ "@backstage/integration": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "@gitbeaker/core": "^35.8.0", - "@gitbeaker/node": "^35.1.0", + "@gitbeaker/node": "^35.8.0", "yaml": "^2.0.0", "zod": "^3.21.4" }, diff --git a/plugins/scaffolder-node/src/actions/gitHelpers.ts b/plugins/scaffolder-node/src/actions/gitHelpers.ts index 770440dba3..6d449a0a29 100644 --- a/plugins/scaffolder-node/src/actions/gitHelpers.ts +++ b/plugins/scaffolder-node/src/actions/gitHelpers.ts @@ -20,15 +20,7 @@ import { Logger } from 'winston'; /** * @public */ -export async function initRepoAndPush({ - dir, - remoteUrl, - auth, - logger, - defaultBranch = 'master', - commitMessage = 'Initial commit', - gitAuthorInfo, -}: { +export async function initRepoAndPush(input: { dir: string; remoteUrl: string; // For use cases where token has to be used with Basic Auth @@ -40,6 +32,15 @@ export async function initRepoAndPush({ commitMessage?: string; gitAuthorInfo?: { name?: string; email?: string }; }): Promise<{ commitHash: string }> { + const { + dir, + remoteUrl, + auth, + logger, + defaultBranch = 'master', + commitMessage = 'Initial commit', + gitAuthorInfo, + } = input; const git = Git.fromAuth({ ...auth, logger, @@ -81,15 +82,7 @@ export async function initRepoAndPush({ /** * @public */ -export async function commitAndPushRepo({ - dir, - auth, - logger, - commitMessage, - gitAuthorInfo, - branch = 'master', - remoteRef, -}: { +export async function commitAndPushRepo(input: { dir: string; // For use cases where token has to be used with Basic Auth // it has to be provided as password together with a username @@ -101,6 +94,16 @@ export async function commitAndPushRepo({ branch?: string; remoteRef?: string; }): Promise<{ commitHash: string }> { + const { + dir, + auth, + logger, + commitMessage, + gitAuthorInfo, + branch = 'master', + remoteRef, + } = input; + const git = Git.fromAuth({ ...auth, logger, diff --git a/yarn.lock b/yarn.lock index f302329de7..c370053903 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8741,7 +8741,7 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" "@gitbeaker/core": ^35.8.0 - "@gitbeaker/node": ^35.1.0 + "@gitbeaker/node": ^35.8.0 yaml: ^2.0.0 zod: ^3.21.4 languageName: unknown @@ -11631,7 +11631,7 @@ __metadata: languageName: node linkType: hard -"@gitbeaker/node@npm:^35.1.0": +"@gitbeaker/node@npm:^35.1.0, @gitbeaker/node@npm:^35.8.0": version: 35.8.1 resolution: "@gitbeaker/node@npm:35.8.1" dependencies: From 66a38b2d59147818da308535568936c2ba26e689 Mon Sep 17 00:00:00 2001 From: blam Date: Sat, 9 Dec 2023 10:46:09 +0100 Subject: [PATCH 15/15] chore: fix api-reports Signed-off-by: blam --- plugins/scaffolder-node/api-report.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/plugins/scaffolder-node/api-report.md b/plugins/scaffolder-node/api-report.md index ca1b9e8b4e..6bb1534679 100644 --- a/plugins/scaffolder-node/api-report.md +++ b/plugins/scaffolder-node/api-report.md @@ -46,15 +46,7 @@ export type ActionContext< }; // @public (undocumented) -export function commitAndPushRepo({ - dir, - auth, - logger, - commitMessage, - gitAuthorInfo, - branch, - remoteRef, -}: { +export function commitAndPushRepo(input: { dir: string; auth: | { @@ -149,15 +141,7 @@ export const getRepoSourceDirectory: ( ) => string; // @public (undocumented) -export function initRepoAndPush({ - dir, - remoteUrl, - auth, - logger, - defaultBranch, - commitMessage, - gitAuthorInfo, -}: { +export function initRepoAndPush(input: { dir: string; remoteUrl: string; auth: