diff --git a/integration-tests/testkit/flow.ts b/integration-tests/testkit/flow.ts
index c442cf16a..c2b821085 100644
--- a/integration-tests/testkit/flow.ts
+++ b/integration-tests/testkit/flow.ts
@@ -104,9 +104,10 @@ export function createProject(input: CreateProjectInput, authToken: string) {
id
cleanId
}
- createdTarget {
+ createdTargets {
id
cleanId
+ name
}
}
}
diff --git a/integration-tests/tests/api/persisted-operations/publish.spec.ts b/integration-tests/tests/api/persisted-operations/publish.spec.ts
index 099b0eaf1..06419f7a9 100644
--- a/integration-tests/tests/api/persisted-operations/publish.spec.ts
+++ b/integration-tests/tests/api/persisted-operations/publish.spec.ts
@@ -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(
diff --git a/integration-tests/tests/api/project/create.spec.ts b/integration-tests/tests/api/project/create.spec.ts
new file mode 100644
index 000000000..5e85d1e51
--- /dev/null
+++ b/integration-tests/tests/api/project/create.spec.ts
@@ -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',
+ })
+ );
+});
diff --git a/integration-tests/tests/api/schema/check.spec.ts b/integration-tests/tests/api/schema/check.spec.ts
index ab2609840..b0a3f75a5 100644
--- a/integration-tests/tests/api/schema/check.spec.ts
+++ b/integration-tests/tests/api/schema/check.spec.ts
@@ -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(
diff --git a/integration-tests/tests/api/schema/publish.spec.ts b/integration-tests/tests/api/schema/publish.spec.ts
index eea36fc79..f3875fd14 100644
--- a/integration-tests/tests/api/schema/publish.spec.ts
+++ b/integration-tests/tests/api/schema/publish.spec.ts
@@ -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(
{
diff --git a/integration-tests/tests/api/schema/sync.spec.ts b/integration-tests/tests/api/schema/sync.spec.ts
index 96303725f..733085fde 100644
--- a/integration-tests/tests/api/schema/sync.spec.ts
+++ b/integration-tests/tests/api/schema/sync.spec.ts
@@ -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(
{
diff --git a/integration-tests/tests/api/target/tokens.spec.ts b/integration-tests/tests/api/target/tokens.spec.ts
index 7a2f1d66f..0be812224 100644
--- a/integration-tests/tests/api/target/tokens.spec.ts
+++ b/integration-tests/tests/api/target/tokens.spec.ts
@@ -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(
diff --git a/integration-tests/tests/api/target/usage.spec.ts b/integration-tests/tests/api/target/usage.spec.ts
index 0fb1acc62..805d3379e 100644
--- a/integration-tests/tests/api/target/usage.spec.ts
+++ b/integration-tests/tests/api/target/usage.spec.ts
@@ -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(
{
diff --git a/integration-tests/tests/cli/schema.spec.ts b/integration-tests/tests/cli/schema.spec.ts
index f7ed7e142..8af93c7ce 100644
--- a/integration-tests/tests/cli/schema.spec.ts
+++ b/integration-tests/tests/cli/schema.spec.ts
@@ -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(
diff --git a/packages/services/api/src/modules/project/module.graphql.ts b/packages/services/api/src/modules/project/module.graphql.ts
index 74ab5cee8..8a29e9ed2 100644
--- a/packages/services/api/src/modules/project/module.graphql.ts
+++ b/packages/services/api/src/modules/project/module.graphql.ts
@@ -48,7 +48,7 @@ export default gql`
type CreateProjectOk {
selector: ProjectSelector!
createdProject: Project!
- createdTarget: Target!
+ createdTargets: [Target!]!
}
type CreateProjectInputErrors {
diff --git a/packages/services/api/src/modules/project/resolvers.ts b/packages/services/api/src/modules/project/resolvers.ts
index fa63081ac..125e340ac 100644
--- a/packages/services/api/src/modules/project/resolvers.ts
+++ b/packages/services/api/src/modules/project/resolvers.ts
@@ -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,
},
};
},
diff --git a/packages/web/app/src/components/v2/modals/create-project.tsx b/packages/web/app/src/components/v2/modals/create-project.tsx
index 4457b044b..f5ffeb40b 100644
--- a/packages/web/app/src/components/v2/modals/create-project.tsx
+++ b/packages/web/app/src/components/v2/modals/create-project.tsx
@@ -19,7 +19,7 @@ const CreateProjectMutation = gql(/* GraphQL */ `
createdProject {
...ProjectFields
}
- createdTarget {
+ createdTargets {
...TargetFields
}
}
@@ -95,7 +95,8 @@ export const CreateProjectModal = ({
A project is built on top of Targets, which are just your environments. We will also create a default - stack named experiment for you (don't worry, you can change it later). + stacks named production, staging and development for you (don't worry, you can change it + later).