Merge pull request #21895 from jayfray12/master
Enhance bitbucket pull request action to add new content
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-node': minor
|
||||
---
|
||||
|
||||
Added functions to clone a repo, create a branch, add files and push and commit to the branch. This allows for files to be added to the a PR for use in the bitbucket pull request action for issue #21762
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
|
||||
---
|
||||
|
||||
Enhanced the pull request action to allow for adding new content to the PR as described in this issue #21762
|
||||
@@ -28,6 +28,7 @@
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/integration": "workspace:^",
|
||||
"@backstage/plugin-scaffolder-node": "workspace:^",
|
||||
"fs-extra": "10.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
|
||||
+129
-2
@@ -21,10 +21,16 @@ import {
|
||||
} from '@backstage/integration';
|
||||
import {
|
||||
createTemplateAction,
|
||||
getRepoSourceDirectory,
|
||||
commitAndPushBranch,
|
||||
addFiles,
|
||||
createBranch as createGitBranch,
|
||||
cloneRepo,
|
||||
parseRepoUrl,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import fetch, { RequestInit, Response } from 'node-fetch';
|
||||
import { Config } from '@backstage/config';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
const createPullRequest = async (opts: {
|
||||
project: string;
|
||||
@@ -152,7 +158,51 @@ const findBranches = async (opts: {
|
||||
|
||||
return undefined;
|
||||
};
|
||||
const createBranch = async (opts: {
|
||||
project: string;
|
||||
repo: string;
|
||||
branchName: string;
|
||||
authorization: string;
|
||||
apiBaseUrl: string;
|
||||
startPoint: string;
|
||||
}) => {
|
||||
const { project, repo, branchName, authorization, apiBaseUrl, startPoint } =
|
||||
opts;
|
||||
|
||||
let response: Response;
|
||||
const options: RequestInit = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
name: branchName,
|
||||
startPoint,
|
||||
}),
|
||||
headers: {
|
||||
Authorization: authorization,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
response = await fetch(
|
||||
`${apiBaseUrl}/projects/${encodeURIComponent(
|
||||
project,
|
||||
)}/repos/${encodeURIComponent(repo)}/branches`,
|
||||
options,
|
||||
);
|
||||
} catch (e) {
|
||||
throw new Error(`Unable to create branch, ${e}`);
|
||||
}
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(
|
||||
`Unable to create branch, ${response.status} ${
|
||||
response.statusText
|
||||
}, ${await response.text()}`,
|
||||
);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
/**
|
||||
* Creates a BitbucketServer Pull Request action.
|
||||
* @public
|
||||
@@ -161,7 +211,7 @@ export function createPublishBitbucketServerPullRequestAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}) {
|
||||
const { integrations } = options;
|
||||
const { integrations, config } = options;
|
||||
|
||||
return createTemplateAction<{
|
||||
repoUrl: string;
|
||||
@@ -268,7 +318,7 @@ export function createPublishBitbucketServerPullRequestAction(options: {
|
||||
apiBaseUrl,
|
||||
});
|
||||
|
||||
const fromRef = await findBranches({
|
||||
let fromRef = await findBranches({
|
||||
project,
|
||||
repo,
|
||||
branchName: sourceBranch,
|
||||
@@ -276,6 +326,83 @@ export function createPublishBitbucketServerPullRequestAction(options: {
|
||||
apiBaseUrl,
|
||||
});
|
||||
|
||||
if (!fromRef) {
|
||||
// create branch
|
||||
ctx.logger.info(
|
||||
`source branch not found -> creating branch named: ${sourceBranch} lastCommit: ${toRef.latestCommit}`,
|
||||
);
|
||||
const latestCommit = toRef.latestCommit;
|
||||
|
||||
fromRef = await createBranch({
|
||||
project,
|
||||
repo,
|
||||
branchName: sourceBranch,
|
||||
authorization,
|
||||
apiBaseUrl,
|
||||
startPoint: latestCommit,
|
||||
});
|
||||
|
||||
const remoteUrl = `https://${host}/scm/${project}/${repo}.git`;
|
||||
|
||||
const auth = authConfig.token
|
||||
? {
|
||||
token: token!,
|
||||
}
|
||||
: {
|
||||
username: authConfig.username!,
|
||||
password: authConfig.password!,
|
||||
};
|
||||
|
||||
const gitAuthorInfo = {
|
||||
name: config.getOptionalString('scaffolder.defaultAuthor.name'),
|
||||
email: config.getOptionalString('scaffolder.defaultAuthor.email'),
|
||||
};
|
||||
|
||||
const tempDir = await ctx.createTemporaryDirectory();
|
||||
const sourceDir = getRepoSourceDirectory(ctx.workspacePath, undefined);
|
||||
await cloneRepo({
|
||||
url: remoteUrl,
|
||||
dir: tempDir,
|
||||
auth,
|
||||
logger: ctx.logger,
|
||||
ref: sourceBranch,
|
||||
});
|
||||
|
||||
await createGitBranch({
|
||||
dir: tempDir,
|
||||
auth,
|
||||
logger: ctx.logger,
|
||||
ref: sourceBranch,
|
||||
});
|
||||
|
||||
// copy files
|
||||
fs.cpSync(sourceDir, tempDir, {
|
||||
recursive: true,
|
||||
filter: path => {
|
||||
return !(path.indexOf('.git') > -1);
|
||||
},
|
||||
});
|
||||
|
||||
await addFiles({
|
||||
dir: tempDir,
|
||||
auth,
|
||||
logger: ctx.logger,
|
||||
filepath: '.',
|
||||
});
|
||||
|
||||
await commitAndPushBranch({
|
||||
dir: tempDir,
|
||||
auth,
|
||||
logger: ctx.logger,
|
||||
commitMessage:
|
||||
description ??
|
||||
config.getOptionalString('scaffolder.defaultCommitMessage') ??
|
||||
'',
|
||||
gitAuthorInfo,
|
||||
branch: sourceBranch,
|
||||
});
|
||||
}
|
||||
|
||||
const pullRequestUrl = await createPullRequest({
|
||||
project,
|
||||
repo,
|
||||
|
||||
@@ -45,6 +45,63 @@ export type ActionContext<
|
||||
each?: JsonObject;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export function addFiles(options: {
|
||||
dir: string;
|
||||
filepath: string;
|
||||
auth:
|
||||
| {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
| {
|
||||
token: string;
|
||||
};
|
||||
logger?: Logger | undefined;
|
||||
}): Promise<void>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function cloneRepo(options: {
|
||||
url: string;
|
||||
dir: string;
|
||||
auth:
|
||||
| {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
| {
|
||||
token: string;
|
||||
};
|
||||
logger?: Logger | undefined;
|
||||
ref?: string | undefined;
|
||||
depth?: number | undefined;
|
||||
noCheckout?: boolean | undefined;
|
||||
}): Promise<void>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function commitAndPushBranch(options: {
|
||||
dir: string;
|
||||
auth:
|
||||
| {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
| {
|
||||
token: string;
|
||||
};
|
||||
logger?: Logger | undefined;
|
||||
commitMessage: string;
|
||||
gitAuthorInfo?: {
|
||||
name?: string;
|
||||
email?: string;
|
||||
};
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
remote?: string;
|
||||
}): Promise<{
|
||||
commitHash: string;
|
||||
}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function commitAndPushRepo(input: {
|
||||
dir: string;
|
||||
@@ -68,6 +125,21 @@ export function commitAndPushRepo(input: {
|
||||
commitHash: string;
|
||||
}>;
|
||||
|
||||
// @public (undocumented)
|
||||
export function createBranch(options: {
|
||||
dir: string;
|
||||
ref: string;
|
||||
auth:
|
||||
| {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
| {
|
||||
token: string;
|
||||
};
|
||||
logger?: Logger | undefined;
|
||||
}): Promise<void>;
|
||||
|
||||
// @public
|
||||
export const createTemplateAction: <
|
||||
TInputParams extends JsonObject = JsonObject,
|
||||
|
||||
@@ -15,7 +15,14 @@
|
||||
*/
|
||||
|
||||
import { Git, getVoidLogger } from '@backstage/backend-common';
|
||||
import { commitAndPushRepo, initRepoAndPush } from './gitHelpers';
|
||||
import {
|
||||
commitAndPushRepo,
|
||||
initRepoAndPush,
|
||||
commitAndPushBranch,
|
||||
addFiles,
|
||||
createBranch,
|
||||
cloneRepo,
|
||||
} from './gitHelpers';
|
||||
|
||||
jest.mock('@backstage/backend-common', () => ({
|
||||
Git: {
|
||||
@@ -29,10 +36,14 @@ jest.mock('@backstage/backend-common', () => ({
|
||||
fetch: jest.fn(),
|
||||
addRemote: jest.fn(),
|
||||
push: jest.fn(),
|
||||
clone: jest.fn(),
|
||||
}),
|
||||
},
|
||||
getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger,
|
||||
}));
|
||||
jest.mock('fs-extra', () => ({
|
||||
cpSync: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockedGit = Git.fromAuth({
|
||||
logger: getVoidLogger(),
|
||||
@@ -303,3 +314,333 @@ describe('commitAndPushRepo', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('cloneRepo', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('with minimal parameters', () => {
|
||||
beforeEach(async () => {
|
||||
await cloneRepo({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('clone the repo', () => {
|
||||
expect(mockedGit.clone).toHaveBeenCalledWith({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: undefined,
|
||||
depth: undefined,
|
||||
noCheckout: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('with token', async () => {
|
||||
await cloneRepo({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
token: 'test-token',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.clone).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
url: 'git@github.com:test/repo.git',
|
||||
ref: undefined,
|
||||
depth: undefined,
|
||||
noCheckout: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('allows overriding the default branch', async () => {
|
||||
await cloneRepo({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: 'trunk',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.clone).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
url: 'git@github.com:test/repo.git',
|
||||
ref: 'trunk',
|
||||
depth: undefined,
|
||||
noCheckout: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('allows overriding the depth', async () => {
|
||||
await cloneRepo({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: 'trunk',
|
||||
depth: 2,
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.clone).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
url: 'git@github.com:test/repo.git',
|
||||
ref: 'trunk',
|
||||
depth: 2,
|
||||
noCheckout: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('allows overriding the noCheckout', async () => {
|
||||
await cloneRepo({
|
||||
url: 'git@github.com:test/repo.git',
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: 'trunk',
|
||||
depth: 2,
|
||||
noCheckout: true,
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.clone).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
url: 'git@github.com:test/repo.git',
|
||||
ref: 'trunk',
|
||||
depth: 2,
|
||||
noCheckout: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createBranch', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('with minimal parameters', () => {
|
||||
beforeEach(async () => {
|
||||
await createBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: 'trunk',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('create the branch', () => {
|
||||
expect(mockedGit.checkout).toHaveBeenCalledWith({
|
||||
ref: 'trunk',
|
||||
dir: '/tmp/repo/dir/',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('with token', async () => {
|
||||
await createBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
ref: 'trunk',
|
||||
auth: {
|
||||
token: 'test-token',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.checkout).toHaveBeenCalledWith({
|
||||
ref: 'trunk',
|
||||
dir: '/tmp/repo/dir/',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addFiles', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('with minimal parameters', () => {
|
||||
beforeEach(async () => {
|
||||
await addFiles({
|
||||
dir: '/tmp/repo/dir/',
|
||||
filepath: '.',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('add files', () => {
|
||||
expect(mockedGit.add).toHaveBeenCalledWith({
|
||||
filepath: '.',
|
||||
dir: '/tmp/repo/dir/',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('with token', async () => {
|
||||
await addFiles({
|
||||
dir: '/tmp/repo/dir/',
|
||||
filepath: '.',
|
||||
auth: {
|
||||
token: 'test-token',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.add).toHaveBeenCalledWith({
|
||||
filepath: '.',
|
||||
dir: '/tmp/repo/dir/',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('commitAndPushBranch', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('with minimal parameters', () => {
|
||||
beforeEach(async () => {
|
||||
await commitAndPushBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
commitMessage: 'commit message',
|
||||
});
|
||||
});
|
||||
|
||||
it('create commit', () => {
|
||||
expect(mockedGit.commit).toHaveBeenCalledWith({
|
||||
message: 'commit message',
|
||||
dir: '/tmp/repo/dir/',
|
||||
author: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
committer: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('pushes to the remote', () => {
|
||||
expect(mockedGit.push).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
remote: 'origin',
|
||||
remoteRef: 'refs/heads/master',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('with token', async () => {
|
||||
await commitAndPushBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
token: 'test-token',
|
||||
},
|
||||
commitMessage: 'commit message',
|
||||
gitAuthorInfo: {
|
||||
name: 'gitCommitter',
|
||||
email: 'gitCommitter@backstage.io',
|
||||
},
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
expect(mockedGit.commit).toHaveBeenCalledWith({
|
||||
message: 'commit message',
|
||||
dir: '/tmp/repo/dir/',
|
||||
author: {
|
||||
name: 'gitCommitter',
|
||||
email: 'gitCommitter@backstage.io',
|
||||
},
|
||||
committer: {
|
||||
name: 'gitCommitter',
|
||||
email: 'gitCommitter@backstage.io',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.push).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
remote: 'origin',
|
||||
remoteRef: 'refs/heads/master',
|
||||
});
|
||||
});
|
||||
|
||||
it('allows overriding the default branch', async () => {
|
||||
await commitAndPushBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
commitMessage: 'commit message',
|
||||
branch: 'trunk',
|
||||
});
|
||||
|
||||
expect(mockedGit.commit).toHaveBeenCalledWith({
|
||||
message: 'commit message',
|
||||
dir: '/tmp/repo/dir/',
|
||||
author: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
committer: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.push).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
remote: 'origin',
|
||||
remoteRef: 'refs/heads/trunk',
|
||||
});
|
||||
});
|
||||
|
||||
it('allows overriding the remoteRef', async () => {
|
||||
await commitAndPushBranch({
|
||||
dir: '/tmp/repo/dir/',
|
||||
auth: {
|
||||
username: 'test-user',
|
||||
password: 'test-password',
|
||||
},
|
||||
commitMessage: 'commit message',
|
||||
remoteRef: 'ABC123',
|
||||
});
|
||||
|
||||
expect(mockedGit.commit).toHaveBeenCalledWith({
|
||||
message: 'commit message',
|
||||
dir: '/tmp/repo/dir/',
|
||||
author: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
committer: {
|
||||
name: 'Scaffolder',
|
||||
email: 'scaffolder@backstage.io',
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockedGit.push).toHaveBeenCalledWith({
|
||||
dir: '/tmp/repo/dir/',
|
||||
remote: 'origin',
|
||||
remoteRef: 'ABC123',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,3 +134,123 @@ export async function commitAndPushRepo(input: {
|
||||
|
||||
return { commitHash };
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function cloneRepo(options: {
|
||||
url: string;
|
||||
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 | undefined;
|
||||
ref?: string | undefined;
|
||||
depth?: number | undefined;
|
||||
noCheckout?: boolean | undefined;
|
||||
}): Promise<void> {
|
||||
const { url, dir, auth, logger, ref, depth, noCheckout } = options;
|
||||
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
logger,
|
||||
});
|
||||
|
||||
await git.clone({ url, dir, ref, depth, noCheckout });
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function createBranch(options: {
|
||||
dir: string;
|
||||
ref: 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 | undefined;
|
||||
}): Promise<void> {
|
||||
const { dir, ref, auth, logger } = options;
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
logger,
|
||||
});
|
||||
|
||||
await git.checkout({ dir, ref });
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function addFiles(options: {
|
||||
dir: string;
|
||||
filepath: 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 | undefined;
|
||||
}): Promise<void> {
|
||||
const { dir, filepath, auth, logger } = options;
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
logger,
|
||||
});
|
||||
|
||||
await git.add({ dir, filepath });
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function commitAndPushBranch(options: {
|
||||
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 | undefined;
|
||||
commitMessage: string;
|
||||
gitAuthorInfo?: { name?: string; email?: string };
|
||||
branch?: string;
|
||||
remoteRef?: string;
|
||||
remote?: string;
|
||||
}): Promise<{ commitHash: string }> {
|
||||
const {
|
||||
dir,
|
||||
auth,
|
||||
logger,
|
||||
commitMessage,
|
||||
gitAuthorInfo,
|
||||
branch = 'master',
|
||||
remoteRef,
|
||||
remote = 'origin',
|
||||
} = options;
|
||||
const git = Git.fromAuth({
|
||||
...auth,
|
||||
logger,
|
||||
});
|
||||
|
||||
// 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,
|
||||
remoteRef: remoteRef ?? `refs/heads/${branch}`,
|
||||
});
|
||||
|
||||
return { commitHash };
|
||||
}
|
||||
|
||||
@@ -25,5 +25,12 @@ export {
|
||||
} from './executeShellCommand';
|
||||
export { fetchContents, fetchFile } from './fetch';
|
||||
export { type ActionContext, type TemplateAction } from './types';
|
||||
export { initRepoAndPush, commitAndPushRepo } from './gitHelpers';
|
||||
export {
|
||||
initRepoAndPush,
|
||||
commitAndPushRepo,
|
||||
commitAndPushBranch,
|
||||
addFiles,
|
||||
createBranch,
|
||||
cloneRepo,
|
||||
} from './gitHelpers';
|
||||
export { parseRepoUrl, getRepoSourceDirectory } from './util';
|
||||
|
||||
Reference in New Issue
Block a user