Rebase on upstream to get context for validator
Signed-off-by: Mustansar Anwar ul Samad <mustansar.samad@gmail.com>
This commit is contained in:
+7
-1
@@ -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(
|
||||
|
||||
+15
-8
@@ -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);
|
||||
|
||||
+7
-1
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user