Documentation Index Fetch the complete documentation index at: https://docs.deployhub.cloud/llms.txt
Use this file to discover all available pages before exploring further.
DeployHub provides comprehensive build tracking and monitoring capabilities to help you understand your deployment pipeline and troubleshoot issues.
Build Model
Each build is tracked as a document in the Build collection:
// From build.model.js:3-25
const buildSchema = new mongoose . Schema ({
project: {
type: mongoose . Schema . Types . ObjectId ,
ref: "Project" ,
required: true ,
index: true
},
commitSha: String ,
status: {
type: String ,
enum: [ 'pending' , 'success' , 'failed' ],
default: 'pending'
},
startedAt: Date ,
finishedAt: Date ,
dockerImage: String ,
logUrl: String
}, { timestamps: true });
buildSchema . index ({ project: 1 , createdAt: - 1 });
Build Statuses:
pending - Build queued or in progress
success - Build completed successfully
failed - Build encountered an error
Builds are indexed by project and creation time for fast historical queries.
Build Lifecycle
1. Build Creation
A new build is created when deployment starts:
// From createDeployment.controller.js:153-156
const newBuild = new Model . Build ({
project: newProject . _id ,
commitSha: commitSha ,
});
await newBuild . save ({ validateBeforeSave: false });
2. Build Queuing
Build is added to BullMQ queue:
// From createDeployment.controller.js:201
buildqueue . add ( "buildqueue" , {
buildId: newBuild . _id . toString (),
projectId: newProject . _id . toString ()
});
3. Build Processing
Build worker picks up the job:
// From buildworker.js:34-41
await Model . Build . findByIdAndUpdate ( buildData . _id , {
status: "pending" ,
startedAt: new Date ()
});
await Model . Project . findByIdAndUpdate ( projectData . _id , {
status: "building"
});
4. Docker Build Logs
Build progress is streamed to stdout:
// From buildworker.js:109-121
await new Promise (( resolve , reject ) => {
docker . modem . followProgress (
tarStream ,
( err , res ) => ( err ? reject ( err ) : resolve ( res )),
( event ) => {
if ( event . stream ) process . stdout . write ( event . stream );
if ( event . error ) {
console . error ( "Docker build error:" , event . error );
reject ( new Error ( event . error ));
}
},
);
});
Example Build Output:
Step 1/8 : FROM node:20.19.5 AS build
---> abc123def456
Step 2/8 : WORKDIR /app
---> Running in xyz789
---> def456ghi789
Step 3/8 : COPY package*.json ./
---> 123abc456def
Step 4/8 : RUN npm ci
---> Running in 789xyz012
npm WARN deprecated package@1.0.0
added 1234 packages in 45s
5. Image Push Logs
Image push progress is also streamed:
// From buildworker.js:161-173
const pushStream = await image . push ({
authconfig: {
username: dockerusername ,
password: dockerpassword ,
},
});
await new Promise (( resolve , reject ) => {
docker . modem . followProgress (
pushStream ,
( err , res ) => ( err ? reject ( err ) : resolve ( res )),
( event ) => {
if ( event . stream ) process . stdout . write ( event . stream );
if ( event . error ) {
console . error ( "image push error:" , event . error );
reject ( new Error ( event . error ));
}
},
);
});
6. Build Completion
Successful builds update the database:
// From buildworker.js:236-240
await Model . Build . findByIdAndUpdate ( buildData . _id , {
status: "success" ,
finishedAt: new Date (),
dockerImage: imageName
});
7. Build Failure
Failed builds are marked accordingly:
// From buildworker.js:267-279
buildWorker . on ( "failed" , async ( job , err ) => {
await Model . Build . findByIdAndUpdate (
job . data . buildId ,
{ status: "failed" , finishedAt: new Date () },
{ validateBeforeSave: false },
);
await Model . Project . findByIdAndUpdate (
job . data . projectId ,
{ status: "failed-deploy" },
{ validateBeforeSave: false },
);
console . log ( `worker failed build on id ${ job . id } with error ${ err } ` );
});
Worker Event Logging
Build Worker Events
// From buildworker.js:259-284
buildWorker . on ( "active" , async ( job ) => {
console . log ( `worker start build working on id ${ job . id } ` );
});
buildWorker . on ( "completed" , async ( job ) => {
await deploymentQueue . add ( "deploymentQueue" , job . data );
});
buildWorker . on ( "failed" , async ( job , err ) => {
console . log ( `worker failed build on id ${ job . id } with error ${ err } ` );
});
Deployment Worker Events
// From deployworker.js:98-154
worker . on ( "completed" , async ( job ) => {
const { projectId } = job . data ;
const projectData = await Model . Project . findById ( projectId );
projectData . status = 'live' ;
await projectData . save ({ validateBeforeSave: false });
console . log ( `Deployment job ${ job . id } completed successfully.` );
});
worker . on ( "failed" , async ( job , err ) => {
const { projectId } = job . data ;
const projectData = await Model . Project . findById ( projectId );
projectData . status = 'failed-deploy' ;
await projectData . save ({ validateBeforeSave: false });
console . log ( `Deployment job ${ job . id } failed with error: ${ err . message } ` );
});
Redeployment Worker Events
// From reDeploy.worker.js:444-479
reDeployMentWorker . on ( "active" , async ( job ) => {
console . log ( `ReDeployment Worker started for project ID ${ job . data } ` );
});
reDeployMentWorker . on ( "completed" , async ( job ) => {
const project = await Model . Project . findById ( job . data );
project . status = "live" ;
await project . save ({ validateBeforeSave: false });
console . log ( `ReDeployment Worker completed for project ID ${ job . data } ` );
});
reDeployMentWorker . on ( "failed" , async ( job , err ) => {
const project = await Model . Project . findById ( job . data );
project . status = "failed-deploy" ;
await project . save ({ validateBeforeSave: false });
console . error ( `ReDeployment Worker failed for project ID ${ job . data } :` , err );
});
Retrieving Build History
Get All Builds for Project
// From Buildscontroller.js:4-29
export const getProjectBuilds = async ( req , res ) => {
const project = await Model . Project . findOne ({
_id: req . params . id ,
owner: req . user . _id ,
status: { $ne: 'deleted' },
}). select ( '_id totalBuilds' ). lean ();
if ( ! project ) {
return res . status ( 404 ). json ({
success: false ,
message: 'Project not found'
});
}
const builds = await Model . Build . find ({ project: req . params . id })
. select ( 'commitSha status startedAt finishedAt logUrl createdAt' )
. sort ({ createdAt: - 1 }) // Most recent first
. limit ( 50 )
. lean ();
res . status ( 200 ). json ({
success: true ,
total: project . totalBuilds || builds . length ,
builds ,
});
};
API Endpoint:
GET / api / projects / : id / builds
Response:
{
"success" : true ,
"total" : 15 ,
"builds" : [
{
"_id" : "507f1f77bcf86cd799439022" ,
"commitSha" : "a1b2c3d4e5f6" ,
"status" : "success" ,
"startedAt" : "2025-03-04T10:15:30.000Z" ,
"finishedAt" : "2025-03-04T10:17:45.000Z" ,
"logUrl" : null ,
"createdAt" : "2025-03-04T10:15:00.000Z"
},
{
"_id" : "507f1f77bcf86cd799439021" ,
"commitSha" : "f6e5d4c3b2a1" ,
"status" : "failed" ,
"startedAt" : "2025-03-03T14:20:10.000Z" ,
"finishedAt" : "2025-03-03T14:21:05.000Z" ,
"createdAt" : "2025-03-03T14:20:00.000Z"
}
]
}
Build history is limited to 50 most recent builds per project for performance.
Get Single Build Details
// From Buildscontroller.js:32-54
export const getBuildById = async ( req , res ) => {
const project = await Model . Project . findOne ({
_id: req . params . id ,
owner: req . user . _id ,
status: { $ne: 'deleted' },
}). select ( '_id' ). lean ();
if ( ! project ) {
return res . status ( 404 ). json ({
success: false ,
message: 'Project not found'
});
}
const build = await Model . Build . findOne ({
_id: req . params . buildId ,
project: req . params . id ,
}). select ( 'commitSha status startedAt finishedAt logUrl dockerImage createdAt' ). lean ();
if ( ! build ) {
return res . status ( 404 ). json ({
success: false ,
message: 'Build not found'
});
}
res . status ( 200 ). json ({ success: true , build });
};
API Endpoint:
GET / api / projects / : id / builds / : buildId
Response:
{
"success" : true ,
"build" : {
"_id" : "507f1f77bcf86cd799439022" ,
"commitSha" : "a1b2c3d4e5f6" ,
"status" : "success" ,
"startedAt" : "2025-03-04T10:15:30.000Z" ,
"finishedAt" : "2025-03-04T10:17:45.000Z" ,
"dockerImage" : "deployhub/507f1f77bcf86cd799439011:507f1f77bcf86cd799439022" ,
"logUrl" : null ,
"createdAt" : "2025-03-04T10:15:00.000Z"
}
}
Build Duration Calculation
Calculate build time from timestamps:
const buildDurationMs = new Date ( build . finishedAt ) - new Date ( build . startedAt );
const buildDurationSeconds = Math . floor ( buildDurationMs / 1000 );
const buildDurationMinutes = Math . floor ( buildDurationSeconds / 60 );
console . log ( `Build took ${ buildDurationMinutes } m ${ buildDurationSeconds % 60 } s` );
// Output: "Build took 2m 15s"
Container Logs
For Node.js applications, container logs can be retrieved:
// From deployworker.js:82
await container . logs ({ stdout: true , stderr: true });
Retrieving logs manually:
const container = docker . getContainer ( containerId );
const logs = await container . logs ({
stdout: true ,
stderr: true ,
tail: 100 , // Last 100 lines
timestamps: true
});
Build Statistics
Project model tracks total build count:
// From project.model.js:67-70
totalBuilds : {
type : Number ,
default : 0
}
Incremented on each build:
// From createDeployment.controller.js:135
newProject . totalBuilds += 1 ;
await newProject . save ({ validateBeforeSave: false });
Commit SHA Tracking
Each build stores the Git commit SHA:
// From createDeployment.controller.js:116-126
const response = await fetch (
`https://api.github.com/repos/ ${ owner } / ${ repo } /git/ref/heads/ ${ branchname } ` ,
{ headers }
);
const data = await response . json ();
commitSha = data ?. object ?. sha || null ;
const newBuild = new Model . Build ({
project: newProject . _id ,
commitSha: commitSha ,
});
Commit SHA enables intelligent redeployments - DeployHub checks if code has changed before rebuilding.
Redeployment Intelligence
Redeployment worker checks commit history:
// From reDeploy.worker.js:70-74
const isBuildFailed = buildData . status === "failed" ;
const isNewCommit = commitSha && buildData . commitSha !== commitSha ;
if ( isBuildFailed || isNewCommit ) {
// Build new image
} else {
// Reuse existing image
}
Rebuild triggers:
Previous build failed
New commit detected (SHA mismatch)
Reuse existing image when:
Same commit SHA
Previous build succeeded
Error Handling
Build errors are captured and logged:
// From buildworker.js:242-244
catch ( error ) {
console . log ( "error in build worker" , error );
throw error ;
}
Errors trigger the worker’s failed event, which:
Updates build status to failed
Updates project status to failed-deploy
Logs error details
Build Cleanup
Build artifacts are cleaned up automatically:
// From buildworker.js:245-251
finally {
const buildFilePath = path . join ( "builds" , job . data . buildId . toString ());
if ( fs . existsSync ( buildFilePath )) {
fs . rmSync ( buildFilePath , { recursive: true , force: true });
console . log ( "Cleaned up build files" );
}
}
Build directories are removed after processing to conserve disk space.
Monitoring Recommendations
Real-Time Monitoring
// Poll build status every 5 seconds
const pollBuild = async ( projectId , buildId ) => {
const response = await fetch ( `/api/projects/ ${ projectId } /builds/ ${ buildId } ` );
const { build } = await response . json ();
if ( build . status === 'pending' ) {
setTimeout (() => pollBuild ( projectId , buildId ), 5000 );
} else {
console . log ( 'Build completed:' , build . status );
}
};
Build Status Indicators
const getStatusColor = ( status ) => {
switch ( status ) {
case 'pending' : return 'yellow' ;
case 'success' : return 'green' ;
case 'failed' : return 'red' ;
default : return 'gray' ;
}
};
const getStatusIcon = ( status ) => {
switch ( status ) {
case 'pending' : return '⏳' ;
case 'success' : return '✅' ;
case 'failed' : return '❌' ;
default : return '❓' ;
}
};
Common Build Issues
Build Timeout
Builds may timeout if they take too long:
Optimize dependencies (use npm ci instead of npm install)
Reduce build output size
Check for infinite loops in build scripts
Out of Memory
Large builds may exceed memory limits:
Reduce concurrent build processes
Optimize webpack/vite configuration
Use smaller dependencies
Docker Build Errors
Common Docker issues:
Missing Dockerfile
Invalid build arguments
File permission issues
Network connectivity problems
Image Push Failures
Push errors usually indicate:
Docker Hub authentication issues
Network connectivity problems
Insufficient disk space
Registry rate limits
API Reference Summary
Get Project Builds
GET / api / projects / : id / builds
Returns up to 50 most recent builds.
Get Build Details
GET / api / projects / : id / builds / : buildId
Returns detailed information for a specific build.
Future Enhancements
Planned Features
Real-time WebSocket log streaming
Build log storage and retrieval
Build metrics and analytics
Build performance insights
Email notifications on build failure
Slack/Discord integration
Currently, logs are written to stdout/stderr. Log persistence to object storage is planned for future releases.