diff --git a/migrations/20241014165446-add-status-message-type-to-build.js b/migrations/20241014165446-add-status-message-type-to-build.js new file mode 100644 index 00000000..35884ed6 --- /dev/null +++ b/migrations/20241014165446-add-status-message-type-to-build.js @@ -0,0 +1,21 @@ +/* eslint-disable new-cap */ + +'use strict'; + +const prefix = process.env.DATASTORE_SEQUELIZE_PREFIX || ''; +const table = `${prefix}builds`; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.sequelize.transaction(async transaction => { + await queryInterface.addColumn( + table, + 'statusMessageType', + { + type: Sequelize.STRING(10) + }, + { transaction } + ); + }); + } +}; diff --git a/models/build.js b/models/build.js index 8d3818c4..dc6dd397 100644 --- a/models/build.js +++ b/models/build.js @@ -22,6 +22,7 @@ const STATUSES = [ 'COLLAPSED', // when the build is collapsed 'FROZEN' // when the build is frozen due to freeze window ]; +const STATUS_MESSAGE_TYPES = ['ERROR', 'WARN', 'INFO']; const MODEL = { id: Joi.number().integer().positive().description('Identifier of this build').example(123345), @@ -85,6 +86,12 @@ const MODEL = { .description('Status message to describe status of the build') .example('Build failed due to infrastructure error'), + statusMessageType: Joi.string() + .valid(...STATUS_MESSAGE_TYPES) + .max(10) + .description('Severity of the status message') + .example('WARN'), + stats: Joi.object() .keys({ queueEnterTime: Joi.string().isoDate().description('When this build enters queue'), @@ -158,6 +165,7 @@ module.exports = { 'eventId', 'environment', 'statusMessage', + 'statusMessageType', 'stats', 'buildClusterName', 'templateId', @@ -172,7 +180,9 @@ module.exports = { * @property update * @type {Joi} */ - update: Joi.object(mutate(MODEL, [], ['status', 'meta', 'statusMessage', 'stats'])).label('Update Build'), + update: Joi.object(mutate(MODEL, [], ['status', 'meta', 'statusMessage', 'statusMessageType', 'stats'])).label( + 'Update Build' + ), /** * Properties for Build that will be passed during a CREATE request @@ -223,6 +233,14 @@ module.exports = { */ allKeys: Object.keys(MODEL), + /** + * All the available status message type + * + * @property allStatusMessageTypes + * @type {Array} + */ + allStatusMessageTypes: STATUS_MESSAGE_TYPES, + /** * Tablename to be used in the datastore * diff --git a/test/data/build.update.yaml b/test/data/build.update.yaml index 1420231b..f8dde799 100644 --- a/test/data/build.update.yaml +++ b/test/data/build.update.yaml @@ -1,6 +1,7 @@ # Build Update Example status: FAILURE statusMessage: 'Build failed to start due to infrastructure error' +statusMessageType: 'ERROR' meta: yes: no stats: diff --git a/test/models/build.test.js b/test/models/build.test.js index d9849bf9..2849c469 100644 --- a/test/models/build.test.js +++ b/test/models/build.test.js @@ -58,6 +58,22 @@ describe('model build', () => { it('fails the get', () => { assert.isNotNull(validate('empty.yaml', models.build.get).error); }); + + // valid status message types + models.build.allStatusMessageTypes.forEach(messageType => { + it('validates the valid message types', () => { + assert.isNull(validate('build.get.yaml', models.build.get, { statusMessageType: messageType }).error); + }); + }); + + // invalid status message types + ['', 'error', 'warn', 'info', 'some_invalid_message_type'].forEach(messageType => { + it('validates the invalid message types', () => { + assert.isNotNull( + validate('build.get.yaml', models.build.get, { statusMessageType: messageType }).error + ); + }); + }); }); describe('steps', () => {