Add auto commitAction to pushRepo action
Signed-off-by: Joao Pedro Goulart <joaopedromgoulart@gmail.com> Signed-off-by: bi003731 <bi003731@inter.co>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': minor
|
||||
---
|
||||
|
||||
In the gitlabRepoPush action, add 'auto' possibility for commitAction input.
|
||||
@@ -31,57 +31,11 @@ import {
|
||||
import path from 'path';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import {
|
||||
LoggerService,
|
||||
resolveSafeChildPath,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import { createGitlabApi, getErrorMessage } from './helpers';
|
||||
import { examples } from './gitlabMergeRequest.examples';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
function computeSha256(file: SerializedFile): string {
|
||||
const hash = createHash('sha256');
|
||||
hash.update(file.content);
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
async function getFileAction(
|
||||
fileInfo: { file: SerializedFile; targetPath?: string },
|
||||
target: { repoID: string; branch: string },
|
||||
api: InstanceType<typeof Gitlab>,
|
||||
logger: LoggerService,
|
||||
remoteFiles: RepositoryTreeSchema[],
|
||||
defaultCommitAction:
|
||||
| 'create'
|
||||
| 'delete'
|
||||
| 'update'
|
||||
| 'skip'
|
||||
| 'auto' = 'auto',
|
||||
): Promise<'create' | 'delete' | 'update' | 'skip'> {
|
||||
if (defaultCommitAction === 'auto') {
|
||||
const filePath = path.join(fileInfo.targetPath ?? '', fileInfo.file.path);
|
||||
|
||||
if (remoteFiles?.some(remoteFile => remoteFile.path === filePath)) {
|
||||
try {
|
||||
const targetFile = await api.RepositoryFiles.show(
|
||||
target.repoID,
|
||||
filePath,
|
||||
target.branch,
|
||||
);
|
||||
if (computeSha256(fileInfo.file) === targetFile.content_sha256) {
|
||||
return 'skip';
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Unable to retrieve detailed information for remote file ${filePath}`,
|
||||
);
|
||||
}
|
||||
return 'update';
|
||||
}
|
||||
return 'create';
|
||||
}
|
||||
return defaultCommitAction;
|
||||
}
|
||||
import { getFileAction } from '../util';
|
||||
|
||||
async function getReviewersFromApprovalRules(
|
||||
api: InstanceType<typeof Gitlab>,
|
||||
|
||||
@@ -26,6 +26,9 @@ import {
|
||||
import { CommitAction } from '@gitbeaker/rest';
|
||||
import { createGitlabApi, getErrorMessage } from './helpers';
|
||||
import { examples } from './gitlabRepoPush.examples';
|
||||
import { getFileAction } from '../util';
|
||||
import { SerializedFile } from '@backstage/plugin-scaffolder-node';
|
||||
import { RepositoryTreeSchema } from '@gitbeaker/rest';
|
||||
|
||||
/**
|
||||
* Create a new action that commits into a gitlab repository.
|
||||
@@ -75,7 +78,7 @@ export const createGitlabRepoPushAction = (options: {
|
||||
.optional(),
|
||||
commitAction: z =>
|
||||
z
|
||||
.enum(['create', 'update', 'delete'], {
|
||||
.enum(['create', 'update', 'delete', 'auto'], {
|
||||
description:
|
||||
'The action to be used for git commit. Defaults to create, but can be set to update or delete',
|
||||
})
|
||||
@@ -126,8 +129,44 @@ export const createGitlabRepoPushAction = (options: {
|
||||
gitignore: true,
|
||||
});
|
||||
|
||||
const actions: CommitAction[] = fileContents.map(file => ({
|
||||
action: commitAction ?? 'create',
|
||||
let remoteFiles: RepositoryTreeSchema[] = [];
|
||||
if ((ctx.input.commitAction ?? 'auto') === 'auto') {
|
||||
try {
|
||||
remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {
|
||||
ref: branchName,
|
||||
recursive: true,
|
||||
path: targetPath ?? undefined,
|
||||
});
|
||||
} catch (e) {
|
||||
ctx.logger.warn(
|
||||
`Could not retrieve the list of files for ${repoID} (branch: ${branchName}) : ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const actions: CommitAction[] = (
|
||||
(
|
||||
await Promise.all(
|
||||
fileContents.map(async file => {
|
||||
const action = await getFileAction(
|
||||
{ file, targetPath },
|
||||
{ repoID, branch: branchName },
|
||||
api,
|
||||
ctx.logger,
|
||||
remoteFiles,
|
||||
ctx.input.commitAction,
|
||||
);
|
||||
return { file, action };
|
||||
}),
|
||||
)
|
||||
).filter(o => o.action !== 'skip') as {
|
||||
file: SerializedFile;
|
||||
action: CommitAction['action'];
|
||||
}[]
|
||||
).map(({ file, action }) => ({
|
||||
action,
|
||||
filePath: targetPath
|
||||
? path.posix.join(targetPath, file.path)
|
||||
: file.path,
|
||||
|
||||
@@ -14,15 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import {
|
||||
GitLabIntegration,
|
||||
ScmIntegrationRegistry,
|
||||
} from '@backstage/integration';
|
||||
import { Gitlab, GroupSchema } from '@gitbeaker/rest';
|
||||
import { Gitlab, GroupSchema, RepositoryTreeSchema } from '@gitbeaker/rest';
|
||||
import { z } from 'zod';
|
||||
import commonGitlabConfig from './commonGitlabConfig';
|
||||
|
||||
import { SerializedFile } from '@backstage/plugin-scaffolder-node';
|
||||
|
||||
import { createHash } from 'crypto';
|
||||
import path from 'path';
|
||||
|
||||
export const parseRepoHost = (repoUrl: string): string => {
|
||||
let parsed;
|
||||
try {
|
||||
@@ -184,3 +190,47 @@ export async function checkEpicScope(
|
||||
throw new InputError(`Could not find epic scope: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function computeSha256(file: SerializedFile): string {
|
||||
const hash = createHash('sha256');
|
||||
hash.update(file.content);
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
export async function getFileAction(
|
||||
fileInfo: { file: SerializedFile; targetPath?: string },
|
||||
target: { repoID: string; branch: string },
|
||||
api: InstanceType<typeof Gitlab>,
|
||||
logger: LoggerService,
|
||||
remoteFiles: RepositoryTreeSchema[],
|
||||
defaultCommitAction:
|
||||
| 'create'
|
||||
| 'delete'
|
||||
| 'update'
|
||||
| 'skip'
|
||||
| 'auto' = 'auto',
|
||||
): Promise<'create' | 'delete' | 'update' | 'skip'> {
|
||||
if (defaultCommitAction === 'auto') {
|
||||
const filePath = path.join(fileInfo.targetPath ?? '', fileInfo.file.path);
|
||||
|
||||
if (remoteFiles?.some(remoteFile => remoteFile.path === filePath)) {
|
||||
try {
|
||||
const targetFile = await api.RepositoryFiles.show(
|
||||
target.repoID,
|
||||
filePath,
|
||||
target.branch,
|
||||
);
|
||||
if (computeSha256(fileInfo.file) === targetFile.content_sha256) {
|
||||
return 'skip';
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
`Unable to retrieve detailed information for remote file ${filePath}`,
|
||||
);
|
||||
}
|
||||
return 'update';
|
||||
}
|
||||
return 'create';
|
||||
}
|
||||
return defaultCommitAction;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user