mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
Create production, staging and development targets by default for new projects (#196)
This commit is contained in:
parent
9cee7420a7
commit
ebddde55e5
13 changed files with 103 additions and 41 deletions
|
|
@ -104,9 +104,10 @@ export function createProject(input: CreateProjectInput, authToken: string) {
|
|||
id
|
||||
cleanId
|
||||
}
|
||||
createdTarget {
|
||||
createdTargets {
|
||||
id
|
||||
cleanId
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ test('can publish persisted operations only with project:operations-store:write'
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with no rights
|
||||
const noAccessTokenResult = await createToken(
|
||||
|
|
@ -127,7 +127,7 @@ test('should skip on already persisted operations', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
|
|||
45
integration-tests/tests/api/project/create.spec.ts
Normal file
45
integration-tests/tests/api/project/create.spec.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { ProjectType } from '@app/gql/graphql';
|
||||
import { createOrganization, createProject } from '../../../testkit/flow';
|
||||
import { authenticate } from '../../../testkit/auth';
|
||||
|
||||
test('creating a project should result in creating the development, staging and production targets', async () => {
|
||||
const { access_token } = await authenticate('main');
|
||||
const orgResult = await createOrganization(
|
||||
{
|
||||
name: 'foo',
|
||||
},
|
||||
access_token
|
||||
);
|
||||
const org = orgResult.body.data!.createOrganization.ok!.createdOrganizationPayload.organization;
|
||||
|
||||
const projectResult = await createProject(
|
||||
{
|
||||
organization: org.cleanId,
|
||||
type: ProjectType.Single,
|
||||
name: 'foo',
|
||||
},
|
||||
access_token
|
||||
);
|
||||
|
||||
const targets = projectResult.body.data!.createProject.ok!.createdTargets;
|
||||
|
||||
expect(targets).toHaveLength(3);
|
||||
expect(targets).toContainEqual(
|
||||
expect.objectContaining({
|
||||
cleanId: 'development',
|
||||
name: 'development',
|
||||
})
|
||||
);
|
||||
expect(targets).toContainEqual(
|
||||
expect.objectContaining({
|
||||
cleanId: 'staging',
|
||||
name: 'staging',
|
||||
})
|
||||
);
|
||||
expect(targets).toContainEqual(
|
||||
expect.objectContaining({
|
||||
cleanId: 'production',
|
||||
name: 'production',
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
@ -34,7 +34,7 @@ test('can check a schema with target:registry:read access', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -145,7 +145,7 @@ test('should match indentation of previous description', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ test('cannot publish a schema without target:registry:write access', async () =>
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -98,7 +98,7 @@ test('can publish a schema with target:registry:write access', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -175,7 +175,7 @@ test('base schema should not affect the output schema persisted in db', async ()
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -276,7 +276,7 @@ test('directives should not be removed (federation)', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -352,7 +352,7 @@ test('should allow to update the URL of a Federated service without changing the
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -443,7 +443,7 @@ test('should allow to update the URL of a Federated service while also changing
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -532,7 +532,7 @@ test('directives should not be removed (stitching)', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -608,7 +608,7 @@ test('directives should not be removed (single)', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -684,7 +684,7 @@ test('share publication of schema using redis', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -758,7 +758,7 @@ test("Two targets with the same commit id shouldn't return an error", async () =
|
|||
owner_access_token
|
||||
);
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
const writeTokenResult = await createToken(
|
||||
{
|
||||
name: 'test',
|
||||
|
|
@ -843,7 +843,7 @@ test('marking versions as valid', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -987,7 +987,7 @@ test('marking only the most recent version as valid result in an update of CDN',
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -1133,7 +1133,7 @@ test('CDN data can not be fetched with an invalid access token', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -1215,7 +1215,7 @@ test('CDN data can be fetched with an valid access token', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ test('marking only the most recent version as valid result in an update of CDN',
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ test('cannot set a scope on a token if user has no access to that scope', async
|
|||
|
||||
const member = joinResult.body.data!.joinOrganization.organization.me;
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Give access to tokens
|
||||
await updateMemberAccess(
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ test('collect operation', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const settingsTokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -216,7 +216,7 @@ test('normalize and collect operation without breaking its syntax', async () =>
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const settingsTokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -393,7 +393,7 @@ test('number of produced and collected operations should match (no errors)', asy
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
@ -491,7 +491,7 @@ test('check usage from two selected targets', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const staging = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const staging = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const productionTargetResult = await createTarget(
|
||||
{
|
||||
|
|
@ -685,7 +685,7 @@ test('number of produced and collected operations should match', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
const tokenResult = await createToken(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ test('can publish and check a schema with target:registry:read access', async ()
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -94,7 +94,7 @@ test('service url should be available in supergraph', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -163,7 +163,7 @@ test('service url should be required in Federation', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -221,7 +221,7 @@ test('schema:check should notify user when registry is empty', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
@ -267,7 +267,7 @@ test('schema:check should throw on corrupted schema', async () => {
|
|||
);
|
||||
|
||||
const project = projectResult.body.data!.createProject.ok!.createdProject;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTarget;
|
||||
const target = projectResult.body.data!.createProject.ok!.createdTargets[0];
|
||||
|
||||
// Create a token with write rights
|
||||
const writeTokenResult = await createToken(
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export default gql`
|
|||
type CreateProjectOk {
|
||||
selector: ProjectSelector!
|
||||
createdProject: Project!
|
||||
createdTarget: Target!
|
||||
createdTargets: [Target!]!
|
||||
}
|
||||
|
||||
type CreateProjectInputErrors {
|
||||
|
|
|
|||
|
|
@ -62,11 +62,26 @@ export const resolvers: ProjectModule.Resolvers & { ProjectType: any } = {
|
|||
...input,
|
||||
organization,
|
||||
});
|
||||
const target = await injector.get(TargetManager).createTarget({
|
||||
name: 'experiment',
|
||||
project: project.id,
|
||||
organization,
|
||||
});
|
||||
|
||||
const targetManager = injector.get(TargetManager);
|
||||
|
||||
const targets = await Promise.all([
|
||||
targetManager.createTarget({
|
||||
name: 'production',
|
||||
project: project.id,
|
||||
organization,
|
||||
}),
|
||||
targetManager.createTarget({
|
||||
name: 'staging',
|
||||
project: project.id,
|
||||
organization,
|
||||
}),
|
||||
targetManager.createTarget({
|
||||
name: 'development',
|
||||
project: project.id,
|
||||
organization,
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
ok: {
|
||||
|
|
@ -75,7 +90,7 @@ export const resolvers: ProjectModule.Resolvers & { ProjectType: any } = {
|
|||
project: project.cleanId,
|
||||
},
|
||||
createdProject: project,
|
||||
createdTarget: target,
|
||||
createdTargets: targets,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const CreateProjectMutation = gql(/* GraphQL */ `
|
|||
createdProject {
|
||||
...ProjectFields
|
||||
}
|
||||
createdTarget {
|
||||
createdTargets {
|
||||
...TargetFields
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,8 @@ export const CreateProjectModal = ({
|
|||
<Heading className="text-center">Create a project</Heading>
|
||||
<p className="text-sm text-gray-500">
|
||||
A project is built on top of <b>Targets</b>, which are just your environments. We will also create a default
|
||||
stack named <b>experiment</b> for you (don't worry, you can change it later).
|
||||
stacks named <b>production</b>, <b>staging</b> and <b>development</b> for you (don't worry, you can change it
|
||||
later).
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ mutation createProject($input: CreateProjectInput!) {
|
|||
createdProject {
|
||||
...ProjectFields
|
||||
}
|
||||
createdTarget {
|
||||
createdTargets {
|
||||
...TargetFields
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue