Assign project domain to latest production deployment (#145)

* Create ApplicationDeploymentRequest with project DNS

* Add comment for filtering AppDeploymentRecord

* Fix lint

* Handle delete gitHub event

* Add sleep before registry write methods

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2024-02-29 18:33:34 +05:30 committed by GitHub
parent a7810a34c9
commit 1ff5ab3dfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 46 additions and 25 deletions

View File

@ -12,12 +12,14 @@ import {
ApplicationDeploymentRequest
} from './entity/Deployment';
import { AppDeploymentRecord, PackageJSON } from './types';
import { sleep } from './utils';
const log = debug('snowball:registry');
const APP_RECORD_TYPE = 'ApplicationRecord';
const APP_DEPLOYMENT_REQUEST_TYPE = 'ApplicationDeploymentRequest';
const APP_DEPLOYMENT_RECORD_TYPE = 'ApplicationDeploymentRecord';
const SLEEP_DURATION = 1000;
// TODO: Move registry code to laconic-sdk/watcher-ts
export class Registry {
@ -111,16 +113,21 @@ export class Registry {
const crn = this.getCrn(appName);
log(`Setting name: ${crn} for record ID: ${result.data.id}`);
await sleep(SLEEP_DURATION);
await this.registry.setName(
{ cid: result.data.id, crn },
this.registryConfig.privateKey,
this.registryConfig.fee
);
await sleep(SLEEP_DURATION);
await this.registry.setName(
{ cid: result.data.id, crn: `${crn}@${applicationRecord.app_version}` },
this.registryConfig.privateKey,
this.registryConfig.fee
);
await sleep(SLEEP_DURATION);
await this.registry.setName(
{
cid: result.data.id,
@ -139,9 +146,9 @@ export class Registry {
async createApplicationDeploymentRequest (data: {
deployment: Deployment,
appName: string,
packageJsonName: string,
repository: string,
environmentVariables: { [key: string]: string }
environmentVariables: { [key: string]: string },
dns: string,
}): Promise<{
applicationDeploymentRequestId: string;
applicationDeploymentRequestData: ApplicationDeploymentRequest;
@ -160,7 +167,7 @@ export class Registry {
version: '1.0.0',
name: `${applicationRecord.attributes.name}@${applicationRecord.attributes.app_version}`,
application: `${crn}@${applicationRecord.attributes.app_version}`,
dns: `${data.deployment.project.name}-${data.deployment.id}`,
dns: data.dns,
// TODO: Not set in test-progressive-web-app CI
// deployment: '$CERC_REGISTRY_DEPLOYMENT_CRN',
@ -178,6 +185,7 @@ export class Registry {
})
};
await sleep(SLEEP_DURATION);
const result = await this.registry.setRecord(
{
privateKey: this.registryConfig.privateKey,
@ -211,11 +219,12 @@ export class Registry {
true
);
// Filter records with ApplicationRecord ids
// Filter records with ApplicationRecord ID and Deployment specific URL
return records.filter((record: AppDeploymentRecord) =>
deployments.some(
(deployment) =>
deployment.applicationRecordId === record.attributes.application
deployment.applicationRecordId === record.attributes.application &&
record.attributes.url.includes(deployment.id)
)
);
}

View File

@ -382,8 +382,7 @@ export class Service {
async createDeployment (
userId: string,
octokit: Octokit,
data: DeepPartial<Deployment>,
recordData: { repoUrl?: string } = {}
data: DeepPartial<Deployment>
): Promise<Deployment> {
assert(data.project?.repository, 'Project repository not found');
log(
@ -407,13 +406,10 @@ export class Service {
assert(packageJSON.name, "name field doesn't exist in package.json");
if (!recordData.repoUrl) {
const { data: repoDetails } = await octokit.rest.repos.get({
const repoUrl = (await octokit.rest.repos.get({
owner,
repo
});
recordData.repoUrl = repoDetails.html_url;
}
})).data.html_url;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } =
@ -422,7 +418,7 @@ export class Service {
packageJSON,
appType: data.project!.template!,
commitHash: data.commitHash!,
repoUrl: recordData.repoUrl
repoUrl
});
// Update previous deployment with prod branch domain
@ -464,11 +460,23 @@ export class Service {
{
deployment: newDeployment,
appName: repo,
packageJsonName: packageJSON.name,
repository: recordData.repoUrl,
environmentVariables: environmentVariablesObj
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`
});
// To set project DNS
if (data.environment === Environment.Production) {
await this.registry.createApplicationDeploymentRequest(
{
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`
});
}
await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData });
return newDeployment;
@ -498,8 +506,6 @@ export class Service {
per_page: 1
});
const { data: repoDetails } = await octokit.rest.repos.get({ owner, repo });
// Create deployment with prod branch and latest commit
await this.createDeployment(user.id,
octokit,
@ -510,9 +516,6 @@ export class Service {
domain: null,
commitHash: latestCommit.sha,
commitMessage: latestCommit.commit.message
},
{
repoUrl: repoDetails.html_url
}
);
@ -555,8 +558,14 @@ export class Service {
}
async handleGitHubPush (data: GitPushEventPayload): Promise<void> {
const { repository, ref, head_commit: headCommit } = data;
log(`Handling GitHub push event from repository: ${repository.full_name}`);
const { repository, ref, head_commit: headCommit, deleted } = data;
if (deleted) {
log(`Branch ${ref} deleted for project ${repository.full_name}`);
return;
}
log(`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`);
const projects = await this.db.getProjects({
where: { repository: repository.full_name }
});

View File

@ -24,6 +24,7 @@ export interface GitPushEventPayload {
id: string;
message: string;
};
deleted: boolean;
}
export interface AppDeploymentRecordAttributes {

View File

@ -66,3 +66,5 @@ export const loadAndSaveData = async <Entity extends ObjectLiteral>(
return savedEntity;
};
export const sleep = async (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));