Merge pull request #17233 from lukasfruntke-extern/feature/add-commit-hash-for-scaffolder

Add Commit Hash Output for Scaffolder SCM Actions
This commit is contained in:
Ben Lambert
2023-04-17 21:15:11 +02:00
committed by GitHub
26 changed files with 174 additions and 32 deletions
+1 -1
View File
@@ -78,7 +78,7 @@
"git-url-parse": "^13.0.0",
"globby": "^11.0.0",
"isbinaryfile": "^5.0.0",
"isomorphic-git": "^1.8.0",
"isomorphic-git": "^1.23.0",
"jsonschema": "^1.2.6",
"knex": "^2.0.0",
"lodash": "^4.17.21",
@@ -14,10 +14,30 @@
* limitations under the License.
*/
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
const mockGit = {
init: jest.fn(),
add: jest.fn(),
checkout: jest.fn(),
commit: jest
.fn()
.mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'),
fetch: jest.fn(),
addRemote: jest.fn(),
push: jest.fn(),
};
jest.mock('@backstage/backend-common', () => ({
Git: {
fromAuth() {
return mockGit;
},
},
getVoidLogger: jest.requireActual('@backstage/backend-common').getVoidLogger,
}));
jest.mock('../helpers');
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { getVoidLogger } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import {
@@ -32,6 +52,10 @@ import {
} from '../helpers';
import { createGithubRepoPushAction } from './githubRepoPush';
const initRepoAndPushMocked = initRepoAndPush as jest.Mock<
Promise<{ commitHash: string }>
>;
const mockOctokit = {
rest: {
repos: {
@@ -77,6 +101,9 @@ describe('github:repo:push', () => {
beforeEach(() => {
jest.resetAllMocks();
initRepoAndPushMocked.mockResolvedValue({ commitHash: 'test123' });
githubCredentialsProvider =
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
action = createGithubRepoPushAction({
@@ -107,6 +107,7 @@ export function createGithubRepoPushAction(options: {
properties: {
remoteUrl: outputProps.remoteUrl,
repoContentsUrl: outputProps.repoContentsUrl,
commitHash: outputProps.commitHash,
},
},
},
@@ -151,7 +152,7 @@ export function createGithubRepoPushAction(options: {
const remoteUrl = targetRepo.data.clone_url;
const repoContentsUrl = `${targetRepo.data.html_url}/blob/${defaultBranch}`;
await initRepoPushAndProtect(
const { commitHash } = await initRepoPushAndProtect(
remoteUrl,
octokitOptions.auth,
ctx.workspacePath,
@@ -180,6 +181,7 @@ export function createGithubRepoPushAction(options: {
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
ctx.output('commitHash', commitHash);
},
});
}
@@ -294,7 +294,7 @@ export async function initRepoPushAndProtect(
gitAuthorEmail?: string,
dismissStaleReviews?: boolean,
requiredCommitSigning?: boolean,
) {
): Promise<{ commitHash: string }> {
const gitAuthorInfo = {
name: gitAuthorName
? gitAuthorName
@@ -308,7 +308,7 @@ export async function initRepoPushAndProtect(
? gitCommitMessage
: config.getOptionalString('scaffolder.defaultCommitMessage');
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(workspacePath, sourcePath),
remoteUrl,
defaultBranch,
@@ -347,6 +347,8 @@ export async function initRepoPushAndProtect(
);
}
}
return { commitHash: commitResult.commitHash };
}
function extractCollaboratorName(
@@ -23,5 +23,11 @@ const repoContentsUrl = {
type: 'string',
};
const commitHash = {
title: 'The git commit hash of the initial commit',
type: 'string',
};
export { remoteUrl };
export { repoContentsUrl };
export { commitHash };
@@ -23,7 +23,9 @@ jest.mock('@backstage/backend-common', () => ({
init: jest.fn(),
add: jest.fn(),
checkout: jest.fn(),
commit: jest.fn(),
commit: jest
.fn()
.mockResolvedValue('220f19cc36b551763d157f1b5e4a4b446165dbd6'),
fetch: jest.fn(),
addRemote: jest.fn(),
push: jest.fn(),
@@ -91,7 +91,7 @@ export async function initRepoAndPush({
defaultBranch?: string;
commitMessage?: string;
gitAuthorInfo?: { name?: string; email?: string };
}): Promise<void> {
}): Promise<{ commitHash: string }> {
const git = Git.fromAuth({
...auth,
logger,
@@ -110,13 +110,12 @@ export async function initRepoAndPush({
email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',
};
await git.commit({
const commitHash = await git.commit({
dir,
message: commitMessage,
author: authorInfo,
committer: authorInfo,
});
await git.addRemote({
dir,
url: remoteUrl,
@@ -127,6 +126,8 @@ export async function initRepoAndPush({
dir,
remote: 'origin',
});
return { commitHash };
}
export async function commitAndPushRepo({
@@ -148,7 +149,7 @@ export async function commitAndPushRepo({
gitAuthorInfo?: { name?: string; email?: string };
branch?: string;
remoteRef?: string;
}): Promise<void> {
}): Promise<{ commitHash: string }> {
const git = Git.fromAuth({
...auth,
logger,
@@ -164,7 +165,7 @@ export async function commitAndPushRepo({
email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',
};
await git.commit({
const commitHash = await git.commit({
dir,
message: commitMessage,
author: authorInfo,
@@ -176,6 +177,8 @@ export async function commitAndPushRepo({
remote: 'origin',
remoteRef: remoteRef ?? `refs/heads/${branch}`,
});
return { commitHash };
}
type BranchProtectionOptions = {
@@ -19,7 +19,16 @@ jest.mock('azure-devops-node-api', () => ({
getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}),
}));
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishAzureAction } from './azure';
import { ScmIntegrations } from '@backstage/integration';
@@ -108,6 +108,10 @@ export function createPublishAzureAction(options: {
title: 'The Id of the created repository',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -183,7 +187,7 @@ export function createPublishAzureAction(options: {
: config.getOptionalString('scaffolder.defaultAuthor.email'),
};
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
remoteUrl,
defaultBranch,
@@ -198,6 +202,7 @@ export function createPublishAzureAction(options: {
gitAuthorInfo,
});
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
ctx.output('repositoryId', repositoryId);
@@ -14,7 +14,16 @@
* limitations under the License.
*/
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishBitbucketAction } from './bitbucket';
import { rest } from 'msw';
@@ -289,6 +289,10 @@ export function createPublishBitbucketAction(options: {
title: 'A URL to the root of the repository',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -391,7 +395,7 @@ export function createPublishBitbucketAction(options: {
};
}
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
remoteUrl,
auth,
@@ -407,6 +411,7 @@ export function createPublishBitbucketAction(options: {
await performEnableLFS({ authorization, host, project, repo });
}
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
},
@@ -14,7 +14,16 @@
* limitations under the License.
*/
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishBitbucketCloudAction } from './bitbucketCloud';
import { rest } from 'msw';
@@ -182,6 +182,10 @@ export function createPublishBitbucketCloudAction(options: {
title: 'A URL to the root of the repository',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -262,7 +266,7 @@ export function createPublishBitbucketCloudAction(options: {
};
}
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
remoteUrl,
auth,
@@ -274,6 +278,7 @@ export function createPublishBitbucketCloudAction(options: {
gitAuthorInfo,
});
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
},
@@ -14,7 +14,16 @@
* limitations under the License.
*/
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishBitbucketServerAction } from './bitbucketServer';
import { rest } from 'msw';
@@ -205,6 +205,10 @@ export function createPublishBitbucketServerAction(options: {
title: 'A URL to the root of the repository',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -279,7 +283,7 @@ export function createPublishBitbucketServerAction(options: {
password: authConfig.password!,
};
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
remoteUrl,
auth,
@@ -295,6 +299,7 @@ export function createPublishBitbucketServerAction(options: {
await performEnableLFS({ authorization, host, project, repo });
}
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
},
@@ -14,7 +14,16 @@
* limitations under the License.
*/
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import path from 'path';
import { createPublishGerritAction } from './gerrit';
@@ -149,6 +149,10 @@ export function createPublishGerritAction(options: {
title: 'A URL to the root of the repository',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -201,7 +205,7 @@ export function createPublishGerritAction(options: {
};
const remoteUrl = `${integrationConfig.config.cloneUrl}/a/${repo}`;
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, sourcePath),
remoteUrl,
auth,
@@ -213,6 +217,7 @@ export function createPublishGerritAction(options: {
const repoContentsUrl = `${integrationConfig.config.gitilesBaseUrl}/${repo}/+/refs/heads/${defaultBranch}`;
ctx.output('remoteUrl', remoteUrl);
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('repoContentsUrl', repoContentsUrl);
},
});
@@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
jest.mock('../helpers');
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
import { getVoidLogger } from '@backstage/backend-common';
import { ConfigReader } from '@backstage/config';
import {
@@ -34,6 +32,10 @@ import {
} from '../helpers';
import { createPublishGithubAction } from './github';
const initRepoAndPushMocked = initRepoAndPush as jest.Mock<
Promise<{ commitHash: string }>
>;
const mockOctokit = {
rest: {
users: {
@@ -90,6 +92,9 @@ describe('publish:github', () => {
};
beforeEach(() => {
initRepoAndPushMocked.mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
});
githubCredentialsProvider =
DefaultGithubCredentialsProvider.fromIntegrations(integrations);
action = createPublishGithubAction({
@@ -156,6 +156,7 @@ export function createPublishGithubAction(options: {
properties: {
remoteUrl: outputProps.remoteUrl,
repoContentsUrl: outputProps.repoContentsUrl,
commitHash: outputProps.commitHash,
},
},
},
@@ -236,7 +237,7 @@ export function createPublishGithubAction(options: {
const remoteUrl = newRepo.clone_url;
const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`;
await initRepoPushAndProtect(
const commitResult = await initRepoPushAndProtect(
remoteUrl,
octokitOptions.auth,
ctx.workspacePath,
@@ -263,6 +264,7 @@ export function createPublishGithubAction(options: {
requiredCommitSigning,
);
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
},
@@ -14,7 +14,16 @@
* limitations under the License.
*/
jest.mock('../helpers');
jest.mock('../helpers', () => {
return {
initRepoAndPush: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
commitAndPushRepo: jest.fn().mockResolvedValue({
commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6',
}),
};
});
import { createPublishGitlabAction } from './gitlab';
import { ScmIntegrations } from '@backstage/integration';
@@ -125,6 +125,10 @@ export function createPublishGitlabAction(options: {
title: 'The ID of the project',
type: 'string',
},
commitHash: {
title: 'The git commit hash of the initial commit',
type: 'string',
},
},
},
},
@@ -212,7 +216,7 @@ export function createPublishGitlabAction(options: {
? gitAuthorEmail
: config.getOptionalString('scaffolder.defaultAuthor.email'),
};
await initRepoAndPush({
const commitResult = await initRepoAndPush({
dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath),
remoteUrl: http_url_to_repo as string,
defaultBranch,
@@ -227,6 +231,7 @@ export function createPublishGitlabAction(options: {
gitAuthorInfo,
});
ctx.output('commitHash', commitResult?.commitHash);
ctx.output('remoteUrl', remoteUrl);
ctx.output('repoContentsUrl', repoContentsUrl);
ctx.output('projectId', projectId);