Andras Bacsai 142b83cc13
v1.0.7 (#32)
New features:
- Automatic error reporting (enabled by default)
- Increase build times by leveraging docker build caches
- 
Fixes:
- Fix error handling
- Fix vue autodetect
- Custom dockerfile is not the default

Others:
- Cleanup `logs-servers` collection, because old errors are not standardized
- New Traefik proxy version
- Standardized directory configurations
2021-04-19 09:46:05 +02:00

120 lines
4.7 KiB
JavaScript

const crypto = require('crypto')
const { cleanupTmp } = require('../../../libs/common')
const Deployment = require('../../../models/Deployment')
const ApplicationLog = require('../../../models/Logs/Application')
const ServerLog = require('../../../models/Logs/Server')
const { queueAndBuild } = require('../../../libs/applications')
const { setDefaultConfiguration, precheckDeployment } = require('../../../libs/applications/configuration')
const { docker } = require('../../../libs/docker')
const cloneRepository = require('../../../libs/applications/github/cloneRepository')
module.exports = async function (fastify) {
// TODO: Add this to fastify plugin
const postSchema = {
body: {
type: 'object',
properties: {
ref: { type: 'string' },
repository: {
type: 'object',
properties: {
id: { type: 'number' },
full_name: { type: 'string' }
},
required: ['id', 'full_name']
},
installation: {
type: 'object',
properties: {
id: { type: 'number' }
},
required: ['id']
}
},
required: ['ref', 'repository', 'installation']
}
}
fastify.post('/', { schema: postSchema }, async (request, reply) => {
let configuration
const hmac = crypto.createHmac('sha256', fastify.config.GITHUP_APP_WEBHOOK_SECRET)
const digest = Buffer.from('sha256=' + hmac.update(JSON.stringify(request.body)).digest('hex'), 'utf8')
const checksum = Buffer.from(request.headers['x-hub-signature-256'], 'utf8')
if (checksum.length !== digest.length || !crypto.timingSafeEqual(digest, checksum)) {
reply.code(500).send({ error: 'Invalid request' })
return
}
if (request.headers['x-github-event'] !== 'push') {
reply.code(500).send({ error: 'Not a push event.' })
return
}
try {
const services = (await docker.engine.listServices()).filter(r => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application')
configuration = services.find(r => {
if (request.body.ref.startsWith('refs')) {
const branch = request.body.ref.split('/')[2]
if (
JSON.parse(r.Spec.Labels.configuration).repository.id === request.body.repository.id &&
JSON.parse(r.Spec.Labels.configuration).repository.branch === branch
) {
return r
}
}
return null
})
if (!configuration) {
reply.code(500).send({ error: 'No configuration found.' })
return
}
configuration = setDefaultConfiguration(JSON.parse(configuration.Spec.Labels.configuration))
await cloneRepository(configuration)
const { foundService, imageChanged, configChanged, forceUpdate } = await precheckDeployment({ services, configuration })
if (foundService && !forceUpdate && !imageChanged && !configChanged) {
cleanupTmp(configuration.general.workdir)
reply.code(500).send({ message: 'Nothing changed, no need to redeploy.' })
return
}
const alreadyQueued = await Deployment.find({
repoId: configuration.repository.id,
branch: configuration.repository.branch,
organization: configuration.repository.organization,
name: configuration.repository.name,
domain: configuration.publish.domain,
progress: { $in: ['queued', 'inprogress'] }
})
if (alreadyQueued.length > 0) {
reply.code(200).send({ message: 'Already in the queue.' })
return
}
queueAndBuild(configuration, imageChanged)
reply.code(201).send({ message: 'Deployment queued.', nickname: configuration.general.nickname, name: configuration.build.container.name })
} catch (error) {
const { id, organization, name, branch } = configuration.repository
const { domain } = configuration.publish
const { deployId } = configuration.general
await Deployment.findOneAndUpdate(
{ repoId: id, branch, deployId, organization, name, domain },
{ repoId: id, branch, deployId, organization, name, domain, progress: 'failed' })
cleanupTmp(configuration.general.workdir)
if (error.name === 'Error') {
// Error during runtime
await new ApplicationLog({ repoId: id, branch, deployId, event: `[ERROR 😖]: ${error.stack}` }).save()
} else {
// Error in my code
const payload = { message: error.message, stack: error.stack, type: 'spaghetticode' }
if (error.message && error.stack) await new ServerLog(payload).save()
if (reply.sent) await new ApplicationLog({ repoId: id, branch, deployId, event: `[ERROR 😖]: ${error.stack}` }).save()
}
throw new Error(error)
}
})
}