Skip to content

Commit

Permalink
Merge branch 'main' into output-pr-id
Browse files Browse the repository at this point in the history
  • Loading branch information
jackmtpt authored Jan 25, 2024
2 parents 55cd61f + d626cc7 commit c2118d8
Show file tree
Hide file tree
Showing 7 changed files with 19,796 additions and 13,495 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,18 @@
},
"homepage": "https://github.com/Parfuemerie-Douglas/scaffolder-backend-module-azure-repositories#readme",
"dependencies": {
"@backstage/backend-common": "^0.18.5",
"@backstage/config": "^1.0.7",
"@backstage/errors": "^1.1.5",
"@backstage/integration": "^1.4.5",
"@backstage/plugin-scaffolder-backend": "^1.13.1",
"@backstage/plugin-scaffolder-node": "^0.1.1",
"@backstage/types": "^1.0.2",
"@backstage/backend-common": "^0.20.0",
"@backstage/config": "^1.1.1",
"@backstage/errors": "^1.2.3",
"@backstage/integration": "^1.8.0",
"@backstage/plugin-scaffolder-backend": "^1.19.2",
"@backstage/plugin-scaffolder-node": "^0.2.9",
"@backstage/types": "^1.1.1",
"azure-devops-node-api": "^12.1.0",
"winston": "^3.2.1"
},
"devDependencies": {
"@backstage/cli": "^0.20.0-next.0"
"@backstage/cli": "^0.25.1"
},
"files": [
"dist"
Expand Down
59 changes: 44 additions & 15 deletions src/actions/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { Logger } from "winston";
import * as azdev from "azure-devops-node-api";
import * as GitApi from "azure-devops-node-api/GitApi";
import * as GitInterfaces from "azure-devops-node-api/interfaces/GitInterfaces";
import { AzureDevOpsCredentialsProvider } from "@backstage/integration";
import { InputError } from "@backstage/errors";

export async function cloneRepo({
dir,
Expand Down Expand Up @@ -58,15 +60,15 @@ export async function cloneRepo({

export async function commitAndPushBranch({
dir,
auth,
credentialsProvider,
logger,
remote = "origin",
remote = 'origin',
commitMessage,
gitAuthorInfo,
branch = "scaffolder",
branch = 'scaffolder',
}: {
dir: string;
auth: { username: string; password: string } | { token: string };
credentialsProvider: AzureDevOpsCredentialsProvider;
logger: Logger;
remote?: string;
commitMessage: string;
Expand All @@ -79,18 +81,45 @@ export async function commitAndPushBranch({
};

const git = Git.fromAuth({
...auth,
onAuth: async url => {
const credentials = await credentialsProvider.getCredentials({ url });

logger.info(`Using ${credentials?.type} credentials for ${url}`);

if (credentials?.type === 'pat') {
return { username: "not-empty", password: credentials.token };
} else if (credentials?.type === 'bearer') {
return {
headers: {
Authorization: `Bearer ${credentials.token}`,
},
};
}

throw new InputError(`No token credentials provided for ${url}`);
},
logger,
});

const currentBranch = await git.currentBranch({dir})
const currentBranch = await git.currentBranch({ dir });

logger.info(`Current branch is ${currentBranch}`);
logger.info(`Target branch is ${branch}`);

if (currentBranch !== branch) {
await git.branch({
dir,
ref: branch,
})

try {
await git.branch({
dir,
ref: branch,
});
} catch (err: unknown) {
if (err instanceof Error && err.name === "AlreadyExistsError") {
// we safely ignore this error
} else {
throw err;
}
}

await git.checkout({
dir,
ref: branch,
Expand All @@ -110,9 +139,9 @@ export async function commitAndPushBranch({
});

await git.push({
dir,
remote: remote,
remoteRef: `refs/heads/${branch}`,
dir,
remote: remote,
remoteRef: `refs/heads/${branch}`,
});
}

Expand All @@ -135,7 +164,7 @@ export async function createADOPullRequest({
const orgUrl = url + auth.org;
const token: string = auth.token || ""; // process.env.AZURE_TOKEN || "";

const authHandler = azdev.getPersonalAccessTokenHandler(token);
const authHandler = azdev.getHandlerFromToken(token);
const connection = new azdev.WebApi(orgUrl, authHandler);

const gitApiObject: GitApi.IGitApi = await connection.getGitApi();
Expand Down
2 changes: 1 addition & 1 deletion src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
* limitations under the License.
*/

export * from "./run";
export * from './run';
28 changes: 15 additions & 13 deletions src/actions/run/cloneAzureRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import { resolveSafeChildPath } from "@backstage/backend-common";
import { InputError } from "@backstage/errors";
import { ScmIntegrationRegistry } from "@backstage/integration";
import { DefaultAzureDevOpsCredentialsProvider, ScmIntegrationRegistry } from "@backstage/integration";
import { createTemplateAction } from "@backstage/plugin-scaffolder-backend";

import { cloneRepo } from "../helpers";
Expand Down Expand Up @@ -70,29 +70,31 @@ export const cloneAzureRepoAction = (options: {
},
},
async handler(ctx) {
const { remoteUrl, branch, server } = ctx.input;
const { remoteUrl, branch } = ctx.input;

const targetPath = ctx.input.targetPath ?? "./";
const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);

const host = server ?? "dev.azure.com";
const integrationConfig = integrations.azure.byHost(host);
const provider =
DefaultAzureDevOpsCredentialsProvider.fromIntegrations(integrations);
const credentials = await provider.getCredentials({ url: remoteUrl });

if (!integrationConfig) {
let auth: { username: string; password: string } | { token: string };
if (ctx.input.token) {
auth = { username: "not-empty", password: ctx.input.token };
} else if (credentials?.type === "pat") {
auth = { username: "not-empty", password: credentials.token };
} else if (credentials?.type === "bearer") {
auth = { token: credentials.token };
} else {
throw new InputError(
`No matching integration configuration for host ${host}, please check your integrations config`
`No token credentials provided for Azure repository ${remoteUrl}`,
);
}

if (!integrationConfig.config.token && !ctx.input.token) {
throw new InputError(`No token provided for Azure Integration ${host}`);
}

const token = ctx.input.token ?? integrationConfig.config.token!;

await cloneRepo({
dir: outputDir,
auth: { username: "notempty", password: token },
auth: auth,
logger: ctx.logger,
remoteUrl: remoteUrl,
branch: branch,
Expand Down
30 changes: 15 additions & 15 deletions src/actions/run/pullRequestAzureRepo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ScmIntegrationRegistry} from "@backstage/integration";
import {DefaultAzureDevOpsCredentialsProvider, ScmIntegrationRegistry} from "@backstage/integration";
import { createTemplateAction } from "@backstage/plugin-scaffolder-backend";
import {InputError} from "@backstage/errors";
import { createADOPullRequest} from "../helpers";
Expand Down Expand Up @@ -80,7 +80,7 @@ export const pullRequestAzureRepoAction = (options: {
title: 'Authenticatino Token',
type: 'string',
description: 'The token to use for authorization.',
},
}
}
},
output: {
Expand All @@ -100,16 +100,15 @@ export const pullRequestAzureRepoAction = (options: {
const targetBranch = `refs/heads/${ctx.input.targetBranch}` ?? `refs/heads/main`;

const host = server ?? "dev.azure.com";
const integrationConfig = integrations.azure.byHost(host);
const provider = DefaultAzureDevOpsCredentialsProvider.fromIntegrations(integrations);
const url = `https://${host}/${ctx.input.organization}`;
const credentials = await provider.getCredentials({ url: url });

if (!integrationConfig) {
throw new InputError(
`No matching integration configuration for host ${host}, please check your integrations config`
);
}
const org = ctx.input.organization ?? "not-empty";
const token = ctx.input.token ?? credentials?.token;

if (!integrationConfig.config.token && !ctx.input.token) {
throw new InputError(`No token provided for Azure Integration ${host}`);
if (!token) {
throw new InputError(`No token credentials provided for ${url}`);
}

const pullRequest: GitInterfaces.GitPullRequest = {
Expand All @@ -118,13 +117,14 @@ export const pullRequestAzureRepoAction = (options: {
title: title,
} as GitInterfaces.GitPullRequest;

const org = ctx.input.organization ?? 'notempty';
const token = ctx.input.token ?? integrationConfig.config.token!;

const pullRequestId = await createADOPullRequest({

gitPullRequestToCreate: pullRequest,
server: server,
auth: { org: org, token: token },
server: host,
auth: {
org: org,
token: token,
},
repoId: repoId,
project: project,
supportsIterations: supportsIterations,
Expand Down
34 changes: 4 additions & 30 deletions src/actions/run/pushAzureRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
*/

import { Config } from "@backstage/config";
import { InputError } from "@backstage/errors";
import { ScmIntegrationRegistry } from "@backstage/integration";
import { DefaultAzureDevOpsCredentialsProvider, ScmIntegrationRegistry } from "@backstage/integration";
import { createTemplateAction } from "@backstage/plugin-scaffolder-backend";

import { commitAndPushBranch } from "../helpers";
Expand Down Expand Up @@ -73,43 +72,18 @@ export const pushAzureRepoAction = (options: {
type: "string",
description: "Sets the default author email for the commit.",
},
server: {
type: "string",
title: "Server hostname",
description: "The hostname of the Azure DevOps service. Defaults to dev.azure.com",
},
token: {
title: "Authenticatino Token",
type: "string",
description: "The token to use for authorization.",
},
},
},
},
async handler(ctx) {
const { branch, gitCommitMessage, gitAuthorName, gitAuthorEmail, server } =
const { branch, gitCommitMessage, gitAuthorName, gitAuthorEmail } =
ctx.input;

const sourcePath = getRepoSourceDirectory(
ctx.workspacePath,
ctx.input.sourcePath
ctx.input.sourcePath,
);

const host = server ?? "dev.azure.com";
const integrationConfig = integrations.azure.byHost(host);

if (!integrationConfig) {
throw new InputError(
`No matching integration configuration for host ${host}, please check your integrations config`
);
}

if (!integrationConfig.config.token && !ctx.input.token) {
throw new InputError(`No token provided for Azure Integration ${host}`);
}

const token = ctx.input.token ?? integrationConfig.config.token!;

const gitAuthorInfo = {
name: gitAuthorName
? gitAuthorName
Expand All @@ -121,7 +95,7 @@ export const pushAzureRepoAction = (options: {

await commitAndPushBranch({
dir: sourcePath,
auth: { username: "notempty", password: token },
credentialsProvider: DefaultAzureDevOpsCredentialsProvider.fromIntegrations(integrations),
logger: ctx.logger,
commitMessage: gitCommitMessage
? gitCommitMessage
Expand Down
Loading

0 comments on commit c2118d8

Please sign in to comment.