forked from cerc-io/snowballtools-base
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
175af0f9e0 | ||
|
|
d975390a1b | ||
|
|
f77323364c | ||
|
|
c6a78f2116 | ||
|
|
cff9a5b2ea | ||
|
|
003b83ba21 | ||
|
|
82a1c151a8 | ||
|
|
2ada11f311 | ||
|
|
6e32d0678a | ||
|
|
198478f5fa | ||
|
|
552dfe783e | ||
|
|
e2bf5d052c | ||
|
|
33323b9bbf | ||
|
|
e2a3254563 | ||
|
|
8589bf4094 | ||
|
|
f8ebdfe7aa | ||
|
|
2166b2f800 | ||
|
|
cdd8d15e73 | ||
|
|
dc7b251988 | ||
|
|
bfb4a3f30b | ||
|
|
8f7fc888a9 | ||
|
|
0e9c3a07fd | ||
|
|
61e3e88a6c |
@@ -19,6 +19,7 @@
|
|||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"express-async-errors": "^3.1.1",
|
||||||
"express-session": "^1.18.0",
|
"express-session": "^1.18.0",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'express-async-errors';
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|||||||
@@ -25,8 +25,15 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
return service.getProjectById(projectId);
|
return service.getProjectById(projectId);
|
||||||
},
|
},
|
||||||
|
|
||||||
projectsInOrganization: async (_: any, { organizationSlug }: {organizationSlug: string }, context: any) => {
|
projectsInOrganization: async (
|
||||||
return service.getProjectsInOrganization(context.user, organizationSlug);
|
_: any,
|
||||||
|
{ organizationSlug }: { organizationSlug: string },
|
||||||
|
context: any,
|
||||||
|
) => {
|
||||||
|
return service.getProjectsInOrganization(
|
||||||
|
context.user,
|
||||||
|
organizationSlug,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
deployments: async (_: any, { projectId }: { projectId: string }) => {
|
deployments: async (_: any, { projectId }: { projectId: string }) => {
|
||||||
@@ -35,7 +42,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
environmentVariables: async (
|
environmentVariables: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ projectId }: { projectId: string }
|
{ projectId }: { projectId: string },
|
||||||
) => {
|
) => {
|
||||||
return service.getEnvironmentVariablesByProjectId(projectId);
|
return service.getEnvironmentVariablesByProjectId(projectId);
|
||||||
},
|
},
|
||||||
@@ -44,7 +51,11 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
return service.getProjectMembersByProjectId(projectId);
|
return service.getProjectMembersByProjectId(projectId);
|
||||||
},
|
},
|
||||||
|
|
||||||
searchProjects: async (_: any, { searchText }: { searchText: string }, context: any) => {
|
searchProjects: async (
|
||||||
|
_: any,
|
||||||
|
{ searchText }: { searchText: string },
|
||||||
|
context: any,
|
||||||
|
) => {
|
||||||
return service.searchProjects(context.user, searchText);
|
return service.searchProjects(context.user, searchText);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -52,11 +63,11 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
filter
|
filter,
|
||||||
}: { projectId: string; filter?: FindOptionsWhere<Domain> }
|
}: { projectId: string; filter?: FindOptionsWhere<Domain> },
|
||||||
) => {
|
) => {
|
||||||
return service.getDomainsByProjectId(projectId, filter);
|
return service.getDomainsByProjectId(projectId, filter);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: Return error in GQL response
|
// TODO: Return error in GQL response
|
||||||
@@ -64,10 +75,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
removeProjectMember: async (
|
removeProjectMember: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ projectMemberId }: { projectMemberId: string },
|
{ projectMemberId }: { projectMemberId: string },
|
||||||
context: any
|
context: any,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.removeProjectMember(context.user, projectMemberId);
|
return await service.removeProjectMember(
|
||||||
|
context.user,
|
||||||
|
projectMemberId,
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
@@ -78,13 +92,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
projectMemberId,
|
projectMemberId,
|
||||||
data
|
data,
|
||||||
}: {
|
}: {
|
||||||
projectMemberId: string;
|
projectMemberId: string;
|
||||||
data: {
|
data: {
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.updateProjectMember(projectMemberId, data);
|
return await service.updateProjectMember(projectMemberId, data);
|
||||||
@@ -98,14 +112,14 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}: {
|
}: {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
data: {
|
data: {
|
||||||
email: string;
|
email: string;
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return Boolean(await service.addProjectMember(projectId, data));
|
return Boolean(await service.addProjectMember(projectId, data));
|
||||||
@@ -119,15 +133,15 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}: {
|
}: {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
data: { environments: string[]; key: string; value: string }[];
|
data: { environments: string[]; key: string; value: string }[];
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return Boolean(
|
return Boolean(
|
||||||
await service.addEnvironmentVariables(projectId, data)
|
await service.addEnvironmentVariables(projectId, data),
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
@@ -139,16 +153,16 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
environmentVariableId,
|
environmentVariableId,
|
||||||
data
|
data,
|
||||||
}: {
|
}: {
|
||||||
environmentVariableId: string;
|
environmentVariableId: string;
|
||||||
data: DeepPartial<EnvironmentVariable>;
|
data: DeepPartial<EnvironmentVariable>;
|
||||||
}
|
},
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.updateEnvironmentVariable(
|
return await service.updateEnvironmentVariable(
|
||||||
environmentVariableId,
|
environmentVariableId,
|
||||||
data
|
data,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
@@ -158,7 +172,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
removeEnvironmentVariable: async (
|
removeEnvironmentVariable: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ environmentVariableId }: { environmentVariableId: string }
|
{ environmentVariableId }: { environmentVariableId: string },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.removeEnvironmentVariable(environmentVariableId);
|
return await service.removeEnvironmentVariable(environmentVariableId);
|
||||||
@@ -171,10 +185,12 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
updateDeploymentToProd: async (
|
updateDeploymentToProd: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ deploymentId }: { deploymentId: string },
|
{ deploymentId }: { deploymentId: string },
|
||||||
context: any
|
context: any,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return Boolean(await service.updateDeploymentToProd(context.user, deploymentId));
|
return Boolean(
|
||||||
|
await service.updateDeploymentToProd(context.user, deploymentId),
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
@@ -185,9 +201,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
organizationSlug,
|
organizationSlug,
|
||||||
data
|
data,
|
||||||
}: { organizationSlug: string; data: DeepPartial<Project> },
|
}: { organizationSlug: string; data: DeepPartial<Project> },
|
||||||
context: any
|
context: any,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.addProject(context.user, organizationSlug, data);
|
return await service.addProject(context.user, organizationSlug, data);
|
||||||
@@ -199,7 +215,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
updateProject: async (
|
updateProject: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ projectId, data }: { projectId: string; data: DeepPartial<Project> }
|
{ projectId, data }: { projectId: string; data: DeepPartial<Project> },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.updateProject(projectId, data);
|
return await service.updateProject(projectId, data);
|
||||||
@@ -212,10 +228,12 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
redeployToProd: async (
|
redeployToProd: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ deploymentId }: { deploymentId: string },
|
{ deploymentId }: { deploymentId: string },
|
||||||
context: any
|
context: any,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return Boolean(await service.redeployToProd(context.user, deploymentId));
|
return Boolean(
|
||||||
|
await service.redeployToProd(context.user, deploymentId),
|
||||||
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
@@ -244,8 +262,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
_: any,
|
_: any,
|
||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
deploymentId
|
deploymentId,
|
||||||
}: { deploymentId: string; projectId: string }
|
}: { deploymentId: string; projectId: string },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.rollbackDeployment(projectId, deploymentId);
|
return await service.rollbackDeployment(projectId, deploymentId);
|
||||||
@@ -257,9 +275,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
deleteDeployment: async (
|
deleteDeployment: async (
|
||||||
_: any,
|
_: any,
|
||||||
{
|
{ deploymentId }: { deploymentId: string },
|
||||||
deploymentId
|
|
||||||
}: { deploymentId: string; }
|
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.deleteDeployment(deploymentId);
|
return await service.deleteDeployment(deploymentId);
|
||||||
@@ -271,7 +287,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
addDomain: async (
|
addDomain: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ projectId, data }: { projectId: string; data: { name: string } }
|
{ projectId, data }: { projectId: string; data: { name: string } },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return Boolean(await service.addDomain(projectId, data));
|
return Boolean(await service.addDomain(projectId, data));
|
||||||
@@ -283,7 +299,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
updateDomain: async (
|
updateDomain: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ domainId, data }: { domainId: string; data: DeepPartial<Domain> }
|
{ domainId, data }: { domainId: string; data: DeepPartial<Domain> },
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.updateDomain(domainId, data);
|
return await service.updateDomain(domainId, data);
|
||||||
@@ -296,7 +312,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
authenticateGitHub: async (
|
authenticateGitHub: async (
|
||||||
_: any,
|
_: any,
|
||||||
{ code }: { code: string },
|
{ code }: { code: string },
|
||||||
context: any
|
context: any,
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
return await service.authenticateGitHub(code, context.user);
|
return await service.authenticateGitHub(code, context.user);
|
||||||
@@ -308,12 +324,14 @@ export const createResolvers = async (service: Service): Promise<any> => {
|
|||||||
|
|
||||||
unauthenticateGitHub: async (_: any, __: object, context: any) => {
|
unauthenticateGitHub: async (_: any, __: object, context: any) => {
|
||||||
try {
|
try {
|
||||||
return service.unauthenticateGitHub(context.user, { gitHubToken: null });
|
return service.unauthenticateGitHub(context.user, {
|
||||||
|
gitHubToken: null,
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ router.get('/registration/:email', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post('/register', async (req, res) => {
|
router.post('/register', async (req, res) => {
|
||||||
|
console.log('Register', req.body);
|
||||||
const { email, challenge, attestation } = req.body;
|
const { email, challenge, attestation } = req.body;
|
||||||
const user = await createUser(req.app.get('service'), {
|
const user = await createUser(req.app.get('service'), {
|
||||||
challenge,
|
challenge,
|
||||||
@@ -31,6 +32,7 @@ router.post('/register', async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post('/authenticate', async (req, res) => {
|
router.post('/authenticate', async (req, res) => {
|
||||||
|
console.log('Authenticate', req.body);
|
||||||
const { signedWhoamiRequest } = req.body;
|
const { signedWhoamiRequest } = req.body;
|
||||||
const user = await authenticateUser(
|
const user = await authenticateUser(
|
||||||
req.app.get('service'),
|
req.app.get('service'),
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Router } from 'express';
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get('/version', async (req, res) => {
|
||||||
|
return res.send({ version: '0.0.7' });
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@@ -17,6 +17,7 @@ import { ServerConfig } from './config';
|
|||||||
import { DEFAULT_GQL_PATH } from './constants';
|
import { DEFAULT_GQL_PATH } from './constants';
|
||||||
import githubRouter from './routes/github';
|
import githubRouter from './routes/github';
|
||||||
import authRouter from './routes/auth';
|
import authRouter from './routes/auth';
|
||||||
|
import stagingRouter from './routes/staging';
|
||||||
import { Service } from './service';
|
import { Service } from './service';
|
||||||
|
|
||||||
const log = debug('snowball:server');
|
const log = debug('snowball:server');
|
||||||
@@ -109,6 +110,12 @@ export const createAndStartServer = async (
|
|||||||
app.set('service', service);
|
app.set('service', service);
|
||||||
app.use('/auth', authRouter);
|
app.use('/auth', authRouter);
|
||||||
app.use('/api/github', githubRouter);
|
app.use('/api/github', githubRouter);
|
||||||
|
app.use('/staging', stagingRouter);
|
||||||
|
|
||||||
|
app.use((err: any, req: any, res: any, next: any) => {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({ error: err.message });
|
||||||
|
});
|
||||||
|
|
||||||
httpServer.listen(port, host, () => {
|
httpServer.listen(port, host, () => {
|
||||||
log(`Server is listening on ${host}:${port}${server.graphqlPath}`);
|
log(`Server is listening on ${host}:${port}${server.graphqlPath}`);
|
||||||
|
|||||||
+225
-169
@@ -15,7 +15,12 @@ import { Permission, ProjectMember } from './entity/ProjectMember';
|
|||||||
import { User } from './entity/User';
|
import { User } from './entity/User';
|
||||||
import { Registry } from './registry';
|
import { Registry } from './registry';
|
||||||
import { GitHubConfig, RegistryConfig } from './config';
|
import { GitHubConfig, RegistryConfig } from './config';
|
||||||
import { AppDeploymentRecord, AppDeploymentRemovalRecord, GitPushEventPayload, PackageJSON } from './types';
|
import {
|
||||||
|
AppDeploymentRecord,
|
||||||
|
AppDeploymentRemovalRecord,
|
||||||
|
GitPushEventPayload,
|
||||||
|
PackageJSON,
|
||||||
|
} from './types';
|
||||||
import { Role } from './entity/UserOrganization';
|
import { Role } from './entity/UserOrganization';
|
||||||
|
|
||||||
const log = debug('snowball:service');
|
const log = debug('snowball:service');
|
||||||
@@ -71,33 +76,32 @@ export class Service {
|
|||||||
// Fetch deployments in building state
|
// Fetch deployments in building state
|
||||||
const deployments = await this.db.getDeployments({
|
const deployments = await this.db.getDeployments({
|
||||||
where: {
|
where: {
|
||||||
status: DeploymentStatus.Building
|
status: DeploymentStatus.Building,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (deployments.length) {
|
if (deployments.length) {
|
||||||
log(
|
log(
|
||||||
`Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`
|
`Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Calculate a timestamp for one hour ago
|
// Calculate a timestamp for one hour ago
|
||||||
const anHourAgo = Date.now() - HOUR;
|
const anHourAgo = Date.now() - HOUR;
|
||||||
|
|
||||||
// Filter out deployments started more than an hour ago and mark them as Error
|
// Filter out deployments started more than an hour ago and mark them as Error
|
||||||
const oldDeploymentsToUpdate = deployments.filter(
|
const oldDeploymentsToUpdate = deployments
|
||||||
deployment => (Number(deployment.updatedAt) < anHourAgo)
|
.filter((deployment) => Number(deployment.updatedAt) < anHourAgo)
|
||||||
)
|
|
||||||
.map((deployment) => {
|
.map((deployment) => {
|
||||||
return this.db.updateDeploymentById(deployment.id, {
|
return this.db.updateDeploymentById(deployment.id, {
|
||||||
status: DeploymentStatus.Error,
|
status: DeploymentStatus.Error,
|
||||||
isCurrent: false
|
isCurrent: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// If there are old deployments to update, log and perform the updates
|
// If there are old deployments to update, log and perform the updates
|
||||||
if (oldDeploymentsToUpdate.length > 0) {
|
if (oldDeploymentsToUpdate.length > 0) {
|
||||||
log(
|
log(
|
||||||
`Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`
|
`Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`,
|
||||||
);
|
);
|
||||||
await Promise.all(oldDeploymentsToUpdate);
|
await Promise.all(oldDeploymentsToUpdate);
|
||||||
}
|
}
|
||||||
@@ -125,17 +129,18 @@ export class Service {
|
|||||||
// Fetch deployments in deleting state
|
// Fetch deployments in deleting state
|
||||||
const deployments = await this.db.getDeployments({
|
const deployments = await this.db.getDeployments({
|
||||||
where: {
|
where: {
|
||||||
status: DeploymentStatus.Deleting
|
status: DeploymentStatus.Deleting,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (deployments.length) {
|
if (deployments.length) {
|
||||||
log(
|
log(
|
||||||
`Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`
|
`Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch ApplicationDeploymentRemovalRecords for deployments
|
// Fetch ApplicationDeploymentRemovalRecords for deployments
|
||||||
const records = await this.registry.getDeploymentRemovalRecords(deployments);
|
const records =
|
||||||
|
await this.registry.getDeploymentRemovalRecords(deployments);
|
||||||
log(`Found ${records.length} ApplicationDeploymentRemovalRecords`);
|
log(`Found ${records.length} ApplicationDeploymentRemovalRecords`);
|
||||||
|
|
||||||
// Update deployments for which ApplicationDeploymentRemovalRecords were returned
|
// Update deployments for which ApplicationDeploymentRemovalRecords were returned
|
||||||
@@ -153,16 +158,16 @@ export class Service {
|
|||||||
* Update deployments with ApplicationDeploymentRecord data
|
* Update deployments with ApplicationDeploymentRecord data
|
||||||
*/
|
*/
|
||||||
async updateDeploymentsWithRecordData(
|
async updateDeploymentsWithRecordData(
|
||||||
records: AppDeploymentRecord[]
|
records: AppDeploymentRecord[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Get deployments for ApplicationDeploymentRecords
|
// Get deployments for ApplicationDeploymentRecords
|
||||||
const deployments = await this.db.getDeployments({
|
const deployments = await this.db.getDeployments({
|
||||||
where: records.map((record) => ({
|
where: records.map((record) => ({
|
||||||
applicationRecordId: record.attributes.application
|
applicationRecordId: record.attributes.application,
|
||||||
})),
|
})),
|
||||||
order: {
|
order: {
|
||||||
createdAt: 'DESC'
|
createdAt: 'DESC',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get project IDs of deployments that are in production environment
|
// Get project IDs of deployments that are in production environment
|
||||||
@@ -174,13 +179,13 @@ export class Service {
|
|||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
new Set<string>()
|
new Set<string>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set old deployments isCurrent to false
|
// Set old deployments isCurrent to false
|
||||||
await this.db.updateDeploymentsByProjectIds(
|
await this.db.updateDeploymentsByProjectIds(
|
||||||
Array.from(productionDeploymentProjectIds),
|
Array.from(productionDeploymentProjectIds),
|
||||||
{ isCurrent: false }
|
{ isCurrent: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
const recordToDeploymentsMap = deployments.reduce(
|
const recordToDeploymentsMap = deployments.reduce(
|
||||||
@@ -188,7 +193,7 @@ export class Service {
|
|||||||
acc[deployment.applicationRecordId] = deployment;
|
acc[deployment.applicationRecordId] = deployment;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update deployment data for ApplicationDeploymentRecords
|
// Update deployment data for ApplicationDeploymentRecords
|
||||||
@@ -200,11 +205,11 @@ export class Service {
|
|||||||
applicationDeploymentRecordData: record.attributes,
|
applicationDeploymentRecordData: record.attributes,
|
||||||
url: record.attributes.url,
|
url: record.attributes.url,
|
||||||
status: DeploymentStatus.Ready,
|
status: DeploymentStatus.Ready,
|
||||||
isCurrent: deployment.environment === Environment.Production
|
isCurrent: deployment.environment === Environment.Production,
|
||||||
});
|
});
|
||||||
|
|
||||||
log(
|
log(
|
||||||
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`
|
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -218,17 +223,23 @@ export class Service {
|
|||||||
records: AppDeploymentRemovalRecord[],
|
records: AppDeploymentRemovalRecord[],
|
||||||
deployments: Deployment[],
|
deployments: Deployment[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const removedApplicationDeploymentRecordIds = records.map(record => record.attributes.deployment);
|
const removedApplicationDeploymentRecordIds = records.map(
|
||||||
|
(record) => record.attributes.deployment,
|
||||||
|
);
|
||||||
|
|
||||||
// Get removed deployments for ApplicationDeploymentRecords
|
// Get removed deployments for ApplicationDeploymentRecords
|
||||||
const removedDeployments = deployments.filter(deployment => removedApplicationDeploymentRecordIds.includes(deployment.applicationDeploymentRecordId!))
|
const removedDeployments = deployments.filter((deployment) =>
|
||||||
|
removedApplicationDeploymentRecordIds.includes(
|
||||||
|
deployment.applicationDeploymentRecordId!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
const recordToDeploymentsMap = removedDeployments.reduce(
|
const recordToDeploymentsMap = removedDeployments.reduce(
|
||||||
(acc: { [key: string]: Deployment }, deployment) => {
|
(acc: { [key: string]: Deployment }, deployment) => {
|
||||||
acc[deployment.applicationDeploymentRecordId!] = deployment;
|
acc[deployment.applicationDeploymentRecordId!] = deployment;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
{}
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update deployment data for ApplicationDeploymentRecords and delete
|
// Update deployment data for ApplicationDeploymentRecords and delete
|
||||||
@@ -241,10 +252,10 @@ export class Service {
|
|||||||
});
|
});
|
||||||
|
|
||||||
log(
|
log(
|
||||||
`Updated deployment ${deployment.id} with ApplicationDeploymentRemovalRecord ${record.id}`
|
`Updated deployment ${deployment.id} with ApplicationDeploymentRemovalRecord ${record.id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.db.deleteDeploymentById(deployment.id)
|
await this.db.deleteDeploymentById(deployment.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(deploymentUpdatePromises);
|
await Promise.all(deploymentUpdatePromises);
|
||||||
@@ -253,41 +264,41 @@ export class Service {
|
|||||||
async getUser(userId: string): Promise<User | null> {
|
async getUser(userId: string): Promise<User | null> {
|
||||||
return this.db.getUser({
|
return this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
id: userId
|
id: userId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserByEmail(email: string): Promise<User | null> {
|
async getUserByEmail(email: string): Promise<User | null> {
|
||||||
return await this.db.getUser({
|
return await this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
email
|
email,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserBySubOrgId(subOrgId: string): Promise<User | null> {
|
async getUserBySubOrgId(subOrgId: string): Promise<User | null> {
|
||||||
return await this.db.getUser({
|
return await this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
subOrgId
|
subOrgId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserByEthAddress(ethAddress: string): Promise<User | null> {
|
async getUserByEthAddress(ethAddress: string): Promise<User | null> {
|
||||||
return await this.db.getUser({
|
return await this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
ethAddress
|
ethAddress,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createUser(params: {
|
async createUser(params: {
|
||||||
name: string
|
name: string;
|
||||||
email: string
|
email: string;
|
||||||
subOrgId: string
|
subOrgId: string;
|
||||||
ethAddress: string
|
ethAddress: string;
|
||||||
turnkeyWalletId: string
|
turnkeyWalletId: string;
|
||||||
}): Promise<User> {
|
}): Promise<User> {
|
||||||
const [org] = await this.db.getOrganizations({});
|
const [org] = await this.db.getOrganizations({});
|
||||||
assert(org, 'No organizations exists in database');
|
assert(org, 'No organizations exists in database');
|
||||||
@@ -305,7 +316,7 @@ export class Service {
|
|||||||
await this.db.addUserOrganization({
|
await this.db.addUserOrganization({
|
||||||
member: user,
|
member: user,
|
||||||
organization: org,
|
organization: org,
|
||||||
role: Role.Owner
|
role: Role.Owner,
|
||||||
});
|
});
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -315,7 +326,7 @@ export class Service {
|
|||||||
const user = await this.db.getUser({ where: { id: userId } });
|
const user = await this.db.getUser({ where: { id: userId } });
|
||||||
assert(
|
assert(
|
||||||
user && user.gitHubToken,
|
user && user.gitHubToken,
|
||||||
'User needs to be authenticated with GitHub token'
|
'User needs to be authenticated with GitHub token',
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Octokit({ auth: user.gitHubToken });
|
return new Octokit({ auth: user.gitHubToken });
|
||||||
@@ -331,8 +342,14 @@ export class Service {
|
|||||||
return dbProject;
|
return dbProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectsInOrganization (user: User, organizationSlug: string): Promise<Project[]> {
|
async getProjectsInOrganization(
|
||||||
const dbProjects = await this.db.getProjectsInOrganization(user.id, organizationSlug);
|
user: User,
|
||||||
|
organizationSlug: string,
|
||||||
|
): Promise<Project[]> {
|
||||||
|
const dbProjects = await this.db.getProjectsInOrganization(
|
||||||
|
user.id,
|
||||||
|
organizationSlug,
|
||||||
|
);
|
||||||
return dbProjects;
|
return dbProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,7 +359,7 @@ export class Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getEnvironmentVariablesByProjectId(
|
async getEnvironmentVariablesByProjectId(
|
||||||
projectId: string
|
projectId: string,
|
||||||
): Promise<EnvironmentVariable[]> {
|
): Promise<EnvironmentVariable[]> {
|
||||||
const dbEnvironmentVariables =
|
const dbEnvironmentVariables =
|
||||||
await this.db.getEnvironmentVariablesByProjectId(projectId);
|
await this.db.getEnvironmentVariablesByProjectId(projectId);
|
||||||
@@ -350,7 +367,7 @@ export class Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getProjectMembersByProjectId(
|
async getProjectMembersByProjectId(
|
||||||
projectId: string
|
projectId: string,
|
||||||
): Promise<ProjectMember[]> {
|
): Promise<ProjectMember[]> {
|
||||||
const dbProjectMembers =
|
const dbProjectMembers =
|
||||||
await this.db.getProjectMembersByProjectId(projectId);
|
await this.db.getProjectMembersByProjectId(projectId);
|
||||||
@@ -358,13 +375,16 @@ export class Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async searchProjects(user: User, searchText: string): Promise<Project[]> {
|
async searchProjects(user: User, searchText: string): Promise<Project[]> {
|
||||||
const dbProjects = await this.db.getProjectsBySearchText(user.id, searchText);
|
const dbProjects = await this.db.getProjectsBySearchText(
|
||||||
|
user.id,
|
||||||
|
searchText,
|
||||||
|
);
|
||||||
return dbProjects;
|
return dbProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainsByProjectId(
|
async getDomainsByProjectId(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
filter?: FindOptionsWhere<Domain>
|
filter?: FindOptionsWhere<Domain>,
|
||||||
): Promise<Domain[]> {
|
): Promise<Domain[]> {
|
||||||
const dbDomains = await this.db.getDomainsByProjectId(projectId, filter);
|
const dbDomains = await this.db.getDomainsByProjectId(projectId, filter);
|
||||||
return dbDomains;
|
return dbDomains;
|
||||||
@@ -372,7 +392,7 @@ export class Service {
|
|||||||
|
|
||||||
async updateProjectMember(
|
async updateProjectMember(
|
||||||
projectMemberId: string,
|
projectMemberId: string,
|
||||||
data: { permissions: Permission[] }
|
data: { permissions: Permission[] },
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return this.db.updateProjectMemberById(projectMemberId, data);
|
return this.db.updateProjectMemberById(projectMemberId, data);
|
||||||
}
|
}
|
||||||
@@ -382,36 +402,39 @@ export class Service {
|
|||||||
data: {
|
data: {
|
||||||
email: string;
|
email: string;
|
||||||
permissions: Permission[];
|
permissions: Permission[];
|
||||||
}
|
},
|
||||||
): Promise<ProjectMember> {
|
): Promise<ProjectMember> {
|
||||||
// TODO: Send invitation
|
// TODO: Send invitation
|
||||||
let user = await this.db.getUser({
|
let user = await this.db.getUser({
|
||||||
where: {
|
where: {
|
||||||
email: data.email
|
email: data.email,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = await this.db.addUser({
|
user = await this.db.addUser({
|
||||||
email: data.email
|
email: data.email,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const newProjectMember = await this.db.addProjectMember({
|
const newProjectMember = await this.db.addProjectMember({
|
||||||
project: {
|
project: {
|
||||||
id: projectId
|
id: projectId,
|
||||||
},
|
},
|
||||||
permissions: data.permissions,
|
permissions: data.permissions,
|
||||||
isPending: true,
|
isPending: true,
|
||||||
member: {
|
member: {
|
||||||
id: user.id
|
id: user.id,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return newProjectMember;
|
return newProjectMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeProjectMember (user: User, projectMemberId: string): Promise<boolean> {
|
async removeProjectMember(
|
||||||
|
user: User,
|
||||||
|
projectMemberId: string,
|
||||||
|
): Promise<boolean> {
|
||||||
const member = await this.db.getProjectMemberById(projectMemberId);
|
const member = await this.db.getProjectMemberById(projectMemberId);
|
||||||
|
|
||||||
if (String(member.member.id) === user.id) {
|
if (String(member.member.id) === user.id) {
|
||||||
@@ -430,7 +453,7 @@ export class Service {
|
|||||||
|
|
||||||
async addEnvironmentVariables(
|
async addEnvironmentVariables(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
data: { environments: string[]; key: string; value: string }[]
|
data: { environments: string[]; key: string; value: string }[],
|
||||||
): Promise<EnvironmentVariable[]> {
|
): Promise<EnvironmentVariable[]> {
|
||||||
const formattedEnvironmentVariables = data
|
const formattedEnvironmentVariables = data
|
||||||
.map((environmentVariable) => {
|
.map((environmentVariable) => {
|
||||||
@@ -440,38 +463,41 @@ export class Service {
|
|||||||
value: environmentVariable.value,
|
value: environmentVariable.value,
|
||||||
environment: environment as Environment,
|
environment: environment as Environment,
|
||||||
project: Object.assign(new Project(), {
|
project: Object.assign(new Project(), {
|
||||||
id: projectId
|
id: projectId,
|
||||||
})
|
}),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.flat();
|
.flat();
|
||||||
|
|
||||||
const savedEnvironmentVariables = await this.db.addEnvironmentVariables(
|
const savedEnvironmentVariables = await this.db.addEnvironmentVariables(
|
||||||
formattedEnvironmentVariables
|
formattedEnvironmentVariables,
|
||||||
);
|
);
|
||||||
return savedEnvironmentVariables;
|
return savedEnvironmentVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateEnvironmentVariable(
|
async updateEnvironmentVariable(
|
||||||
environmentVariableId: string,
|
environmentVariableId: string,
|
||||||
data: DeepPartial<EnvironmentVariable>
|
data: DeepPartial<EnvironmentVariable>,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return this.db.updateEnvironmentVariable(environmentVariableId, data);
|
return this.db.updateEnvironmentVariable(environmentVariableId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeEnvironmentVariable(
|
async removeEnvironmentVariable(
|
||||||
environmentVariableId: string
|
environmentVariableId: string,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return this.db.deleteEnvironmentVariable(environmentVariableId);
|
return this.db.deleteEnvironmentVariable(environmentVariableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateDeploymentToProd (user: User, deploymentId: string): Promise<Deployment> {
|
async updateDeploymentToProd(
|
||||||
|
user: User,
|
||||||
|
deploymentId: string,
|
||||||
|
): Promise<Deployment> {
|
||||||
const oldDeployment = await this.db.getDeployment({
|
const oldDeployment = await this.db.getDeployment({
|
||||||
where: { id: deploymentId },
|
where: { id: deploymentId },
|
||||||
relations: {
|
relations: {
|
||||||
project: true
|
project: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!oldDeployment) {
|
if (!oldDeployment) {
|
||||||
@@ -480,20 +506,18 @@ export class Service {
|
|||||||
|
|
||||||
const prodBranchDomains = await this.db.getDomainsByProjectId(
|
const prodBranchDomains = await this.db.getDomainsByProjectId(
|
||||||
oldDeployment.project.id,
|
oldDeployment.project.id,
|
||||||
{ branch: oldDeployment.project.prodBranch }
|
{ branch: oldDeployment.project.prodBranch },
|
||||||
);
|
);
|
||||||
|
|
||||||
const octokit = await this.getOctokit(user.id);
|
const octokit = await this.getOctokit(user.id);
|
||||||
|
|
||||||
const newDeployment = await this.createDeployment(user.id,
|
const newDeployment = await this.createDeployment(user.id, octokit, {
|
||||||
octokit,
|
|
||||||
{
|
|
||||||
project: oldDeployment.project,
|
project: oldDeployment.project,
|
||||||
branch: oldDeployment.branch,
|
branch: oldDeployment.branch,
|
||||||
environment: Environment.Production,
|
environment: Environment.Production,
|
||||||
domain: prodBranchDomains[0],
|
domain: prodBranchDomains[0],
|
||||||
commitHash: oldDeployment.commitHash,
|
commitHash: oldDeployment.commitHash,
|
||||||
commitMessage: oldDeployment.commitMessage
|
commitMessage: oldDeployment.commitMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
return newDeployment;
|
return newDeployment;
|
||||||
@@ -502,11 +526,11 @@ export class Service {
|
|||||||
async createDeployment(
|
async createDeployment(
|
||||||
userId: string,
|
userId: string,
|
||||||
octokit: Octokit,
|
octokit: Octokit,
|
||||||
data: DeepPartial<Deployment>
|
data: DeepPartial<Deployment>,
|
||||||
): Promise<Deployment> {
|
): Promise<Deployment> {
|
||||||
assert(data.project?.repository, 'Project repository not found');
|
assert(data.project?.repository, 'Project repository not found');
|
||||||
log(
|
log(
|
||||||
`Creating deployment in project ${data.project.name} from branch ${data.branch}`
|
`Creating deployment in project ${data.project.name} from branch ${data.branch}`,
|
||||||
);
|
);
|
||||||
const [owner, repo] = data.project.repository.split('/');
|
const [owner, repo] = data.project.repository.split('/');
|
||||||
|
|
||||||
@@ -514,7 +538,7 @@ export class Service {
|
|||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
path: 'package.json',
|
path: 'package.json',
|
||||||
ref: data.commitHash
|
ref: data.commitHash,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!packageJSONData) {
|
if (!packageJSONData) {
|
||||||
@@ -526,10 +550,12 @@ export class Service {
|
|||||||
|
|
||||||
assert(packageJSON.name, "name field doesn't exist in package.json");
|
assert(packageJSON.name, "name field doesn't exist in package.json");
|
||||||
|
|
||||||
const repoUrl = (await octokit.rest.repos.get({
|
const repoUrl = (
|
||||||
|
await octokit.rest.repos.get({
|
||||||
owner,
|
owner,
|
||||||
repo
|
repo,
|
||||||
})).data.html_url;
|
})
|
||||||
|
).data.html_url;
|
||||||
|
|
||||||
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
|
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
|
||||||
const { applicationRecordId, applicationRecordData } =
|
const { applicationRecordId, applicationRecordData } =
|
||||||
@@ -538,17 +564,20 @@ export class Service {
|
|||||||
packageJSON,
|
packageJSON,
|
||||||
appType: data.project!.template!,
|
appType: data.project!.template!,
|
||||||
commitHash: data.commitHash!,
|
commitHash: data.commitHash!,
|
||||||
repoUrl
|
repoUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update previous deployment with prod branch domain
|
// Update previous deployment with prod branch domain
|
||||||
// TODO: Fix unique constraint error for domain
|
// TODO: Fix unique constraint error for domain
|
||||||
if (data.domain) {
|
if (data.domain) {
|
||||||
await this.db.updateDeployment({
|
await this.db.updateDeployment(
|
||||||
domainId: data.domain.id
|
{
|
||||||
}, {
|
domainId: data.domain.id,
|
||||||
domain: null
|
},
|
||||||
});
|
{
|
||||||
|
domain: null,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newDeployment = await this.db.addDeployment({
|
const newDeployment = await this.db.addDeployment({
|
||||||
@@ -562,53 +591,67 @@ export class Service {
|
|||||||
applicationRecordData,
|
applicationRecordData,
|
||||||
domain: data.domain,
|
domain: data.domain,
|
||||||
createdBy: Object.assign(new User(), {
|
createdBy: Object.assign(new User(), {
|
||||||
id: userId
|
id: userId,
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
log(`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`);
|
log(
|
||||||
|
`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`,
|
||||||
|
);
|
||||||
|
|
||||||
const environmentVariables = await this.db.getEnvironmentVariablesByProjectId(data.project.id!, { environment: Environment.Production });
|
const environmentVariables =
|
||||||
|
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, {
|
||||||
|
environment: Environment.Production,
|
||||||
|
});
|
||||||
|
|
||||||
const environmentVariablesObj = environmentVariables.reduce((acc, env) => {
|
const environmentVariablesObj = environmentVariables.reduce(
|
||||||
|
(acc, env) => {
|
||||||
acc[env.key] = env.value;
|
acc[env.key] = env.value;
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as { [key: string]: string });
|
},
|
||||||
|
{} as { [key: string]: string },
|
||||||
|
);
|
||||||
|
|
||||||
// To set project DNS
|
// To set project DNS
|
||||||
if (data.environment === Environment.Production) {
|
if (data.environment === Environment.Production) {
|
||||||
// On deleting deployment later, project DNS deployment is also deleted
|
// On deleting deployment later, project DNS deployment is also deleted
|
||||||
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
|
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
|
||||||
await this.registry.createApplicationDeploymentRequest(
|
await this.registry.createApplicationDeploymentRequest({
|
||||||
{
|
|
||||||
deployment: newDeployment,
|
deployment: newDeployment,
|
||||||
appName: repo,
|
appName: repo,
|
||||||
repository: repoUrl,
|
repository: repoUrl,
|
||||||
environmentVariables: environmentVariablesObj,
|
environmentVariables: environmentVariablesObj,
|
||||||
dns: `${newDeployment.project.name}`
|
dns: `${newDeployment.project.name}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.registry.createApplicationDeploymentRequest(
|
const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
|
||||||
{
|
await this.registry.createApplicationDeploymentRequest({
|
||||||
deployment: newDeployment,
|
deployment: newDeployment,
|
||||||
appName: repo,
|
appName: repo,
|
||||||
repository: repoUrl,
|
repository: repoUrl,
|
||||||
environmentVariables: environmentVariablesObj,
|
environmentVariables: environmentVariablesObj,
|
||||||
dns: `${newDeployment.project.name}-${newDeployment.id}`
|
dns: `${newDeployment.project.name}-${newDeployment.id}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData });
|
await this.db.updateDeploymentById(newDeployment.id, {
|
||||||
|
applicationDeploymentRequestId,
|
||||||
|
applicationDeploymentRequestData,
|
||||||
|
});
|
||||||
|
|
||||||
return newDeployment;
|
return newDeployment;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addProject (user: User, organizationSlug: string, data: DeepPartial<Project>): Promise<Project | undefined> {
|
async addProject(
|
||||||
|
user: User,
|
||||||
|
organizationSlug: string,
|
||||||
|
data: DeepPartial<Project>,
|
||||||
|
): Promise<Project | undefined> {
|
||||||
const organization = await this.db.getOrganization({
|
const organization = await this.db.getOrganization({
|
||||||
where: {
|
where: {
|
||||||
slug: organizationSlug
|
slug: organizationSlug,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
if (!organization) {
|
if (!organization) {
|
||||||
throw new Error('Organization does not exist');
|
throw new Error('Organization does not exist');
|
||||||
@@ -620,26 +663,23 @@ export class Service {
|
|||||||
const [owner, repo] = project.repository.split('/');
|
const [owner, repo] = project.repository.split('/');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: [latestCommit]
|
data: [latestCommit],
|
||||||
} = await octokit.rest.repos.listCommits({
|
} = await octokit.rest.repos.listCommits({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
sha: project.prodBranch,
|
sha: project.prodBranch,
|
||||||
per_page: 1
|
per_page: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create deployment with prod branch and latest commit
|
// Create deployment with prod branch and latest commit
|
||||||
await this.createDeployment(user.id,
|
await this.createDeployment(user.id, octokit, {
|
||||||
octokit,
|
|
||||||
{
|
|
||||||
project,
|
project,
|
||||||
branch: project.prodBranch,
|
branch: project.prodBranch,
|
||||||
environment: Environment.Production,
|
environment: Environment.Production,
|
||||||
domain: null,
|
domain: null,
|
||||||
commitHash: latestCommit.sha,
|
commitHash: latestCommit.sha,
|
||||||
commitMessage: latestCommit.commit.message
|
commitMessage: latestCommit.commit.message,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
await this.createRepoHook(octokit, project);
|
await this.createRepoHook(octokit, project);
|
||||||
|
|
||||||
@@ -655,11 +695,11 @@ export class Service {
|
|||||||
config: {
|
config: {
|
||||||
url: new URL(
|
url: new URL(
|
||||||
'api/github/webhook',
|
'api/github/webhook',
|
||||||
this.config.gitHubConfig.webhookUrl
|
this.config.gitHubConfig.webhookUrl,
|
||||||
).href,
|
).href,
|
||||||
content_type: 'json'
|
content_type: 'json',
|
||||||
},
|
},
|
||||||
events: ['push']
|
events: ['push'],
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook--status-codes
|
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook--status-codes
|
||||||
@@ -668,7 +708,7 @@ export class Service {
|
|||||||
err instanceof RequestError &&
|
err instanceof RequestError &&
|
||||||
err.status === 422 &&
|
err.status === 422 &&
|
||||||
(err.response?.data as any).errors.some(
|
(err.response?.data as any).errors.some(
|
||||||
(err: any) => err.message === GITHUB_UNIQUE_WEBHOOK_ERROR
|
(err: any) => err.message === GITHUB_UNIQUE_WEBHOOK_ERROR,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -687,9 +727,11 @@ export class Service {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`);
|
log(
|
||||||
|
`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`,
|
||||||
|
);
|
||||||
const projects = await this.db.getProjects({
|
const projects = await this.db.getProjects({
|
||||||
where: { repository: repository.full_name }
|
where: { repository: repository.full_name },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!projects.length) {
|
if (!projects.length) {
|
||||||
@@ -703,7 +745,7 @@ export class Service {
|
|||||||
for await (const project of projects) {
|
for await (const project of projects) {
|
||||||
const octokit = await this.getOctokit(project.ownerId);
|
const octokit = await this.getOctokit(project.ownerId);
|
||||||
const [domain] = await this.db.getDomainsByProjectId(project.id, {
|
const [domain] = await this.db.getDomainsByProjectId(project.id, {
|
||||||
branch
|
branch,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create deployment with branch and latest commit in GitHub data
|
// Create deployment with branch and latest commit in GitHub data
|
||||||
@@ -716,14 +758,14 @@ export class Service {
|
|||||||
: Environment.Preview,
|
: Environment.Preview,
|
||||||
domain,
|
domain,
|
||||||
commitHash: headCommit.id,
|
commitHash: headCommit.id,
|
||||||
commitMessage: headCommit.message
|
commitMessage: headCommit.message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProject(
|
async updateProject(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
data: DeepPartial<Project>
|
data: DeepPartial<Project>,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
return this.db.updateProjectById(projectId, data);
|
return this.db.updateProjectById(projectId, data);
|
||||||
}
|
}
|
||||||
@@ -736,13 +778,13 @@ export class Service {
|
|||||||
async deleteDomain(domainId: string): Promise<boolean> {
|
async deleteDomain(domainId: string): Promise<boolean> {
|
||||||
const domainsRedirectedFrom = await this.db.getDomains({
|
const domainsRedirectedFrom = await this.db.getDomains({
|
||||||
where: {
|
where: {
|
||||||
redirectToId: domainId
|
redirectToId: domainId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (domainsRedirectedFrom.length > 0) {
|
if (domainsRedirectedFrom.length > 0) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Cannot delete domain since it has redirects from other domains'
|
'Cannot delete domain since it has redirects from other domains',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,11 +796,11 @@ export class Service {
|
|||||||
relations: {
|
relations: {
|
||||||
project: true,
|
project: true,
|
||||||
domain: true,
|
domain: true,
|
||||||
createdBy: true
|
createdBy: true,
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
id: deploymentId
|
id: deploymentId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (oldDeployment === null) {
|
if (oldDeployment === null) {
|
||||||
@@ -767,16 +809,14 @@ export class Service {
|
|||||||
|
|
||||||
const octokit = await this.getOctokit(user.id);
|
const octokit = await this.getOctokit(user.id);
|
||||||
|
|
||||||
const newDeployment = await this.createDeployment(user.id,
|
const newDeployment = await this.createDeployment(user.id, octokit, {
|
||||||
octokit,
|
|
||||||
{
|
|
||||||
project: oldDeployment.project,
|
project: oldDeployment.project,
|
||||||
// TODO: Put isCurrent field in project
|
// TODO: Put isCurrent field in project
|
||||||
branch: oldDeployment.branch,
|
branch: oldDeployment.branch,
|
||||||
environment: Environment.Production,
|
environment: Environment.Production,
|
||||||
domain: oldDeployment.domain,
|
domain: oldDeployment.domain,
|
||||||
commitHash: oldDeployment.commitHash,
|
commitHash: oldDeployment.commitHash,
|
||||||
commitMessage: oldDeployment.commitMessage
|
commitMessage: oldDeployment.commitMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
return newDeployment;
|
return newDeployment;
|
||||||
@@ -784,19 +824,19 @@ export class Service {
|
|||||||
|
|
||||||
async rollbackDeployment(
|
async rollbackDeployment(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
deploymentId: string
|
deploymentId: string,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
// TODO: Implement transactions
|
// TODO: Implement transactions
|
||||||
const oldCurrentDeployment = await this.db.getDeployment({
|
const oldCurrentDeployment = await this.db.getDeployment({
|
||||||
relations: {
|
relations: {
|
||||||
domain: true
|
domain: true,
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
project: {
|
project: {
|
||||||
id: projectId
|
id: projectId,
|
||||||
|
},
|
||||||
|
isCurrent: true,
|
||||||
},
|
},
|
||||||
isCurrent: true
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!oldCurrentDeployment) {
|
if (!oldCurrentDeployment) {
|
||||||
@@ -805,12 +845,12 @@ export class Service {
|
|||||||
|
|
||||||
const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById(
|
const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById(
|
||||||
oldCurrentDeployment.id,
|
oldCurrentDeployment.id,
|
||||||
{ isCurrent: false, domain: null }
|
{ isCurrent: false, domain: null },
|
||||||
);
|
);
|
||||||
|
|
||||||
const newCurrentDeploymentUpdate = await this.db.updateDeploymentById(
|
const newCurrentDeploymentUpdate = await this.db.updateDeploymentById(
|
||||||
deploymentId,
|
deploymentId,
|
||||||
{ isCurrent: true, domain: oldCurrentDeployment?.domain }
|
{ isCurrent: true, domain: oldCurrentDeployment?.domain },
|
||||||
);
|
);
|
||||||
|
|
||||||
return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate;
|
return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate;
|
||||||
@@ -819,11 +859,11 @@ export class Service {
|
|||||||
async deleteDeployment(deploymentId: string): Promise<boolean> {
|
async deleteDeployment(deploymentId: string): Promise<boolean> {
|
||||||
const deployment = await this.db.getDeployment({
|
const deployment = await this.db.getDeployment({
|
||||||
where: {
|
where: {
|
||||||
id: deploymentId
|
id: deploymentId,
|
||||||
},
|
},
|
||||||
relations: {
|
relations: {
|
||||||
project: true
|
project: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (deployment && deployment.applicationDeploymentRecordId) {
|
if (deployment && deployment.applicationDeploymentRecordId) {
|
||||||
@@ -831,31 +871,39 @@ export class Service {
|
|||||||
if (deployment.isCurrent) {
|
if (deployment.isCurrent) {
|
||||||
const currentDeploymentURL = `https://${deployment.project.subDomain}`;
|
const currentDeploymentURL = `https://${deployment.project.subDomain}`;
|
||||||
|
|
||||||
const deploymentRecords = await this.registry.getDeploymentRecordsByFilter({
|
const deploymentRecords =
|
||||||
|
await this.registry.getDeploymentRecordsByFilter({
|
||||||
application: deployment.applicationRecordId,
|
application: deployment.applicationRecordId,
|
||||||
url: currentDeploymentURL
|
url: currentDeploymentURL,
|
||||||
})
|
});
|
||||||
|
|
||||||
if (!deploymentRecords.length) {
|
if (!deploymentRecords.length) {
|
||||||
log(`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`);
|
log(
|
||||||
|
`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`,
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deploymentRecords[0].id });
|
await this.registry.createApplicationDeploymentRemovalRequest({
|
||||||
|
deploymentId: deploymentRecords[0].id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deployment.applicationDeploymentRecordId });
|
const result =
|
||||||
|
await this.registry.createApplicationDeploymentRemovalRequest({
|
||||||
|
deploymentId: deployment.applicationDeploymentRecordId,
|
||||||
|
});
|
||||||
|
|
||||||
await this.db.updateDeploymentById(
|
await this.db.updateDeploymentById(deployment.id, {
|
||||||
deployment.id,
|
|
||||||
{
|
|
||||||
status: DeploymentStatus.Deleting,
|
status: DeploymentStatus.Deleting,
|
||||||
applicationDeploymentRemovalRequestId: result.applicationDeploymentRemovalRequestId,
|
applicationDeploymentRemovalRequestId:
|
||||||
applicationDeploymentRemovalRequestData: result.applicationDeploymentRemovalRequestData
|
result.applicationDeploymentRemovalRequestId,
|
||||||
}
|
applicationDeploymentRemovalRequestData:
|
||||||
);
|
result.applicationDeploymentRemovalRequestData,
|
||||||
|
});
|
||||||
|
|
||||||
return (result !== undefined || result !== null);
|
return result !== undefined || result !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -863,7 +911,7 @@ export class Service {
|
|||||||
|
|
||||||
async addDomain(
|
async addDomain(
|
||||||
projectId: string,
|
projectId: string,
|
||||||
data: { name: string }
|
data: { name: string },
|
||||||
): Promise<{
|
): Promise<{
|
||||||
primaryDomain: Domain;
|
primaryDomain: Domain;
|
||||||
redirectedDomain: Domain;
|
redirectedDomain: Domain;
|
||||||
@@ -877,7 +925,7 @@ export class Service {
|
|||||||
const primaryDomainDetails = {
|
const primaryDomainDetails = {
|
||||||
...data,
|
...data,
|
||||||
branch: currentProject.prodBranch,
|
branch: currentProject.prodBranch,
|
||||||
project: currentProject
|
project: currentProject,
|
||||||
};
|
};
|
||||||
|
|
||||||
const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails);
|
const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails);
|
||||||
@@ -888,27 +936,27 @@ export class Service {
|
|||||||
name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`,
|
name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`,
|
||||||
branch: currentProject.prodBranch,
|
branch: currentProject.prodBranch,
|
||||||
project: currentProject,
|
project: currentProject,
|
||||||
redirectTo: savedPrimaryDomain
|
redirectTo: savedPrimaryDomain,
|
||||||
};
|
};
|
||||||
|
|
||||||
const savedRedirectedDomain = await this.db.addDomain(
|
const savedRedirectedDomain = await this.db.addDomain(
|
||||||
redirectedDomainDetails
|
redirectedDomainDetails,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
primaryDomain: savedPrimaryDomain,
|
primaryDomain: savedPrimaryDomain,
|
||||||
redirectedDomain: savedRedirectedDomain
|
redirectedDomain: savedRedirectedDomain,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateDomain(
|
async updateDomain(
|
||||||
domainId: string,
|
domainId: string,
|
||||||
data: DeepPartial<Domain>
|
data: DeepPartial<Domain>,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const domain = await this.db.getDomain({
|
const domain = await this.db.getDomain({
|
||||||
where: {
|
where: {
|
||||||
id: domainId
|
id: domainId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (domain === null) {
|
if (domain === null) {
|
||||||
@@ -916,16 +964,16 @@ export class Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const newDomain = {
|
const newDomain = {
|
||||||
...data
|
...data,
|
||||||
};
|
};
|
||||||
|
|
||||||
const domainsRedirectedFrom = await this.db.getDomains({
|
const domainsRedirectedFrom = await this.db.getDomains({
|
||||||
where: {
|
where: {
|
||||||
project: {
|
project: {
|
||||||
id: domain.projectId
|
id: domain.projectId,
|
||||||
|
},
|
||||||
|
redirectToId: domain.id,
|
||||||
},
|
},
|
||||||
redirectToId: domain.id
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// If there are domains redirecting to current domain, only branch of current domain can be updated
|
// If there are domains redirecting to current domain, only branch of current domain can be updated
|
||||||
@@ -936,8 +984,8 @@ export class Service {
|
|||||||
if (data.redirectToId) {
|
if (data.redirectToId) {
|
||||||
const redirectedDomain = await this.db.getDomain({
|
const redirectedDomain = await this.db.getDomain({
|
||||||
where: {
|
where: {
|
||||||
id: data.redirectToId
|
id: data.redirectToId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (redirectedDomain === null) {
|
if (redirectedDomain === null) {
|
||||||
@@ -946,7 +994,7 @@ export class Service {
|
|||||||
|
|
||||||
if (redirectedDomain.redirectToId) {
|
if (redirectedDomain.redirectToId) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.'
|
'Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -958,9 +1006,14 @@ export class Service {
|
|||||||
return updateResult;
|
return updateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
async authenticateGitHub (code:string, user: User): Promise<{token: string}> {
|
async authenticateGitHub(
|
||||||
const { authentication: { token } } = await this.oauthApp.createToken({
|
code: string,
|
||||||
code
|
user: User,
|
||||||
|
): Promise<{ token: string }> {
|
||||||
|
const {
|
||||||
|
authentication: { token },
|
||||||
|
} = await this.oauthApp.createToken({
|
||||||
|
code,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.db.updateUser(user, { gitHubToken: token });
|
await this.db.updateUser(user, { gitHubToken: token });
|
||||||
@@ -968,7 +1021,10 @@ export class Service {
|
|||||||
return { token };
|
return { token };
|
||||||
}
|
}
|
||||||
|
|
||||||
async unauthenticateGitHub (user: User, data: DeepPartial<User>): Promise<boolean> {
|
async unauthenticateGitHub(
|
||||||
|
user: User,
|
||||||
|
data: DeepPartial<User>,
|
||||||
|
): Promise<boolean> {
|
||||||
return this.db.updateUser(user, data);
|
return this.db.updateUser(user, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ services:
|
|||||||
restEndpoint: 'http://console.laconic.com:1317'
|
restEndpoint: 'http://console.laconic.com:1317'
|
||||||
gqlEndpoint: 'http://console.laconic.com:9473/api'
|
gqlEndpoint: 'http://console.laconic.com:9473/api'
|
||||||
userKey: 87d00f66a73e2ca428adeb49ba9164d0ad9a87edc60e33d46ad3031b9c5701fe
|
userKey: 87d00f66a73e2ca428adeb49ba9164d0ad9a87edc60e33d46ad3031b9c5701fe
|
||||||
bondId: 098c906850b87412f02200e41f449bc79e055eab77acfef32c0b22443bb46661
|
bondId: 89c75c7bc5759861d10285aff6f9e7227d6855e446b77ad5d8324822dfec7deb
|
||||||
chainId: laconic_9000-1
|
chainId: laconic_9000-1
|
||||||
gas: 550000
|
gas: 1200000
|
||||||
fees: 200000aphoton
|
fees: 200000aphoton
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Repository URL
|
# Repository URL
|
||||||
REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base"
|
REPO_URL="https://github.com/snowball-tools/snowballtools-base"
|
||||||
|
|
||||||
# Get the latest commit hash from the repository
|
# Get the latest commit hash from the repository
|
||||||
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
|
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
|
||||||
@@ -64,7 +64,13 @@ echo "Files generated successfully."
|
|||||||
RECORD_FILE=records/application-record.yml
|
RECORD_FILE=records/application-record.yml
|
||||||
|
|
||||||
# Publish ApplicationRecord
|
# Publish ApplicationRecord
|
||||||
RECORD_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
|
publish_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE)
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to publish record"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
RECORD_ID=$(echo $publish_response | jq -r '.id')
|
||||||
echo "ApplicationRecord published"
|
echo "ApplicationRecord published"
|
||||||
echo $RECORD_ID
|
echo $RECORD_ID
|
||||||
|
|
||||||
@@ -73,15 +79,36 @@ REGISTRY_APP_CRN="crn://snowballtools/applications/snowballtools-base-frontend"
|
|||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set name: $REGISTRY_APP_CRN@${PACKAGE_VERSION}"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set hash"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
# Set name if latest release
|
# Set name if latest release
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set release"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
echo "$REGISTRY_APP_CRN set for ApplicationRecord"
|
echo "$REGISTRY_APP_CRN set for ApplicationRecord"
|
||||||
|
|
||||||
# Check if record found for REGISTRY_APP_CRN
|
# Check if record found for REGISTRY_APP_CRN
|
||||||
APP_RECORD=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN" | jq '.[0]')
|
query_response=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN")
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to query name"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
APP_RECORD=$(echo $query_response | jq '.[0]')
|
||||||
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
|
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
|
||||||
echo "No record found for $REGISTRY_APP_CRN."
|
echo "No record found for $REGISTRY_APP_CRN."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -90,6 +117,11 @@ fi
|
|||||||
RECORD_FILE=records/application-deployment-request.yml
|
RECORD_FILE=records/application-deployment-request.yml
|
||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
DEPLOYMENT_REQUEST_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
|
deployment_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE)
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to query deployment request"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
DEPLOYMENT_REQUEST_ID=$(echo $deployment_response | jq -r '.id')
|
||||||
echo "ApplicationDeploymentRequest published"
|
echo "ApplicationDeploymentRequest published"
|
||||||
echo $DEPLOYMENT_REQUEST_ID
|
echo $DEPLOYMENT_REQUEST_ID
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Repository URL
|
# Repository URL
|
||||||
REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base"
|
REPO_URL="https://github.com/snowball-tools/snowballtools-base"
|
||||||
|
|
||||||
# Get the latest commit hash from the repository
|
# Get the latest commit hash from the repository
|
||||||
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
|
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
|
||||||
@@ -44,8 +44,8 @@ record:
|
|||||||
LACONIC_HOSTED_CONFIG_lit_relay_api_key: 15DDD969-E75F-404D-AAD9-58A37C4FD354_snowball
|
LACONIC_HOSTED_CONFIG_lit_relay_api_key: 15DDD969-E75F-404D-AAD9-58A37C4FD354_snowball
|
||||||
LACONIC_HOSTED_CONFIG_aplchemy_api_key: THvPart_gqI5x02RNYSBntlmwA66I_qc
|
LACONIC_HOSTED_CONFIG_aplchemy_api_key: THvPart_gqI5x02RNYSBntlmwA66I_qc
|
||||||
LACONIC_HOSTED_CONFIG_bugsnag_api_key: 8c480cd5386079f9dd44f9581264a073
|
LACONIC_HOSTED_CONFIG_bugsnag_api_key: 8c480cd5386079f9dd44f9581264a073
|
||||||
LACONIC_HOSTED_CONFIG_passkey_wallet_rpid: localhost
|
LACONIC_HOSTED_CONFIG_passkey_wallet_rpid: dashboard.staging.apps.snowballtools.com
|
||||||
LACONIC_HOSTED_CONFIG_turnkey_api_base_url: https://api.turnkey.com/
|
LACONIC_HOSTED_CONFIG_turnkey_api_base_url: https://api.turnkey.com
|
||||||
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
|
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
|
||||||
meta:
|
meta:
|
||||||
note: Added by Snowball @ $CURRENT_DATE_TIME
|
note: Added by Snowball @ $CURRENT_DATE_TIME
|
||||||
@@ -70,7 +70,13 @@ echo "Files generated successfully."
|
|||||||
RECORD_FILE=staging-records/application-record.yml
|
RECORD_FILE=staging-records/application-record.yml
|
||||||
|
|
||||||
# Publish ApplicationRecord
|
# Publish ApplicationRecord
|
||||||
RECORD_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
|
publish_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE)
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to publish record"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
RECORD_ID=$(echo $publish_response | jq -r '.id')
|
||||||
echo "ApplicationRecord published"
|
echo "ApplicationRecord published"
|
||||||
echo $RECORD_ID
|
echo $RECORD_ID
|
||||||
|
|
||||||
@@ -79,15 +85,36 @@ REGISTRY_APP_CRN="crn://staging-snowballtools/applications/staging-snowballtools
|
|||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set name: $REGISTRY_APP_CRN@${PACKAGE_VERSION}"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set hash"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
# Set name if latest release
|
# Set name if latest release
|
||||||
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
|
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to set release"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
echo "$REGISTRY_APP_CRN set for ApplicationRecord"
|
echo "$REGISTRY_APP_CRN set for ApplicationRecord"
|
||||||
|
|
||||||
# Check if record found for REGISTRY_APP_CRN
|
# Check if record found for REGISTRY_APP_CRN
|
||||||
APP_RECORD=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN" | jq '.[0]')
|
query_response=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN")
|
||||||
|
rc=$?
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to query name"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
APP_RECORD=$(echo $query_response | jq '.[0]')
|
||||||
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
|
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
|
||||||
echo "No record found for $REGISTRY_APP_CRN."
|
echo "No record found for $REGISTRY_APP_CRN."
|
||||||
exit 1
|
exit 1
|
||||||
@@ -96,6 +123,11 @@ fi
|
|||||||
RECORD_FILE=staging-records/application-deployment-request.yml
|
RECORD_FILE=staging-records/application-deployment-request.yml
|
||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
DEPLOYMENT_REQUEST_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
|
deployment_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE)
|
||||||
|
if [ $rc -ne 0 ]; then
|
||||||
|
echo "FATAL: Failed to query deployment request"
|
||||||
|
exit $rc
|
||||||
|
fi
|
||||||
|
DEPLOYMENT_REQUEST_ID=$(echo $deployment_response | jq -r '.id')
|
||||||
echo "ApplicationDeploymentRequest published"
|
echo "ApplicationDeploymentRequest published"
|
||||||
echo $DEPLOYMENT_REQUEST_ID
|
echo $DEPLOYMENT_REQUEST_ID
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ record:
|
|||||||
LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2
|
LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2
|
||||||
meta:
|
meta:
|
||||||
note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024
|
note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024
|
||||||
repository: "https://git.vdb.to/cerc-io/snowballtools-base"
|
repository: "https://github.com/snowball-tools/snowballtools-base"
|
||||||
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
|
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ record:
|
|||||||
type: ApplicationRecord
|
type: ApplicationRecord
|
||||||
version: 0.0.2
|
version: 0.0.2
|
||||||
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
|
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
|
||||||
repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
|
repository: ["https://github.com/snowball-tools/snowballtools-base"]
|
||||||
app_type: webapp
|
app_type: webapp
|
||||||
name: snowballtools-base-frontend
|
name: snowballtools-base-frontend
|
||||||
app_version: 0.1.8
|
app_version: 0.1.8
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ record:
|
|||||||
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
|
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
|
||||||
meta:
|
meta:
|
||||||
note: Added by Snowball @ Tuesday 21 May 2024 06:17:23 AM UTC
|
note: Added by Snowball @ Tuesday 21 May 2024 06:17:23 AM UTC
|
||||||
repository: "https://git.vdb.to/cerc-io/snowballtools-base"
|
repository: "https://github.com/snowball-tools/snowballtools-base"
|
||||||
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
|
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ record:
|
|||||||
type: ApplicationRecord
|
type: ApplicationRecord
|
||||||
version: 0.0.2
|
version: 0.0.2
|
||||||
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
|
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
|
||||||
repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
|
repository: ["https://github.com/snowball-tools/snowballtools-base"]
|
||||||
app_type: webapp
|
app_type: webapp
|
||||||
name: staging-snowballtools-base-frontend
|
name: staging-snowballtools-base-frontend
|
||||||
app_version: 0.0.0
|
app_version: 0.0.0
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Input, InputProps } from './shared/Input';
|
|||||||
const SearchBar: React.ForwardRefRenderFunction<
|
const SearchBar: React.ForwardRefRenderFunction<
|
||||||
HTMLInputElement,
|
HTMLInputElement,
|
||||||
InputProps & RefAttributes<HTMLInputElement>
|
InputProps & RefAttributes<HTMLInputElement>
|
||||||
> = ({ value, onChange, placeholder = 'Search', ...props }) => {
|
> = ({ value, onChange, placeholder = 'Search', ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<div className="relative flex w-full">
|
<div className="relative flex w-full">
|
||||||
<Input
|
<Input
|
||||||
@@ -18,6 +18,7 @@ const SearchBar: React.ForwardRefRenderFunction<
|
|||||||
appearance="borderless"
|
appearance="borderless"
|
||||||
className="w-full lg:w-[459px]"
|
className="w-full lg:w-[459px]"
|
||||||
{...props}
|
{...props}
|
||||||
|
ref={ref}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+14
-24
@@ -1,13 +1,8 @@
|
|||||||
import { CopyBlock, atomOneLight } from 'react-code-blocks';
|
import { CopyBlock, atomOneLight } from 'react-code-blocks';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import { Modal } from 'components/shared/Modal';
|
||||||
Button,
|
import { Button } from 'components/shared/Button';
|
||||||
Dialog,
|
|
||||||
DialogHeader,
|
|
||||||
DialogBody,
|
|
||||||
DialogFooter,
|
|
||||||
} from '@snowballtools/material-tailwind-react-fork';
|
|
||||||
|
|
||||||
interface AssignDomainProps {
|
interface AssignDomainProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@@ -16,11 +11,12 @@ interface AssignDomainProps {
|
|||||||
|
|
||||||
const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
|
const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} handler={handleOpen}>
|
<Modal open={open} onOpenChange={handleOpen}>
|
||||||
<DialogHeader>Assign Domain</DialogHeader>
|
<Modal.Content>
|
||||||
<DialogBody>
|
<Modal.Header>Assign Domain</Modal.Header>
|
||||||
In order to assign a domain to your production deployments, configure it
|
<Modal.Body>
|
||||||
in the{' '}
|
In order to assign a domain to your production deployments, configure
|
||||||
|
it in the{' '}
|
||||||
{/* TODO: Fix selection of project settings tab on navigation to domains */}
|
{/* TODO: Fix selection of project settings tab on navigation to domains */}
|
||||||
<Link to="../settings/domains" className="text-light-blue-800 inline">
|
<Link to="../settings/domains" className="text-light-blue-800 inline">
|
||||||
project settings{' '}
|
project settings{' '}
|
||||||
@@ -34,18 +30,12 @@ const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
|
|||||||
showLineNumbers={false}
|
showLineNumbers={false}
|
||||||
theme={atomOneLight}
|
theme={atomOneLight}
|
||||||
/>
|
/>
|
||||||
</DialogBody>
|
</Modal.Body>
|
||||||
<DialogFooter className="flex justify-start">
|
<Modal.Footer className="flex justify-start">
|
||||||
<Button
|
<Button onClick={handleOpen}>Okay</Button>
|
||||||
className="rounded-3xl"
|
</Modal.Footer>
|
||||||
variant="gradient"
|
</Modal.Content>
|
||||||
color="blue"
|
</Modal>
|
||||||
onClick={handleOpen}
|
|
||||||
>
|
|
||||||
<span>Okay</span>
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</Dialog>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { useState } from 'react';
|
import { useState, ComponentPropsWithRef } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
|
||||||
|
import {
|
||||||
|
Menu,
|
||||||
|
MenuHandler,
|
||||||
|
MenuItem,
|
||||||
|
MenuList,
|
||||||
|
} from '@snowballtools/material-tailwind-react-fork';
|
||||||
|
|
||||||
import { Deployment, Domain, Environment, Project } from 'gql-client';
|
import { Deployment, Domain, Environment, Project } from 'gql-client';
|
||||||
import { Button } from 'components/shared/Button';
|
import { Button } from 'components/shared/Button';
|
||||||
import {
|
import {
|
||||||
@@ -11,17 +18,11 @@ import {
|
|||||||
UndoIcon,
|
UndoIcon,
|
||||||
CrossCircleIcon,
|
CrossCircleIcon,
|
||||||
} from 'components/shared/CustomIcon';
|
} from 'components/shared/CustomIcon';
|
||||||
import {
|
|
||||||
Menu,
|
|
||||||
MenuHandler,
|
|
||||||
MenuItem,
|
|
||||||
MenuList,
|
|
||||||
} from '@snowballtools/material-tailwind-react-fork';
|
|
||||||
import { ComponentPropsWithRef } from 'react';
|
|
||||||
import AssignDomainDialog from './AssignDomainDialog';
|
import AssignDomainDialog from './AssignDomainDialog';
|
||||||
import { useGQLClient } from 'context/GQLClientContext';
|
import { useGQLClient } from 'context/GQLClientContext';
|
||||||
import { cn } from 'utils/classnames';
|
import { cn } from 'utils/classnames';
|
||||||
import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog';
|
import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog';
|
||||||
|
import { useToast } from 'components/shared/Toast';
|
||||||
|
|
||||||
interface DeploymentMenuProps extends ComponentPropsWithRef<'div'> {
|
interface DeploymentMenuProps extends ComponentPropsWithRef<'div'> {
|
||||||
deployment: Deployment;
|
deployment: Deployment;
|
||||||
@@ -41,6 +42,7 @@ export const DeploymentMenu = ({
|
|||||||
...props
|
...props
|
||||||
}: DeploymentMenuProps) => {
|
}: DeploymentMenuProps) => {
|
||||||
const client = useGQLClient();
|
const client = useGQLClient();
|
||||||
|
const { toast, dismiss } = useToast();
|
||||||
|
|
||||||
const [changeToProduction, setChangeToProduction] = useState(false);
|
const [changeToProduction, setChangeToProduction] = useState(false);
|
||||||
const [redeployToProduction, setRedeployToProduction] = useState(false);
|
const [redeployToProduction, setRedeployToProduction] = useState(false);
|
||||||
@@ -51,9 +53,19 @@ export const DeploymentMenu = ({
|
|||||||
const isUpdated = await client.updateDeploymentToProd(deployment.id);
|
const isUpdated = await client.updateDeploymentToProd(deployment.id);
|
||||||
if (isUpdated) {
|
if (isUpdated) {
|
||||||
await onUpdate();
|
await onUpdate();
|
||||||
toast.success('Deployment changed to production');
|
toast({
|
||||||
|
id: 'deployment_changed_to_production',
|
||||||
|
title: 'Deployment changed to production',
|
||||||
|
variant: 'success',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.error('Unable to change deployment to production');
|
toast({
|
||||||
|
id: 'deployment_not_changed_to_production',
|
||||||
|
title: 'Error changing deployment to production',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -61,9 +73,19 @@ export const DeploymentMenu = ({
|
|||||||
const isRedeployed = await client.redeployToProd(deployment.id);
|
const isRedeployed = await client.redeployToProd(deployment.id);
|
||||||
if (isRedeployed) {
|
if (isRedeployed) {
|
||||||
await onUpdate();
|
await onUpdate();
|
||||||
toast.success('Redeployed to production');
|
toast({
|
||||||
|
id: 'redeployed_to_production',
|
||||||
|
title: 'Redeployed to production',
|
||||||
|
variant: 'success',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.error('Unable to redeploy to production');
|
toast({
|
||||||
|
id: 'redeployed_to_production_failed',
|
||||||
|
title: 'Error redeploying to production',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,9 +96,19 @@ export const DeploymentMenu = ({
|
|||||||
);
|
);
|
||||||
if (isRollbacked) {
|
if (isRollbacked) {
|
||||||
await onUpdate();
|
await onUpdate();
|
||||||
toast.success('Deployment rolled back');
|
toast({
|
||||||
|
id: 'deployment_rolled_back',
|
||||||
|
title: 'Deployment rolled back',
|
||||||
|
variant: 'success',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.error('Unable to rollback deployment');
|
toast({
|
||||||
|
id: 'deployment_rollback_failed',
|
||||||
|
title: 'Error rolling back deployment',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,9 +116,19 @@ export const DeploymentMenu = ({
|
|||||||
const isDeleted = await client.deleteDeployment(deployment.id);
|
const isDeleted = await client.deleteDeployment(deployment.id);
|
||||||
if (isDeleted) {
|
if (isDeleted) {
|
||||||
await onUpdate();
|
await onUpdate();
|
||||||
toast.success('Deleted deployment');
|
toast({
|
||||||
|
id: 'deployment_deleted',
|
||||||
|
title: 'Deployment deleted',
|
||||||
|
variant: 'success',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast.error('Unable to delete deployment');
|
toast({
|
||||||
|
id: 'deployment_not_deleted',
|
||||||
|
title: 'Error deleting deployment',
|
||||||
|
variant: 'error',
|
||||||
|
onDismiss: dismiss,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
ComponentPropsWithoutRef,
|
ComponentPropsWithoutRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { FieldValues, UseFormRegister } from 'react-hook-form';
|
|
||||||
|
|
||||||
import { WarningIcon } from 'components/shared/CustomIcon';
|
import { WarningIcon } from 'components/shared/CustomIcon';
|
||||||
import { cloneIcon } from 'utils/cloneIcon';
|
import { cloneIcon } from 'utils/cloneIcon';
|
||||||
@@ -12,7 +11,7 @@ import { cn } from 'utils/classnames';
|
|||||||
|
|
||||||
import { InputTheme, inputTheme } from './Input.theme';
|
import { InputTheme, inputTheme } from './Input.theme';
|
||||||
|
|
||||||
export interface InputProps<T extends FieldValues = FieldValues>
|
export interface InputProps
|
||||||
extends InputTheme,
|
extends InputTheme,
|
||||||
Omit<ComponentPropsWithoutRef<'input'>, 'size'> {
|
Omit<ComponentPropsWithoutRef<'input'>, 'size'> {
|
||||||
label?: string;
|
label?: string;
|
||||||
@@ -20,9 +19,6 @@ export interface InputProps<T extends FieldValues = FieldValues>
|
|||||||
leftIcon?: ReactNode;
|
leftIcon?: ReactNode;
|
||||||
rightIcon?: ReactNode;
|
rightIcon?: ReactNode;
|
||||||
helperText?: string;
|
helperText?: string;
|
||||||
|
|
||||||
// react-hook-form optional register
|
|
||||||
register?: ReturnType<UseFormRegister<T>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Input = forwardRef<HTMLInputElement, InputProps>(
|
const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||||
@@ -34,7 +30,6 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|||||||
leftIcon,
|
leftIcon,
|
||||||
rightIcon,
|
rightIcon,
|
||||||
helperText,
|
helperText,
|
||||||
register,
|
|
||||||
size,
|
size,
|
||||||
state,
|
state,
|
||||||
appearance,
|
appearance,
|
||||||
@@ -107,12 +102,11 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
|
|||||||
<div className={containerCls({ class: className })}>
|
<div className={containerCls({ class: className })}>
|
||||||
{leftIcon && renderLeftIcon}
|
{leftIcon && renderLeftIcon}
|
||||||
<input
|
<input
|
||||||
{...(register ? register : {})}
|
|
||||||
className={cn(inputCls(), {
|
className={cn(inputCls(), {
|
||||||
'pl-10': leftIcon,
|
'pl-10': leftIcon,
|
||||||
})}
|
})}
|
||||||
{...props}
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
{rightIcon && renderRightIcon}
|
{rightIcon && renderRightIcon}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import { SERVER_GQL_PATH } from './constants';
|
|||||||
import { Toaster } from 'components/shared/Toast';
|
import { Toaster } from 'components/shared/Toast';
|
||||||
import { LogErrorBoundary } from 'utils/log-error';
|
import { LogErrorBoundary } from 'utils/log-error';
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
console.log(`v-${__VERSION__}`);
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement,
|
document.getElementById('root') as HTMLElement,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ export const Login = ({ onDone }: Props) => {
|
|||||||
console.log('Handling google redirect back');
|
console.log('Handling google redirect back');
|
||||||
try {
|
try {
|
||||||
await google.handleOAuthRedirectBack();
|
await google.handleOAuthRedirectBack();
|
||||||
|
// @ts-ignore
|
||||||
wallet = await google.getEthersWallet();
|
wallet = await google.getEthersWallet();
|
||||||
|
// @ts-ignore
|
||||||
const result = await signInWithEthereum(1, 'login', wallet);
|
const result = await signInWithEthereum(1, 'login', wallet);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
setError(result.error);
|
setError(result.error);
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ export const SignUp = ({ onDone }: Props) => {
|
|||||||
setProvider('google');
|
setProvider('google');
|
||||||
try {
|
try {
|
||||||
await google.handleOAuthRedirectBack();
|
await google.handleOAuthRedirectBack();
|
||||||
|
// @ts-ignore
|
||||||
wallet = await google.getEthersWallet();
|
wallet = await google.getEthersWallet();
|
||||||
|
// @ts-ignore
|
||||||
const result = await signInWithEthereum(1, 'signup', wallet);
|
const result = await signInWithEthereum(1, 'signup', wallet);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
setError({ type: 'provider', message: result.error });
|
setError({ type: 'provider', message: result.error });
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { defineConfig, PluginOption } from 'vite';
|
import { defineConfig, PluginOption } from 'vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -16,5 +18,8 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
'process.env': {},
|
'process.env': {},
|
||||||
|
__VERSION__: JSON.stringify(
|
||||||
|
(await promisify(exec)('git rev-parse --short HEAD')).stdout.trim(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+4
-1
@@ -20,7 +20,10 @@ var __async = (__this, __arguments, generator) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// src/client.ts
|
// src/client.ts
|
||||||
import { ApolloClient, InMemoryCache } from "@apollo/client";
|
import {
|
||||||
|
ApolloClient,
|
||||||
|
InMemoryCache
|
||||||
|
} from "@apollo/client";
|
||||||
|
|
||||||
// src/queries.ts
|
// src/queries.ts
|
||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -1,8 +1,13 @@
|
|||||||
import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';
|
import {
|
||||||
|
ApolloClient,
|
||||||
|
DefaultOptions,
|
||||||
|
InMemoryCache,
|
||||||
|
NormalizedCacheObject,
|
||||||
|
} from "@apollo/client";
|
||||||
|
|
||||||
import * as queries from './queries';
|
import * as queries from "./queries";
|
||||||
import * as types from './types';
|
import * as types from "./types";
|
||||||
import * as mutations from './mutations';
|
import * as mutations from "./mutations";
|
||||||
|
|
||||||
export interface GraphQLConfig {
|
export interface GraphQLConfig {
|
||||||
gqlEndpoint: string;
|
gqlEndpoint: string;
|
||||||
@@ -11,13 +16,13 @@ export interface GraphQLConfig {
|
|||||||
// TODO: check options
|
// TODO: check options
|
||||||
const defaultOptions: DefaultOptions = {
|
const defaultOptions: DefaultOptions = {
|
||||||
watchQuery: {
|
watchQuery: {
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: "no-cache",
|
||||||
errorPolicy: 'ignore'
|
errorPolicy: "ignore",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: "no-cache",
|
||||||
errorPolicy: 'all'
|
errorPolicy: "all",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export class GQLClient {
|
export class GQLClient {
|
||||||
@@ -28,13 +33,13 @@ export class GQLClient {
|
|||||||
uri: config.gqlEndpoint,
|
uri: config.gqlEndpoint,
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
credentials: 'include'
|
credentials: "include",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser(): Promise<types.GetUserResponse> {
|
async getUser(): Promise<types.GetUserResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getUser
|
query: queries.getUser,
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -44,19 +49,21 @@ export class GQLClient {
|
|||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getProject,
|
query: queries.getProject,
|
||||||
variables: {
|
variables: {
|
||||||
projectId
|
projectId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectsInOrganization (organizationSlug: string) : Promise<types.GetProjectsInOrganizationResponse> {
|
async getProjectsInOrganization(
|
||||||
|
organizationSlug: string
|
||||||
|
): Promise<types.GetProjectsInOrganizationResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getProjectsInOrganization,
|
query: queries.getProjectsInOrganization,
|
||||||
variables: {
|
variables: {
|
||||||
organizationSlug
|
organizationSlug,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -64,179 +71,216 @@ export class GQLClient {
|
|||||||
|
|
||||||
async getOrganizations(): Promise<types.GetOrganizationsResponse> {
|
async getOrganizations(): Promise<types.GetOrganizationsResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getOrganizations
|
query: queries.getOrganizations,
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDeployments (projectId: string) : Promise<types.GetDeploymentsResponse> {
|
async getDeployments(
|
||||||
|
projectId: string
|
||||||
|
): Promise<types.GetDeploymentsResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getDeployments,
|
query: queries.getDeployments,
|
||||||
variables: {
|
variables: {
|
||||||
projectId
|
projectId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEnvironmentVariables (projectId: string) : Promise<types.GetEnvironmentVariablesResponse> {
|
async getEnvironmentVariables(
|
||||||
|
projectId: string
|
||||||
|
): Promise<types.GetEnvironmentVariablesResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getEnvironmentVariables,
|
query: queries.getEnvironmentVariables,
|
||||||
variables: {
|
variables: {
|
||||||
projectId
|
projectId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectMembers (projectId: string) : Promise<types.GetProjectMembersResponse> {
|
async getProjectMembers(
|
||||||
|
projectId: string
|
||||||
|
): Promise<types.GetProjectMembersResponse> {
|
||||||
const result = await this.client.query({
|
const result = await this.client.query({
|
||||||
query: queries.getProjectMembers,
|
query: queries.getProjectMembers,
|
||||||
variables: {
|
variables: {
|
||||||
projectId
|
projectId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addProjectMember (projectId: string, data: types.AddProjectMemberInput) : Promise<types.AddProjectMemberResponse> {
|
async addProjectMember(
|
||||||
|
projectId: string,
|
||||||
|
data: types.AddProjectMemberInput
|
||||||
|
): Promise<types.AddProjectMemberResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.addProjectMember,
|
mutation: mutations.addProjectMember,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProjectMember (projectMemberId: string, data: types.UpdateProjectMemberInput): Promise<types.UpdateProjectMemberResponse> {
|
async updateProjectMember(
|
||||||
|
projectMemberId: string,
|
||||||
|
data: types.UpdateProjectMemberInput
|
||||||
|
): Promise<types.UpdateProjectMemberResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.updateProjectMember,
|
mutation: mutations.updateProjectMember,
|
||||||
variables: {
|
variables: {
|
||||||
projectMemberId,
|
projectMemberId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeProjectMember (projectMemberId: string): Promise<types.RemoveProjectMemberResponse> {
|
async removeProjectMember(
|
||||||
|
projectMemberId: string
|
||||||
|
): Promise<types.RemoveProjectMemberResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.removeProjectMember,
|
mutation: mutations.removeProjectMember,
|
||||||
variables: {
|
variables: {
|
||||||
projectMemberId
|
projectMemberId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchProjects (searchText: string) : Promise<types.SearchProjectsResponse> {
|
async searchProjects(
|
||||||
|
searchText: string
|
||||||
|
): Promise<types.SearchProjectsResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.searchProjects,
|
query: queries.searchProjects,
|
||||||
variables: {
|
variables: {
|
||||||
searchText
|
searchText,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addEnvironmentVariables (projectId: string, data: types.AddEnvironmentVariableInput[]): Promise<types.AddEnvironmentVariablesResponse> {
|
async addEnvironmentVariables(
|
||||||
|
projectId: string,
|
||||||
|
data: types.AddEnvironmentVariableInput[]
|
||||||
|
): Promise<types.AddEnvironmentVariablesResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.addEnvironmentVariables,
|
mutation: mutations.addEnvironmentVariables,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateEnvironmentVariable (environmentVariableId: string, data: types.UpdateEnvironmentVariableInput): Promise<types.UpdateEnvironmentVariableResponse> {
|
async updateEnvironmentVariable(
|
||||||
|
environmentVariableId: string,
|
||||||
|
data: types.UpdateEnvironmentVariableInput
|
||||||
|
): Promise<types.UpdateEnvironmentVariableResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.updateEnvironmentVariable,
|
mutation: mutations.updateEnvironmentVariable,
|
||||||
variables: {
|
variables: {
|
||||||
environmentVariableId,
|
environmentVariableId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeEnvironmentVariable (environmentVariableId: string): Promise<types.RemoveEnvironmentVariableResponse> {
|
async removeEnvironmentVariable(
|
||||||
|
environmentVariableId: string
|
||||||
|
): Promise<types.RemoveEnvironmentVariableResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.removeEnvironmentVariable,
|
mutation: mutations.removeEnvironmentVariable,
|
||||||
variables: {
|
variables: {
|
||||||
environmentVariableId
|
environmentVariableId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateDeploymentToProd (deploymentId: string): Promise<types.UpdateDeploymentToProdResponse> {
|
async updateDeploymentToProd(
|
||||||
|
deploymentId: string
|
||||||
|
): Promise<types.UpdateDeploymentToProdResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.updateDeploymentToProd,
|
mutation: mutations.updateDeploymentToProd,
|
||||||
variables: {
|
variables: {
|
||||||
deploymentId
|
deploymentId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addProject (organizationSlug: string, data: types.AddProjectInput): Promise<types.AddProjectResponse> {
|
async addProject(
|
||||||
|
organizationSlug: string,
|
||||||
|
data: types.AddProjectInput
|
||||||
|
): Promise<types.AddProjectResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.addProject,
|
mutation: mutations.addProject,
|
||||||
variables: {
|
variables: {
|
||||||
organizationSlug,
|
organizationSlug,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProject (projectId: string, data: types.UpdateProjectInput): Promise<types.UpdateProjectResponse> {
|
async updateProject(
|
||||||
|
projectId: string,
|
||||||
|
data: types.UpdateProjectInput
|
||||||
|
): Promise<types.UpdateProjectResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.updateProjectMutation,
|
mutation: mutations.updateProjectMutation,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateDomain (domainId: string, data: types.UpdateDomainInput): Promise<types.UpdateDomainResponse> {
|
async updateDomain(
|
||||||
|
domainId: string,
|
||||||
|
data: types.UpdateDomainInput
|
||||||
|
): Promise<types.UpdateDomainResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.updateDomainMutation,
|
mutation: mutations.updateDomainMutation,
|
||||||
variables: {
|
variables: {
|
||||||
domainId,
|
domainId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async redeployToProd (deploymentId: string): Promise<types.RedeployToProdResponse> {
|
async redeployToProd(
|
||||||
|
deploymentId: string
|
||||||
|
): Promise<types.RedeployToProdResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.redeployToProd,
|
mutation: mutations.redeployToProd,
|
||||||
variables: {
|
variables: {
|
||||||
deploymentId
|
deploymentId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -246,8 +290,8 @@ export class GQLClient {
|
|||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.deleteProject,
|
mutation: mutations.deleteProject,
|
||||||
variables: {
|
variables: {
|
||||||
projectId
|
projectId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -257,66 +301,79 @@ export class GQLClient {
|
|||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.deleteDomain,
|
mutation: mutations.deleteDomain,
|
||||||
variables: {
|
variables: {
|
||||||
domainId
|
domainId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async rollbackDeployment (projectId: string, deploymentId: string): Promise<types.RollbackDeploymentResponse> {
|
async rollbackDeployment(
|
||||||
|
projectId: string,
|
||||||
|
deploymentId: string
|
||||||
|
): Promise<types.RollbackDeploymentResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.rollbackDeployment,
|
mutation: mutations.rollbackDeployment,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
deploymentId
|
deploymentId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteDeployment (deploymentId: string): Promise<types.DeleteDeploymentResponse> {
|
async deleteDeployment(
|
||||||
|
deploymentId: string
|
||||||
|
): Promise<types.DeleteDeploymentResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.deleteDeployment,
|
mutation: mutations.deleteDeployment,
|
||||||
variables: {
|
variables: {
|
||||||
deploymentId
|
deploymentId,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async addDomain (projectId: string, data: types.AddDomainInput): Promise<types.AddDomainResponse> {
|
async addDomain(
|
||||||
|
projectId: string,
|
||||||
|
data: types.AddDomainInput
|
||||||
|
): Promise<types.AddDomainResponse> {
|
||||||
const result = await this.client.mutate({
|
const result = await this.client.mutate({
|
||||||
mutation: mutations.addDomain,
|
mutation: mutations.addDomain,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
data
|
data,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomains (projectId: string, filter?: types.FilterDomainInput): Promise<types.GetDomainsResponse> {
|
async getDomains(
|
||||||
|
projectId: string,
|
||||||
|
filter?: types.FilterDomainInput
|
||||||
|
): Promise<types.GetDomainsResponse> {
|
||||||
const { data } = await this.client.query({
|
const { data } = await this.client.query({
|
||||||
query: queries.getDomains,
|
query: queries.getDomains,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
filter
|
filter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async authenticateGitHub (code: string): Promise<types.AuthenticateGitHubResponse> {
|
async authenticateGitHub(
|
||||||
|
code: string
|
||||||
|
): Promise<types.AuthenticateGitHubResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.authenticateGitHub,
|
mutation: mutations.authenticateGitHub,
|
||||||
variables: {
|
variables: {
|
||||||
code
|
code,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -324,7 +381,7 @@ export class GQLClient {
|
|||||||
|
|
||||||
async unauthenticateGithub(): Promise<types.UnauthenticateGitHubResponse> {
|
async unauthenticateGithub(): Promise<types.UnauthenticateGitHubResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: mutations.unauthenticateGitHub
|
mutation: mutations.unauthenticateGitHub,
|
||||||
});
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -10575,6 +10575,11 @@ exponential-backoff@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
|
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
|
||||||
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
|
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
|
||||||
|
|
||||||
|
express-async-errors@^3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/express-async-errors/-/express-async-errors-3.1.1.tgz#6053236d61d21ddef4892d6bd1d736889fc9da41"
|
||||||
|
integrity sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==
|
||||||
|
|
||||||
express-session@^1.18.0:
|
express-session@^1.18.0:
|
||||||
version "1.18.0"
|
version "1.18.0"
|
||||||
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3"
|
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3"
|
||||||
|
|||||||
Reference in New Issue
Block a user