diff --git a/node-packages/commons/src/api.ts b/node-packages/commons/src/api.ts index a85c462891..98e5b7c495 100644 --- a/node-packages/commons/src/api.ts +++ b/node-packages/commons/src/api.ts @@ -1367,11 +1367,15 @@ export const addDeployment = ( completed: string = null, priority: number = null, bulkId: string = null, - bulkName: string = null + bulkName: string = null, + sourceUser = null, + sourceType = null, ): Promise => graphqlapi.mutate( ` - ($name: String!, $status: DeploymentStatusType!, $created: String!, $environment: Int!, $id: Int, $remoteId: String, $started: String, $completed: String, $priority: Int, $bulkId: String, $bulkName: String) { + ($name: String!, $status: DeploymentStatusType!, $created: String!, $environment: Int!, $id: Int, $remoteId: String, + $started: String, $completed: String, $priority: Int, $bulkId: String, $bulkName: String, + $sourceUser: String, $sourceType: DeploymentSourceType) { addDeployment(input: { name: $name status: $status @@ -1384,6 +1388,8 @@ export const addDeployment = ( priority: $priority bulkId: $bulkId bulkName: $bulkName + sourceUser: $sourceUser + sourceType: $sourceType }) { ...${deploymentFragment} } @@ -1400,7 +1406,9 @@ export const addDeployment = ( completed, priority, bulkId, - bulkName + bulkName, + sourceUser, + sourceType, } ); @@ -1416,10 +1424,14 @@ export const addDeployment = ( service = null, command = null, execute = false, + sourceUser = null, + sourceType = null, ) => graphqlapi.mutate( ` - ($name: String!, $status: TaskStatusType!, $created: String!, $environment: Int!, $id: Int, $remoteId: String, $started: String, $completed: String, $service: String, $command: String, $execute: Boolean) { + ($name: String!, $status: TaskStatusType!, $created: String!, $environment: Int!, $id: Int, $remoteId: String, + $started: String, $completed: String, $service: String, $command: String, $execute: Boolean, + $sourceUser: String, $sourceType: TaskSourceType) { addTask(input: { name: $name status: $status @@ -1432,6 +1444,8 @@ export const addDeployment = ( service: $service command: $command execute: $execute + sourceUser: $sourceUser + sourceType: $sourceType }) { ...${taskFragment} } @@ -1449,6 +1463,8 @@ export const addDeployment = ( service, command, execute, + sourceUser, + sourceType, }, ); diff --git a/node-packages/commons/src/tasks.ts b/node-packages/commons/src/tasks.ts index 9af665f082..d45cabc1de 100644 --- a/node-packages/commons/src/tasks.ts +++ b/node-packages/commons/src/tasks.ts @@ -372,7 +372,9 @@ export const getControllerBuildData = async function(deployData: any) { buildPriority, bulkId, bulkName, - buildVariables + buildVariables, + sourceUser, + sourceType, } = deployData; var environmentName = makeSafe(branchName) @@ -593,7 +595,9 @@ export const getControllerBuildData = async function(deployData: any) { null, null, null, null, buildPriority, bulkId, - bulkName + bulkName, + sourceUser, + sourceType, ); } catch (error) { logger.error(`Could not save deployment for project ${lagoonProjectData.id}. Message: ${error}`); diff --git a/services/api/database/migrations/20240115000000_taskdeployment_source.js b/services/api/database/migrations/20240115000000_taskdeployment_source.js new file mode 100644 index 0000000000..3015a6f8e8 --- /dev/null +++ b/services/api/database/migrations/20240115000000_taskdeployment_source.js @@ -0,0 +1,31 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + return knex.schema + .alterTable('task', function (table) { + table.enu('source_type', ['api']); + table.string('source_user', 300); + }) + .alterTable('deployment', function (table) { + table.enu('source_type', ['api', 'webhook']); + table.string('source_user', 300); + }) +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function(knex) { + return knex.schema + .alterTable('task', (table) => { + table.dropColumn('source_type'); + table.dropColumn('source_user'); + }) + .alterTable('deployment', (table) => { + table.dropColumn('source_type'); + table.dropColumn('source_user'); + }) +}; \ No newline at end of file diff --git a/services/api/src/apolloServer.js b/services/api/src/apolloServer.js index 544c8ddb20..a2594f10ff 100644 --- a/services/api/src/apolloServer.js +++ b/services/api/src/apolloServer.js @@ -149,6 +149,7 @@ const apolloServer = new ApolloServer({ let keycloakUsersGroups = [] let groupRoleProjectIds = [] const keycloakGrant = grant + let legacyGrant = legacyCredentials ? legacyCredentials : null if (keycloakGrant) { keycloakUsersGroups = await User.User(modelClients).getAllGroupsForUser(keycloakGrant.access_token.content.sub); serviceAccount = await keycloakGrantManager.obtainFromClientCredentials(); @@ -164,6 +165,7 @@ const apolloServer = new ApolloServer({ ? keycloakHasPermission(grant, requestCache, modelClients, serviceAccount, currentUser, groupRoleProjectIds) : legacyHasPermission(legacyCredentials), keycloakGrant, + legacyGrant, requestCache, models: { UserModel: User.User(modelClients), @@ -233,6 +235,7 @@ const apolloServer = new ApolloServer({ let keycloakUsersGroups = [] let groupRoleProjectIds = [] const keycloakGrant = req.kauth ? req.kauth.grant : null + let legacyGrant = req.legacyCredentials ? req.legacyCredentials : null if (keycloakGrant) { keycloakUsersGroups = await User.User(modelClients).getAllGroupsForUser(keycloakGrant.access_token.content.sub); serviceAccount = await keycloakGrantManager.obtainFromClientCredentials(); @@ -284,6 +287,7 @@ const apolloServer = new ApolloServer({ hasPermission, keycloakGrant, requestCache, + legacyGrant, userActivityLogger: (message, meta) => { let defaultMeta = { user: req.kauth diff --git a/services/api/src/resolvers.js b/services/api/src/resolvers.js index 7225794fae..8c192b3174 100644 --- a/services/api/src/resolvers.js +++ b/services/api/src/resolvers.js @@ -317,6 +317,13 @@ const resolvers = { MAINTAINER: 'maintainer', OWNER: 'owner' }, + DeploymentSourceType: { + API: 'api', + WEBHOOK: 'webhook' + }, + TaskSourceType: { + API: 'api', + }, ProjectOrderType: { NAME: 'name', CREATED: 'created' diff --git a/services/api/src/resources/deployment/helpers.ts b/services/api/src/resources/deployment/helpers.ts index d6fdb8173f..6bd9c2c549 100644 --- a/services/api/src/resources/deployment/helpers.ts +++ b/services/api/src/resources/deployment/helpers.ts @@ -14,7 +14,21 @@ export const Helpers = (sqlClientPool: Pool) => { return R.prop(0, rows); }; + // getSourceUser can decode the keycloak or legacy grant into a username or issuer name + // this can then be stored against the deployment (or task) resource in the API when it is created + const getSourceUser =async (keycloakGrant, legacyGrant) => { + let sourceUser = "administrator" + if (keycloakGrant) { + sourceUser = keycloakGrant.access_token.content.email + } + if (legacyGrant) { + sourceUser = legacyGrant.iss + } + return sourceUser + } + return { + getSourceUser, getDeploymentById, getDeploymentByDeploymentInput: async deploymentInput => { const notEmpty = R.complement(R.anyPass([R.isNil, R.isEmpty])); diff --git a/services/api/src/resources/deployment/resolvers.ts b/services/api/src/resources/deployment/resolvers.ts index 8b119365c4..382977600c 100644 --- a/services/api/src/resources/deployment/resolvers.ts +++ b/services/api/src/resources/deployment/resolvers.ts @@ -340,10 +340,12 @@ export const addDeployment: ResolverFn = async ( priority, bulkId, bulkName, - buildStep + buildStep, + sourceUser, + sourceType, } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { const environment = await environmentHelpers( sqlClientPool @@ -352,6 +354,12 @@ export const addDeployment: ResolverFn = async ( project: environment.project }); + if (!sourceUser) { + sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) + } + if (!sourceType) { + sourceType = "API" + } const { insertId } = await query( sqlClientPool, Sql.insertDeployment({ @@ -366,7 +374,9 @@ export const addDeployment: ResolverFn = async ( priority, bulkId, bulkName, - buildStep + buildStep, + sourceType, + sourceUser, }) ); @@ -606,7 +616,7 @@ export const deployEnvironmentLatest: ResolverFn = async ( returnData } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { try { @@ -671,7 +681,7 @@ export const deployEnvironmentLatest: ResolverFn = async ( } let buildName = generateBuildId(); - + const sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) let deployData: { [key: string]: any; } = { @@ -682,6 +692,8 @@ export const deployEnvironmentLatest: ResolverFn = async ( bulkId: bulkId, bulkName: bulkName, buildVariables: buildVariables, + sourceType: "API", + sourceUser: sourceUser }; let meta: { [key: string]: any; @@ -808,7 +820,7 @@ export const deployEnvironmentBranch: ResolverFn = async ( returnData } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { const project = await projectHelpers(sqlClientPool).getProjectByProjectInput( projectInput @@ -825,6 +837,7 @@ export const deployEnvironmentBranch: ResolverFn = async ( } let buildName = generateBuildId(); + const sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const deployData = { type: 'branch', @@ -836,6 +849,8 @@ export const deployEnvironmentBranch: ResolverFn = async ( bulkId: bulkId, bulkName: bulkName, buildVariables: buildVariables, + sourceType: "API", + sourceUser: sourceUser }; const meta = { @@ -912,7 +927,7 @@ export const deployEnvironmentPullrequest: ResolverFn = async ( returnData } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { const branchName = `pr-${number}`; const project = await projectHelpers(sqlClientPool).getProjectByProjectInput( @@ -931,6 +946,7 @@ export const deployEnvironmentPullrequest: ResolverFn = async ( let buildName = generateBuildId(); + const sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const deployData = { type: 'pullrequest', projectName: project.name, @@ -946,6 +962,8 @@ export const deployEnvironmentPullrequest: ResolverFn = async ( bulkId: bulkId, bulkName: bulkName, buildVariables: buildVariables, + sourceType: "API", + sourceUser: sourceUser }; const meta = { @@ -1018,7 +1036,7 @@ export const deployEnvironmentPromote: ResolverFn = async ( returnData } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { const destProject = await projectHelpers( sqlClientPool @@ -1056,6 +1074,7 @@ export const deployEnvironmentPromote: ResolverFn = async ( let buildName = generateBuildId(); + const sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const deployData = { type: 'promote', projectName: destProject.name, @@ -1066,6 +1085,8 @@ export const deployEnvironmentPromote: ResolverFn = async ( bulkId: bulkId, bulkName: bulkName, buildVariables: buildVariables, + sourceType: "API", + sourceUser: sourceUser }; const meta = { @@ -1129,7 +1150,7 @@ export const deployEnvironmentPromote: ResolverFn = async ( export const switchActiveStandby: ResolverFn = async ( root, { input: { project: projectInput } }, - { sqlClientPool, hasPermission } + { sqlClientPool, hasPermission, keycloakGrant, legacyGrant } ) => { const project = await projectHelpers(sqlClientPool).getProjectByProjectInput( projectInput @@ -1227,6 +1248,8 @@ export const switchActiveStandby: ResolverFn = async ( }; // try it now + const sourceUser = await Helpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) + const sourceType = "API" try { // add a task into the environment var date = new Date(); @@ -1242,7 +1265,9 @@ export const switchActiveStandby: ResolverFn = async ( null, '', '', - false + false, + sourceUser, + sourceType, ); data.task.id = sourceTaskData.addTask.id.toString(); diff --git a/services/api/src/resources/deployment/sql.ts b/services/api/src/resources/deployment/sql.ts index 9a44d8e263..e84e942d36 100644 --- a/services/api/src/resources/deployment/sql.ts +++ b/services/api/src/resources/deployment/sql.ts @@ -23,6 +23,8 @@ export const Sql = { bulkId, bulkName, buildStep, + sourceType, + sourceUser, }: { id: number, name: string, @@ -36,6 +38,8 @@ export const Sql = { bulkId: string, bulkName: string, buildStep: string, + sourceType?: string, + sourceUser?: string, }) => knex('deployment') .insert({ @@ -51,6 +55,8 @@ export const Sql = { bulkId, bulkName, buildStep, + sourceType, + sourceUser, }) .toString(), deleteDeployment: (id: number) => diff --git a/services/api/src/resources/index.ts b/services/api/src/resources/index.ts index f1450e4d53..52c6368bd1 100644 --- a/services/api/src/resources/index.ts +++ b/services/api/src/resources/index.ts @@ -12,6 +12,7 @@ export interface ResolverFn { sqlClientPool: Pool, hasPermission: hasPermission, keycloakGrant: any | null, + legacyGrant: any | null, userActivityLogger: any | null, models: { UserModel, diff --git a/services/api/src/resources/task/helpers.ts b/services/api/src/resources/task/helpers.ts index baa0e317d6..d3243810d3 100644 --- a/services/api/src/resources/task/helpers.ts +++ b/services/api/src/resources/task/helpers.ts @@ -9,6 +9,7 @@ import { Sql } from './sql'; import { Sql as projectSql } from '../project/sql'; import { Sql as environmentSql } from '../environment/sql'; import { Helpers as environmentHelpers } from '../environment/helpers'; +import { logger } from '../../loggers/logger'; export const Helpers = (sqlClientPool: Pool, hasPermission) => { const getTaskById = async (TaskID: number) => { @@ -47,7 +48,9 @@ export const Helpers = (sqlClientPool: Pool, hasPermission) => { deployTokenInjection, projectKeyInjection, adminOnlyView, - execute + execute, + sourceUser, + sourceType }: { id?: number; name: string; @@ -64,6 +67,8 @@ export const Helpers = (sqlClientPool: Pool, hasPermission) => { projectKeyInjection: boolean; adminOnlyView: boolean; execute: boolean; + sourceUser: string; + sourceType: string; }) => { const { insertId } = await query( sqlClientPool, @@ -82,6 +87,8 @@ export const Helpers = (sqlClientPool: Pool, hasPermission) => { projectKeyInjection, adminOnlyView, remoteId, + sourceUser, + sourceType, }), ); diff --git a/services/api/src/resources/task/resolvers.ts b/services/api/src/resources/task/resolvers.ts index b5949e180a..4b7f5edb37 100644 --- a/services/api/src/resources/task/resolvers.ts +++ b/services/api/src/resources/task/resolvers.ts @@ -11,6 +11,7 @@ import { Helpers } from './helpers'; import { Filters } from './filters'; import { Helpers as environmentHelpers } from '../environment/helpers'; import { Helpers as projectHelpers } from '../project/helpers'; +import { Helpers as deploymentHelpers } from '../deployment/helpers'; import { Validators as envValidators } from '../environment/validators'; import S3 from 'aws-sdk/clients/s3'; import sha1 from 'sha1'; @@ -238,10 +239,12 @@ export const addTask: ResolverFn = async ( deployTokenInjection, projectKeyInjection, adminOnlyView, - execute: executeRequest + execute: executeRequest, + sourceType, + sourceUser, } }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environment); const envPerm = await environmentHelpers(sqlClientPool).getEnvironmentById( @@ -263,6 +266,13 @@ export const addTask: ResolverFn = async ( let taskName = generateTaskName() + if (!sourceUser) { + sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) + } + if (!sourceType) { + sourceType = "API" + } + userActivityLogger(`User added task '${name}'`, { project: '', event: 'api:addTask', @@ -279,7 +289,9 @@ export const addTask: ResolverFn = async ( service, command, remoteId, - execute: executeRequest + execute: executeRequest, + sourceUser, + sourceType, } } }); @@ -299,7 +311,9 @@ export const addTask: ResolverFn = async ( deployTokenInjection, projectKeyInjection, adminOnlyView, - execute + execute, + sourceUser, + sourceType }); return taskData; @@ -483,7 +497,7 @@ export const updateTask: ResolverFn = async ( export const taskDrushArchiveDump: ResolverFn = async ( root, { environment: environmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environmentId); await envValidators(sqlClientPool).environmentHasService( @@ -513,6 +527,7 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ } }); + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: 'Drush archive-dump', taskName: generateTaskName(), @@ -522,7 +537,9 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -531,7 +548,7 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ export const taskDrushSqlDump: ResolverFn = async ( root, { environment: environmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environmentId); await envValidators(sqlClientPool).environmentHasService( @@ -562,6 +579,7 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ } }); + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: 'Drush sql-dump', taskName: generateTaskName(), @@ -571,7 +589,9 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -580,7 +600,7 @@ TOKEN="$(ssh -p `+"${LAGOON_CONFIG_TOKEN_PORT:-$TASK_SSH_PORT}"+` -t lagoon@`+"$ export const taskDrushCacheClear: ResolverFn = async ( root, { environment: environmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environmentId); await envValidators(sqlClientPool).environmentHasService( @@ -613,6 +633,7 @@ export const taskDrushCacheClear: ResolverFn = async ( } }); + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: 'Drush cache-clear', taskName: generateTaskName(), @@ -622,7 +643,9 @@ export const taskDrushCacheClear: ResolverFn = async ( deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -631,7 +654,7 @@ export const taskDrushCacheClear: ResolverFn = async ( export const taskDrushCron: ResolverFn = async ( root, { environment: environmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environmentId); await envValidators(sqlClientPool).environmentHasService( @@ -653,6 +676,7 @@ export const taskDrushCron: ResolverFn = async ( } }); + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: 'Drush cron', taskName: generateTaskName(), @@ -662,7 +686,9 @@ export const taskDrushCron: ResolverFn = async ( deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -674,7 +700,7 @@ export const taskDrushSqlSync: ResolverFn = async ( sourceEnvironment: sourceEnvironmentId, destinationEnvironment: destinationEnvironmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(sourceEnvironmentId); await envValidators(sqlClientPool).environmentExists( @@ -725,6 +751,7 @@ export const taskDrushSqlSync: ResolverFn = async ( if [[ ! "" = "$(drush | grep 'lagoon:aliases')" ]]; then LAGOON_ALIAS_PREFIX="lagoon.\${LAGOON_PROJECT}-"; fi && \ drush -y sql-sync @\${LAGOON_ALIAS_PREFIX}${sourceEnvironment.name} @self`; + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: `Sync DB ${sourceEnvironment.name} -> ${destinationEnvironment.name}`, taskName: generateTaskName(), @@ -734,7 +761,9 @@ export const taskDrushSqlSync: ResolverFn = async ( deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -746,7 +775,7 @@ export const taskDrushRsyncFiles: ResolverFn = async ( sourceEnvironment: sourceEnvironmentId, destinationEnvironment: destinationEnvironmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(sourceEnvironmentId); await envValidators(sqlClientPool).environmentExists( @@ -797,6 +826,7 @@ export const taskDrushRsyncFiles: ResolverFn = async ( if [[ ! "" = "$(drush | grep 'lagoon:aliases')" ]]; then LAGOON_ALIAS_PREFIX="lagoon.\${LAGOON_PROJECT}-"; fi && \ drush -y rsync @\${LAGOON_ALIAS_PREFIX}${sourceEnvironment.name}:%files @self:%files -- --omit-dir-times --no-perms --no-group --no-owner --chmod=ugo=rwX`; + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: `Sync files ${sourceEnvironment.name} -> ${destinationEnvironment.name}`, taskName: generateTaskName(), @@ -806,7 +836,9 @@ export const taskDrushRsyncFiles: ResolverFn = async ( deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; @@ -815,7 +847,7 @@ export const taskDrushRsyncFiles: ResolverFn = async ( export const taskDrushUserLogin: ResolverFn = async ( root, { environment: environmentId }, - { sqlClientPool, hasPermission, userActivityLogger } + { sqlClientPool, hasPermission, userActivityLogger, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environmentId); await envValidators(sqlClientPool).environmentHasService( @@ -837,6 +869,7 @@ export const taskDrushUserLogin: ResolverFn = async ( } }); + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: 'Drush uli', taskName: generateTaskName(), @@ -846,7 +879,9 @@ export const taskDrushUserLogin: ResolverFn = async ( deployTokenInjection: false, projectKeyInjection: false, adminOnlyView: false, - execute: true + execute: true, + sourceType: "API", + sourceUser: sourceUser, }); return taskData; diff --git a/services/api/src/resources/task/sql.ts b/services/api/src/resources/task/sql.ts index ef110f987c..d287ad879f 100644 --- a/services/api/src/resources/task/sql.ts +++ b/services/api/src/resources/task/sql.ts @@ -28,6 +28,8 @@ export const Sql = { type = null, advanced_image = null, advanced_payload = null, + sourceUser = null, + sourceType = null, }: { id: number; name: string; @@ -46,6 +48,8 @@ export const Sql = { type?: string; advanced_image?: string; advanced_payload?: string; + sourceUser?: string; + sourceType?: string; }) => knex('task') .insert({ @@ -66,6 +70,8 @@ export const Sql = { type, advanced_image, advanced_payload, + sourceUser, + sourceType, }) .toString(), deleteTask: (id: number) => diff --git a/services/api/src/resources/task/task_definition_resolvers.ts b/services/api/src/resources/task/task_definition_resolvers.ts index 20da4cf532..50b2a4129d 100644 --- a/services/api/src/resources/task/task_definition_resolvers.ts +++ b/services/api/src/resources/task/task_definition_resolvers.ts @@ -5,6 +5,7 @@ import { Helpers } from './helpers'; import { Filters } from './filters'; import { Helpers as environmentHelpers } from '../environment/helpers'; import { Helpers as projectHelpers } from '../project/helpers'; +import { Helpers as deploymentHelpers } from '../deployment/helpers'; import { Validators as envValidators } from '../environment/validators'; import { TaskRegistration, @@ -529,8 +530,8 @@ const getProjectByEnvironmentIdOrProjectId = async ( export const invokeRegisteredTask = async ( root, - { advancedTaskDefinition, environment, argumentValues }, - { sqlClientPool, hasPermission, models, keycloakGroups } + { advancedTaskDefinition, environment, argumentValues, sourceType }, + { sqlClientPool, hasPermission, models, keycloakGroups, keycloakGrant, legacyGrant } ) => { await envValidators(sqlClientPool).environmentExists(environment); @@ -603,7 +604,10 @@ export const invokeRegisteredTask = async ( } taskCommand += `${task.command}`; - + if (!sourceType) { + sourceType = "API" + } + const sourceUser = await deploymentHelpers(sqlClientPool).getSourceUser(keycloakGrant, legacyGrant) const taskData = await Helpers(sqlClientPool, hasPermission).addTask({ name: task.name, taskName: generateTaskName(), @@ -613,7 +617,9 @@ export const invokeRegisteredTask = async ( deployTokenInjection: task.deployTokenInjection, projectKeyInjection: task.projectKeyInjection, adminOnlyView: task.adminOnlyView, - execute: true + execute: true, + sourceType: sourceType, + sourceUser: sourceUser, }); return taskData; break; diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index 96ba832ee4..835ec5d846 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -132,6 +132,15 @@ const typeDefs = gql` GUEST } + enum DeploymentSourceType { + API + WEBHOOK + } + + enum TaskSourceType { + API + } + scalar SeverityScore type AdvancedTaskDefinitionArgument { @@ -1008,6 +1017,15 @@ const typeDefs = gql` bulkId: String bulkName: String buildStep: String + """ + The username or email address that triggered this deployment. + For webhook requests, the username or email address will attempt to be extracted from the webhook payload depending on the source of the webhook + """ + sourceUser: String + """ + The source of this task from the available deplyoment trigger types + """ + sourceType: DeploymentSourceType } type Insight { @@ -1047,6 +1065,14 @@ const typeDefs = gql` remoteId: String logs: String files: [File] + """ + The username or email address that triggered the task. + """ + sourceUser: String + """ + The source of this task from the available task trigger types + """ + sourceType: TaskSourceType } type AdvancedTask { @@ -1616,6 +1642,8 @@ const typeDefs = gql` bulkId: String bulkName: String buildStep: String + sourceUser: String + sourceType: DeploymentSourceType } input DeleteDeploymentInput { @@ -1657,6 +1685,8 @@ const typeDefs = gql` command: String remoteId: String execute: Boolean + sourceUser: String + sourceType: TaskSourceType } diff --git a/services/webhooks2tasks/src/handlers/bitbucketPullRequestUpdated.ts b/services/webhooks2tasks/src/handlers/bitbucketPullRequestUpdated.ts index 26e935d1be..66b1957b8a 100644 --- a/services/webhooks2tasks/src/handlers/bitbucketPullRequestUpdated.ts +++ b/services/webhooks2tasks/src/handlers/bitbucketPullRequestUpdated.ts @@ -47,7 +47,12 @@ export async function bitbucketPullRequestUpdated(webhook: WebhookRequestData, p } let buildName = generateBuildId(); - + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.pullrequest.author.username) { + sourceUser = body.pullrequest.author.username + } const data: deployData = { repoName: body.repository.full_name, repoUrl: body.repository.links.html.href, @@ -61,7 +66,9 @@ export async function bitbucketPullRequestUpdated(webhook: WebhookRequestData, p baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.pullrequest.id}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/bitbucketPush.ts b/services/webhooks2tasks/src/handlers/bitbucketPush.ts index 0b4898e747..451dc56e80 100644 --- a/services/webhooks2tasks/src/handlers/bitbucketPush.ts +++ b/services/webhooks2tasks/src/handlers/bitbucketPush.ts @@ -42,12 +42,20 @@ export async function bitbucketPush(webhook: WebhookRequestData, project: Projec let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.actor.username) { + sourceUser = body.actor.username + } const data: deployData = { projectName: project.name, type: 'branch', branchName: branchName, sha: sha, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } let logMessage = `\`<${body.push.changes[0].new.links.html.href}>\`` diff --git a/services/webhooks2tasks/src/handlers/giteaPullRequestOpened.ts b/services/webhooks2tasks/src/handlers/giteaPullRequestOpened.ts index 238dc054a6..f2559771d5 100644 --- a/services/webhooks2tasks/src/handlers/giteaPullRequestOpened.ts +++ b/services/webhooks2tasks/src/handlers/giteaPullRequestOpened.ts @@ -48,6 +48,12 @@ export async function giteaPullRequestOpened(webhook: WebhookRequestData, projec let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { repoUrl: body.repository.html_url, repoName: body.repository.full_name, @@ -61,7 +67,9 @@ export async function giteaPullRequestOpened(webhook: WebhookRequestData, projec baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.number}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/giteaPullRequestSynchronize.ts b/services/webhooks2tasks/src/handlers/giteaPullRequestSynchronize.ts index 280dd7982c..aca515674e 100644 --- a/services/webhooks2tasks/src/handlers/giteaPullRequestSynchronize.ts +++ b/services/webhooks2tasks/src/handlers/giteaPullRequestSynchronize.ts @@ -66,6 +66,12 @@ export async function giteaPullRequestSynchronize(webhook: WebhookRequestData, p let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { repoName: body.repository.full_name, repoUrl: body.repository.html_url, @@ -79,7 +85,9 @@ export async function giteaPullRequestSynchronize(webhook: WebhookRequestData, p baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.number}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/giteaPush.ts b/services/webhooks2tasks/src/handlers/giteaPush.ts index c513c840b6..bbe0390891 100644 --- a/services/webhooks2tasks/src/handlers/giteaPush.ts +++ b/services/webhooks2tasks/src/handlers/giteaPush.ts @@ -43,12 +43,20 @@ export async function giteaPush(webhook: WebhookRequestData, project: Project) { let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { projectName: project.name, type: 'branch', branchName: branchName, sha: sha, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } let logMessage = `\`<${body.repository.html_url}/tree/${meta.branch}|${meta.branch}>\`` diff --git a/services/webhooks2tasks/src/handlers/githubPullRequestOpened.ts b/services/webhooks2tasks/src/handlers/githubPullRequestOpened.ts index 134e7942f6..d110fbe73d 100644 --- a/services/webhooks2tasks/src/handlers/githubPullRequestOpened.ts +++ b/services/webhooks2tasks/src/handlers/githubPullRequestOpened.ts @@ -48,6 +48,12 @@ export async function githubPullRequestOpened(webhook: WebhookRequestData, proje let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { repoUrl: body.repository.html_url, repoName: body.repository.full_name, @@ -61,7 +67,9 @@ export async function githubPullRequestOpened(webhook: WebhookRequestData, proje baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.number}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/githubPullRequestSynchronize.ts b/services/webhooks2tasks/src/handlers/githubPullRequestSynchronize.ts index da5e8705e4..5223e44013 100644 --- a/services/webhooks2tasks/src/handlers/githubPullRequestSynchronize.ts +++ b/services/webhooks2tasks/src/handlers/githubPullRequestSynchronize.ts @@ -66,6 +66,12 @@ export async function githubPullRequestSynchronize(webhook: WebhookRequestData, let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { repoName: body.repository.full_name, repoUrl: body.repository.html_url, @@ -79,7 +85,9 @@ export async function githubPullRequestSynchronize(webhook: WebhookRequestData, baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.number}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/githubPush.ts b/services/webhooks2tasks/src/handlers/githubPush.ts index 9641582dbf..c186ff61bf 100644 --- a/services/webhooks2tasks/src/handlers/githubPush.ts +++ b/services/webhooks2tasks/src/handlers/githubPush.ts @@ -42,12 +42,20 @@ export async function githubPush(webhook: WebhookRequestData, project: Project) let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.sender.login) { + sourceUser = body.sender.login + } const data: deployData = { projectName: project.name, type: 'branch', branchName: branchName, sha: sha, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } let logMessage = `\`<${body.repository.html_url}/tree/${meta.branch}|${meta.branch}>\`` diff --git a/services/webhooks2tasks/src/handlers/gitlabPullRequestOpened.ts b/services/webhooks2tasks/src/handlers/gitlabPullRequestOpened.ts index 8df6178ac3..97fc822df7 100644 --- a/services/webhooks2tasks/src/handlers/gitlabPullRequestOpened.ts +++ b/services/webhooks2tasks/src/handlers/gitlabPullRequestOpened.ts @@ -48,6 +48,12 @@ export async function gitlabPullRequestOpened(webhook: WebhookRequestData, proje let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.user.username) { + sourceUser = body.user.username + } const data: deployData = { repoUrl: body.object_attributes.target.web_url, repoName: body.object_attributes.target.name, @@ -61,7 +67,9 @@ export async function gitlabPullRequestOpened(webhook: WebhookRequestData, proje baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.object_attributes.iid}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/gitlabPullRequestUpdated.ts b/services/webhooks2tasks/src/handlers/gitlabPullRequestUpdated.ts index ffa93d6898..7b7004c181 100644 --- a/services/webhooks2tasks/src/handlers/gitlabPullRequestUpdated.ts +++ b/services/webhooks2tasks/src/handlers/gitlabPullRequestUpdated.ts @@ -48,6 +48,12 @@ export async function gitlabPullRequestUpdated(webhook: WebhookRequestData, proj let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.user.username) { + sourceUser = body.user.username + } const data: deployData = { repoUrl: body.object_attributes.target.web_url, repoName: body.object_attributes.target.name, @@ -61,7 +67,9 @@ export async function gitlabPullRequestUpdated(webhook: WebhookRequestData, proj baseBranchName: baseBranchName, baseSha: baseSha, branchName: `pr-${body.object_attributes.iid}`, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } try { diff --git a/services/webhooks2tasks/src/handlers/gitlabPush.ts b/services/webhooks2tasks/src/handlers/gitlabPush.ts index af249a3e42..a89fa3452f 100644 --- a/services/webhooks2tasks/src/handlers/gitlabPush.ts +++ b/services/webhooks2tasks/src/handlers/gitlabPush.ts @@ -43,12 +43,20 @@ export async function gitlabPush(webhook: WebhookRequestData, project: Project) let buildName = generateBuildId(); + // try get the user from the webhook payload + // otherwise just use "webhook" as the trigger user + let sourceUser = "webhook" + if (body.user_username) { + sourceUser = body.user_username + } const data: deployData = { projectName: project.name, type: 'branch', branchName: branchName, sha: sha, - buildName: buildName + buildName: buildName, + sourceUser: sourceUser, + sourceType: "WEBHOOK", } let logMessage = `\`<${body.project.http_url}/tree/${meta.branch}|${meta.branch}>\`` diff --git a/services/webhooks2tasks/src/types.ts b/services/webhooks2tasks/src/types.ts index d7a307a642..98bd8eaaa3 100644 --- a/services/webhooks2tasks/src/types.ts +++ b/services/webhooks2tasks/src/types.ts @@ -32,6 +32,8 @@ export interface deployData { buildPriority?: string, bulkId?: string, buildVariables?: any, + sourceUser?: string, + sourceType?: string, }; export interface WebhookRequestData { diff --git a/tests/tasks/api/deploy-environment-latest.gql b/tests/tasks/api/deploy-environment-latest.gql new file mode 100644 index 0000000000..f72bf9d48d --- /dev/null +++ b/tests/tasks/api/deploy-environment-latest.gql @@ -0,0 +1,10 @@ +mutation deployEnvironmentLatest { + deployEnvironmentLatest(input:{ + environment:{ + name: "{{ branch }}" + project:{ + name: "{{ project }}" + } + }, returnData: true + }) +} diff --git a/tests/tasks/api/deploy-environment-latest.yaml b/tests/tasks/api/deploy-environment-latest.yaml new file mode 100644 index 0000000000..1bcb6c85bd --- /dev/null +++ b/tests/tasks/api/deploy-environment-latest.yaml @@ -0,0 +1,72 @@ +- name: "Start deployEnvironmentLatest (no SHA) loop with 3 retries" + block: + - ansible.builtin.include_tasks: refresh-token.yaml + - name: "Set the retry count to {{ retry_count }}" + set_fact: + retry_count: "{{ 0 if retry_count is undefined else retry_count|int + 1 }}" + - name: "{{ testname }} - POST api deployEnvironmentLatest with target git branch {{ branch }} and project {{ project }} (no sha) to {{ graphql_url }}" + uri: + url: "{{ graphql_url }}" + method: POST + headers: + Authorization: "Bearer {{ token }}" + body_format: json + return_content: true + body: + query: '{{ lookup("template", "./deploy-environment-latest.gql") }}' + #body: '{ "query": "mutation($branchName: String!, $projectName: String!) {deployEnvironmentLatest(input:{branchName:$branchName,project:{name:$projectName}})}", "variables": {"branchName":"{{ branch }}","projectName":"{{ project }}"}}' + register: apiresponse + - name: Print apiresponse + ansible.builtin.debug: + msg: "api response: {{ apiresponse }}" + - fail: + msg: "unsuccessful deploy" + when: apiresponse.json.data.deployEnvironmentLatest is not match("lagoon-build") + # - name: Get the build pod name + # kubernetes.core.k8s_info: + # kind: Pod + # wait: yes + # namespace: "{{ namespace }}" + # label_selectors: + # - lagoon.sh/jobType = build + # field_selectors: + # - status.phase=Running + # wait_sleep: 1 + # wait_timeout: 60 + # register: build_pod + # - name: Print build_pod + # ansible.builtin.debug: + # msg: "build_pod: {{ build_pod.resources[0].metadata.name }} {{ build_pod.resources[0].status.phase }}" + - name: Wait until the build pod is completed + kubernetes.core.k8s_info: + kind: Pod + wait: yes + name: "{{ apiresponse.json.data.deployEnvironmentLatest }}" + namespace: "{{ namespace }}" + label_selectors: + - lagoon.sh/jobType = build + field_selectors: + - status.phase=Succeeded + wait_condition: + type: Ready + reason: PodCompleted + status: "False" + wait_sleep: 10 + wait_timeout: 600 + register: build_complete + - name: Print build_complete + ansible.builtin.debug: + msg: "build_complete: {{ build_complete.resources[0].metadata.name }} {{ build_complete.resources[0].status.phase }}" + - name: "Set the retry count back to 0 when successful" + set_fact: + retry_count: 0 + rescue: + - fail: + msg: Ended after 3 retries + when: retry_count|int == 3 + - name: Pause for retry + pause: + seconds: 10 + - debug: + msg: "Failed to connect - Retrying..." + - include_tasks: ./deploy-environment-latest.yaml diff --git a/tests/tasks/api/get-latest-deployment-source.gql b/tests/tasks/api/get-latest-deployment-source.gql new file mode 100644 index 0000000000..2244afc675 --- /dev/null +++ b/tests/tasks/api/get-latest-deployment-source.gql @@ -0,0 +1,19 @@ +query environmentByKubernetesNamespaceName { + environmentByKubernetesNamespaceName( + kubernetesNamespaceName: "{{ namespace }}" + ){ + deployments(limit: 1){ + id + name + status + bulkId + bulkName + priority + started + created + completed + sourceUser + sourceType + } + } +} \ No newline at end of file diff --git a/tests/tasks/api/get-latest-deployment-source.yaml b/tests/tasks/api/get-latest-deployment-source.yaml new file mode 100644 index 0000000000..62fd476bc6 --- /dev/null +++ b/tests/tasks/api/get-latest-deployment-source.yaml @@ -0,0 +1,54 @@ +- name: "{{ testname }} - Verify that source user and type are correct" + block: + - ansible.builtin.include_tasks: admin-token.yaml + - name: "{{ testname }} - POST api check latest deployment {{ graphql_url }}" + uri: + url: "{{ graphql_url }}" + method: POST + headers: + Authorization: "Bearer {{ admin_token }}" + body_format: json + body: + query: '{{ lookup("template", "./get-latest-deployment-source.gql") }}' + register: apiresponse + until: + - apiresponse.json.data.environmentByKubernetesNamespaceName.deployments[0].status is defined + retries: 30 + delay: 10 + + - ansible.builtin.include_tasks: admin-token.yaml + - name: "{{ testname }} - POST api check latest deployment {{ graphql_url }}" + uri: + url: "{{ graphql_url }}" + method: POST + headers: + Authorization: "Bearer {{ admin_token }}" + body_format: json + body: + query: '{{ lookup("template", "./get-latest-deployment-source.gql") }}' + register: apiresponse + + - name: "{{ testname }} - POST api trigger bulk deployment for environments to {{ graphql_url }}" + debug: + msg: "api response: {{ apiresponse.json }}" + + - ansible.builtin.include_tasks: admin-token.yaml + - name: "{{ testname }} - POST api check latest deployment source user and type are correct {{ graphql_url }}" + uri: + url: "{{ graphql_url }}" + method: POST + headers: + Authorization: "Bearer {{ admin_token }}" + body_format: json + body: + query: '{{ lookup("template", "./get-latest-deployment-source.gql") }}' + register: apiresponse + until: + - apiresponse.json.data.environmentByKubernetesNamespaceName.deployments[0].sourceUser == sourceUser + - apiresponse.json.data.environmentByKubernetesNamespaceName.deployments[0].sourceType == sourceType + retries: 60 + delay: 10 + + - name: "{{ testname }} - POST api trigger bulk deployment for environments to {{ graphql_url }}" + debug: + msg: "api response: {{ apiresponse.json }}" diff --git a/tests/tests/api/deploy-pullrequest.yaml b/tests/tests/api/deploy-pullrequest.yaml index 89cc96d19a..14b3522e4a 100644 --- a/tests/tests/api/deploy-pullrequest.yaml +++ b/tests/tests/api/deploy-pullrequest.yaml @@ -45,6 +45,15 @@ tasks: - ansible.builtin.include_tasks: ../../tasks/api/deploy-pullrequest.yaml +- name: "{{ testname }} - api check deployment source user and type for deploy environment" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-pr-1" + sourceUser: "ci-customer-user-rsa@example.com" + sourceType: "API" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml - ansible.builtin.import_playbook: ../../checks/check-pullrequest.yaml vars: diff --git a/tests/tests/features/promote.yaml b/tests/tests/features/promote.yaml index e4af587993..5987ba62cf 100644 --- a/tests/tests/features/promote.yaml +++ b/tests/tests/features/promote.yaml @@ -35,6 +35,16 @@ tasks: - ansible.builtin.include_tasks: ../../tasks/api/promote.yaml +- name: "{{ testname }} - api check deployment source user and type" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-{{ promote_environment | regex_replace('/', '-') }}" + sourceUser: "test-suite" + sourceType: "API" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml + - ansible.builtin.import_playbook: ../../checks/check-branch-sha.yaml vars: expected_head: "{{ current_head }}" diff --git a/tests/tests/github/branch.yaml b/tests/tests/github/branch.yaml index 74b0e3724f..b3b26bc564 100644 --- a/tests/tests/github/branch.yaml +++ b/tests/tests/github/branch.yaml @@ -40,6 +40,16 @@ tasks: - ansible.builtin.include_tasks: ../../tasks/webhook-github/push.yaml +- name: "{{ testname }} - api check deployment source user and type" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-{{ branch | regex_replace('/', '-') }}" + sourceUser: "Schnitzel" + sourceType: "WEBHOOK" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml + - ansible.builtin.import_playbook: ../../checks/check-branch-sha.yaml vars: expected_head: "{{ current_head }}" diff --git a/tests/tests/github/pullrequest.yaml b/tests/tests/github/pullrequest.yaml index 336bb800ea..5c84f5743d 100644 --- a/tests/tests/github/pullrequest.yaml +++ b/tests/tests/github/pullrequest.yaml @@ -45,6 +45,15 @@ tasks: - ansible.builtin.include_tasks: ../../tasks/webhook-github/pullrequest-opened.yaml +- name: "{{ testname }} - api check deployment source user and type" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-pr-1" + sourceUser: "baxterthehacker" + sourceType: "WEBHOOK" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml # - ansible.builtin.import_playbook: ../../checks/check-branch-sha.yaml # vars: diff --git a/tests/tests/nginx/nginx.yaml b/tests/tests/nginx/nginx.yaml index 290972d2cb..fa2fe69552 100644 --- a/tests/tests/nginx/nginx.yaml +++ b/tests/tests/nginx/nginx.yaml @@ -46,6 +46,16 @@ tasks: - ansible.builtin.include_tasks: ../../tasks/api/deploy-no-sha.yaml +- name: "{{ testname }} - api check deployment source user and type for deploy environment" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-{{ branch | regex_replace('/', '-') }}" + sourceUser: "ci-customer-user-rsa@example.com" + sourceType: "API" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml + - ansible.builtin.import_playbook: check-first.yaml vars: expected_head: "{{ current_head }}" @@ -140,6 +150,26 @@ expected_branch: "{{ branch }}" project: "{{ project }}" +- name: "{{ testname }} - api deployEnvironmentLatest on {{ project }}, which should deploy the same as the last one" + hosts: localhost + serial: 1 + vars: + branch: "{{ branch }}" + project: "{{ project }}" + namespace: "{{ project | regex_replace('_', '-') }}-{{ branch | regex_replace('/', '-') }}" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/deploy-environment-latest.yaml + +- name: "{{ testname }} - api check deployment source user and type for deploy environment" + hosts: localhost + serial: 1 + vars: + namespace: "{{ project | regex_replace('_', '-') }}-{{ branch | regex_replace('/', '-') }}" + sourceUser: "ci-customer-user-rsa@example.com" + sourceType: "API" + tasks: + - ansible.builtin.include_tasks: ../../tasks/api/get-latest-deployment-source.yaml + - name: "{{ testname }} - api deleteEnvironment on {{ project }}, which should remove all resources" hosts: localhost serial: 1