Rebase on upstream to get context for validator

Signed-off-by: Mustansar Anwar ul Samad <mustansar.samad@gmail.com>
This commit is contained in:
Mustansar Anwar ul Samad
2021-08-09 21:32:33 +12:00
parent 0f101a87d9
commit dc962cab25
9 changed files with 91 additions and 61 deletions
@@ -69,7 +69,13 @@ export function createGithubActionsDispatchAction(options: {
async handler(ctx) {
const { repoUrl, workflowId, branchOrTagName } = ctx.input;
const { owner, repo, host } = parseRepoUrl(repoUrl);
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
if (!owner) {
throw new InputError(
`No owner provided for host: ${host}, and repo ${repo}`,
);
}
ctx.logger.info(
`Dispatching workflow ${workflowId} for repo ${repoUrl} on ${branchOrTagName}`,
@@ -80,7 +80,10 @@ export function createPublishAzureAction(options: {
async handler(ctx) {
const { repoUrl, defaultBranch = 'master' } = ctx.input;
const { owner, repo, host, organization } = parseRepoUrl(repoUrl);
const { owner, repo, host, organization } = parseRepoUrl(
repoUrl,
integrations,
);
if (!organization) {
throw new InputError(
@@ -50,7 +50,7 @@ describe('publish:bitbucket', () => {
const action = createPublishBitbucketAction({ integrations, config });
const mockContext = {
input: {
repoUrl: 'bitbucket.org?type=bitbucket&workspace=workspace&project=project&repo=repo',
repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo',
repoVisibility: 'private',
},
workspacePath: 'lol',
@@ -70,21 +70,21 @@ describe('publish:bitbucket', () => {
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'bitbucket.org?type=bitbucket&project=project&repo=repo' },
input: { repoUrl: 'bitbucket.org?project=project&repo=repo' },
}),
).rejects.toThrow(/missing workspace/);
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'bitbucket.org?type=bitbucket&workspace=workspace&repo=repo' },
input: { repoUrl: 'bitbucket.org?workspace=workspace&repo=repo' },
}),
).rejects.toThrow(/missing project/);
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'bitbucket.org?type=bitbucket&workspace=workspace&project=project' },
input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project' },
}),
).rejects.toThrow(/missing repo/);
});
@@ -93,7 +93,9 @@ describe('publish:bitbucket', () => {
await expect(
action.handler({
...mockContext,
input: { repoUrl: 'missing.com?type=bitbucket&workspace=workspace&project=project&repo=repo' },
input: {
repoUrl: 'missing.com?workspace=workspace&project=project&repo=repo',
},
}),
).rejects.toThrow(/No matching integration configuration/);
});
@@ -103,7 +105,8 @@ describe('publish:bitbucket', () => {
action.handler({
...mockContext,
input: {
repoUrl: 'notoken.bitbucket.com?type=bitbucket&workspace=workspace&project=project&repo=repo',
repoUrl:
'notoken.bitbucket.com?workspace=workspace&project=project&repo=repo',
},
}),
).rejects.toThrow(/Authorization has not been provided for Bitbucket/);
@@ -116,7 +119,11 @@ describe('publish:bitbucket', () => {
'https://api.bitbucket.org/2.0/repositories/workspace/repo',
(req, res, ctx) => {
expect(req.headers.get('Authorization')).toBe('Bearer tokenlols');
expect(req.body).toEqual({ is_private: true, scm: 'git', project: { key: 'project' } });
expect(req.body).toEqual({
is_private: true,
scm: 'git',
project: { key: 'project' },
});
return res(
ctx.status(200),
ctx.set('Content-Type', 'application/json'),
@@ -176,7 +183,7 @@ describe('publish:bitbucket', () => {
...mockContext,
input: {
...mockContext.input,
repoUrl: 'hosted.bitbucket.com?type=bitbucket&project=project&repo=repo',
repoUrl: 'hosted.bitbucket.com?project=project&repo=repo',
},
});
});
@@ -33,7 +33,14 @@ const createBitbucketCloudRepository = async (opts: {
repoVisibility: 'private' | 'public';
authorization: string;
}) => {
const { workspace, project, repo, description, repoVisibility, authorization } = opts;
const {
workspace,
project,
repo,
description,
repoVisibility,
authorization,
} = opts;
const options: RequestInit = {
method: 'POST',
@@ -115,7 +122,7 @@ const createBitbucketServerRepository = async (opts: {
try {
const baseUrl = apiBaseUrl ? apiBaseUrl : `https://${host}/rest/api/1.0`;
response = await fetch(`${baseUrl}/projects/${owner}/repos`, options);
response = await fetch(`${baseUrl}/projects/${project}/repos`, options);
} catch (e) {
throw new Error(`Unable to create repository, ${e}`);
}
@@ -162,10 +169,10 @@ const getAuthorizationHeader = (config: BitbucketIntegrationConfig) => {
const performEnableLFS = async (opts: {
authorization: string;
host: string;
owner: string;
project: string;
repo: string;
}) => {
const { authorization, host, owner, repo } = opts;
const { authorization, host, project, repo } = opts;
const options: RequestInit = {
method: 'PUT',
@@ -175,7 +182,7 @@ const performEnableLFS = async (opts: {
};
const { ok, status, statusText } = await fetch(
`https://${host}/rest/git-lfs/admin/projects/${owner}/repos/${repo}/enabled`,
`https://${host}/rest/git-lfs/admin/projects/${project}/repos/${repo}/enabled`,
options,
);
@@ -268,10 +275,10 @@ export function createPublishBitbucketAction(options: {
// Workspace is only required for bitbucket cloud
if (host === 'bitbucket.org') {
if (!workspace) {
throw new InputError(
`Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing workspace`,
);
}
throw new InputError(
`Invalid URL provider was included in the repo URL to create ${ctx.input.repoUrl}, missing workspace`,
);
}
}
// Project is required for both bitbucket cloud and bitbucket server
@@ -293,9 +300,9 @@ export function createPublishBitbucketAction(options: {
const apiBaseUrl = integrationConfig.config.apiBaseUrl;
const createMethod =
host === 'bitbucket.org'
? createBitbucketCloudRepository
: createBitbucketServerRepository;
host === 'bitbucket.org'
? createBitbucketCloudRepository
: createBitbucketServerRepository;
const { remoteUrl, repoContentsUrl } = await createMethod({
authorization,
@@ -333,7 +340,7 @@ export function createPublishBitbucketAction(options: {
});
if (enableLFS && host !== 'bitbucket.org') {
await performEnableLFS({ authorization, host, owner, repo });
await performEnableLFS({ authorization, host, project, repo });
}
ctx.output('remoteUrl', remoteUrl);
@@ -173,7 +173,13 @@ export const createPublishGithubPullRequestAction = ({
sourcePath,
} = ctx.input;
const { owner, repo, host } = parseRepoUrl(repoUrl);
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
if (!owner) {
throw new InputError(
`No owner provided for host: ${host}, and repo ${repo}`,
);
}
const client = await clientFactory({ integrations, host, owner, repo });
const fileRoot = sourcePath
@@ -65,38 +65,19 @@ export const parseRepoUrl = (
}
if (type === 'bitbucket') {
const organization = parsed.searchParams.get('organization') ?? undefined;
return { host, owner, repo, organization };
};
export const parseRepoUrlForBitbucket = (repoUrl: 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 workspace = parsed.searchParams.get('workspace');
if (!workspace) {
throw new InputError(
`Invalid repo URL passed to publisher: ${repoUrl}, missing workspace`,
);
if (host === 'bitbucket.org') {
if (!workspace) {
throw new InputError(
`Invalid repo URL passed to publisher: ${repoUrl}, missing workspace`,
);
}
}
if (!project) {
throw new InputError(
`Invalid repo URL passed to publisher: ${repoUrl}, missing project`,
);
}
}
else {
} else {
if (!owner) {
throw new InputError(
`Invalid repo URL passed to publisher: ${repoUrl}, missing owner`,
@@ -111,8 +92,5 @@ export const parseRepoUrlForBitbucket = (repoUrl: string) => {
);
}
const organization = parsed.searchParams.get('organization');
return { host, owner, repo, organization, workspace, project };
};
@@ -22,6 +22,7 @@ import { RepoSpec } from '../actions/builtin/publish/util';
import { DatabaseTaskStore } from './DatabaseTaskStore';
import { StorageTaskBroker } from './StorageTaskBroker';
import { TaskWorker } from './TaskWorker';
import { ScmIntegrations } from '@backstage/integration';
async function createStore(): Promise<DatabaseTaskStore> {
const manager = DatabaseManager.fromConfig(
@@ -188,6 +189,7 @@ describe('TaskWorker', () => {
workingDirectory: os.tmpdir(),
actionRegistry,
taskBroker: broker,
integrations,
});
const { taskId } = await broker.dispatch({
@@ -221,6 +223,7 @@ describe('TaskWorker', () => {
workingDirectory: os.tmpdir(),
actionRegistry,
taskBroker: broker,
integrations,
});
const { taskId } = await broker.dispatch({
@@ -254,6 +257,7 @@ describe('TaskWorker', () => {
workingDirectory: os.tmpdir(),
actionRegistry,
taskBroker: broker,
integrations,
});
const { taskId } = await broker.dispatch({
@@ -27,6 +27,7 @@ import { parseRepoUrl } from '../actions/builtin/publish/util';
import { TemplateActionRegistry } from '../actions/TemplateActionRegistry';
import { isTruthy } from './helper';
import { Task, TaskBroker } from './types';
import { ScmIntegrations } from '@backstage/integration';
type Options = {
logger: Logger;
@@ -50,7 +51,7 @@ export class TaskWorker {
});
this.handlebars.registerHelper('projectSlug', repoUrl => {
const { owner, repo } = parseRepoUrl(repoUrl);
const { owner, repo } = parseRepoUrl(repoUrl, options.integrations);
return `${owner}/${repo}`;
});
@@ -100,20 +100,21 @@ export const RepoUrlPicker = ({
return await scaffolderApi.getIntegrationsList({ allowedHosts });
});
const { host, type, owner, repo, organization, workspace, project } = splitFormData(formData);
const { host, owner, repo, organization, workspace, project } = splitFormData(
formData,
);
const updateHost = useCallback(
(evt: React.ChangeEvent<{ name?: string; value: unknown }>) => {
onChange(
serializeFormData({
host: evt.target.value as string,
type: (integrations?getIntegrationTypeByHost(evt.target.value as string, integrations): undefined),
owner,
repo,
organization,
workspace,
project,
}),
)
);
},
[onChange, owner, repo, organization, workspace, project],
);
@@ -160,7 +161,7 @@ export const RepoUrlPicker = ({
project,
}),
),
[onChange, host , type, owner, repo, workspace, project],
[onChange, host, owner, repo, workspace, project],
);
const updateWorkspace = useCallback(
@@ -206,7 +207,16 @@ export const RepoUrlPicker = ({
}),
);
}
}, [onChange, integrations, host, type, owner, repo, organization, workspace, project]);
}, [
onChange,
integrations,
host,
owner,
repo,
organization,
workspace,
project,
]);
if (loading) {
return <Progress />;
@@ -263,7 +273,11 @@ export const RepoUrlPicker = ({
error={rawErrors?.length > 0 && !workspace}
>
<InputLabel htmlFor="wokrspaceInput">Workspace</InputLabel>
<Input id="wokrspaceInput" onChange={updateWorkspace} value={workspace} />
<Input
id="wokrspaceInput"
onChange={updateWorkspace}
value={workspace}
/>
<FormHelperText>
The workspace where the repository will be created
</FormHelperText>
@@ -275,7 +289,11 @@ export const RepoUrlPicker = ({
error={rawErrors?.length > 0 && !project}
>
<InputLabel htmlFor="wokrspaceInput">Project</InputLabel>
<Input id="wokrspaceInput" onChange={updateProject} value={project} />
<Input
id="wokrspaceInput"
onChange={updateProject}
value={project}
/>
<FormHelperText>
The project where the repository will be created
</FormHelperText>