UNPKG

hubot-deploy

Version:
195 lines (154 loc) 6.12 kB
Fs = require "fs" Url = require "url" Path = require "path" Fernet = require "fernet" Version = require(Path.join(__dirname, "..", "..", "version")).Version Octonode = require "octonode" GitHubApi = require(Path.join(__dirname, "..", "api")).Api ########################################################################### class Deployment @APPS_FILE = process.env['HUBOT_DEPLOY_APPS_JSON'] or "apps.json" constructor: (@name, @ref, @task, @env, @force, @hosts) -> @room = 'unknown' @user = 'unknown' @adapter = 'unknown' @userName = 'unknown' @robotName = 'hubot' @autoMerge = true @environments = [ "production" ] @requiredContexts = null @caFile = Fs.readFileSync(process.env['HUBOT_CA_FILE']) if process.env['HUBOT_CA_FILE'] @messageId = undefined @threadId = undefined try applications = JSON.parse(Fs.readFileSync(@constructor.APPS_FILE).toString()) catch throw new Error("Unable to parse your apps.json file in hubot-deploy") @application = applications[@name] if @application? @repository = @application['repository'] @configureAutoMerge() @configureRequiredContexts() @configureEnvironments() @allowedRooms = @application['allowed_rooms'] isValidApp: -> @application? isValidEnv: -> @env in @environments isAllowedRoom: (room) -> !@allowedRooms? || room in @allowedRooms # Retrieves a fully constructed request body and removes sensitive config info # A hash to be converted into the body of the post to create a GitHub Deployment requestBody: -> body = JSON.parse(JSON.stringify(@unfilteredRequestBody())) if body?.payload?.config? delete(body.payload.config.github_api) delete(body.payload.config.github_token) if process.env.HUBOT_DEPLOY_ENCRYPT_PAYLOAD and process.env.HUBOT_DEPLOY_FERNET_SECRETS payload = body.payload fernetSecret = new Fernet.Secret(process.env.HUBOT_DEPLOY_FERNET_SECRETS) fernetToken = new Fernet.Token(secret: fernetSecret) body.payload = fernetToken.encode(payload) body unfilteredRequestBody: -> ref: @ref task: @task force: @force auto_merge: @autoMerge environment: @env required_contexts: @requiredContexts description: "#{@task} on #{@env} from hubot-deploy-v#{Version}" payload: name: @name robotName: @robotName hosts: @hosts yubikey: @yubikey notify: adapter: @adapter room: @room user: @user user_name: @userName message_id: @messageId thread_id: @threadId config: @application setUserToken: (token) -> @userToken = token.trim() apiConfig: -> new GitHubApi(@userToken, @application) api: -> api = Octonode.client(@apiConfig().token, { hostname: @apiConfig().hostname }) api.requestDefaults.agentOptions = { ca: @caFile } if @caFile api latest: (callback) -> path = @apiConfig().path("repos/#{@repository}/deployments") params = environment: @env @api().get path, params, (err, status, body, headers) -> callback(err, body) post: (callback) -> name = @name repository = @repository env = @env ref = @ref requiredContexts = @requiredContexts @rawPost (err, status, body, headers) -> data = body if err data = err if data['message'] bodyMessage = data['message'] if bodyMessage.match(/No successful commit statuses/) message = """ I don't see a successful build for #{repository} that covers the latest \"#{ref}\" branch. """ if bodyMessage.match(/Conflict merging ([-_\.0-9a-z]+)/) default_branch = data.message.match(/Conflict merging ([-_\.0-9a-z]+)/)[1] message = """ There was a problem merging the #{default_branch} for #{repository} into #{ref}. You'll need to merge it manually, or disable auto-merging. """ if bodyMessage.match(/Merged ([-_\.0-9a-z]+) into/) tmpMessage = """ Successfully merged the default branch for #{repository} into #{ref}. Normal push notifications should provide feedback. """ console.log tmpMessage if bodyMessage.match(/Conflict: Commit status checks/) errors = data['errors'][0] commitContexts = errors.contexts namedContexts = (context.context for context in commitContexts ) failedContexts = (context.context for context in commitContexts when context.state isnt 'success') if requiredContexts? failedContexts.push(context) for context in requiredContexts when context not in namedContexts bodyMessage = """ Unmet required commit status contexts for #{name}: #{failedContexts.join(',')} failed. """ if bodyMessage == "Not Found" message = "Unable to create deployments for #{repository}. Check your scopes for this token." else message = bodyMessage callback(err, status, body, headers, message) rawPost: (callback) -> path = @apiConfig().path("repos/#{@repository}/deployments") repository = @repository env = @env ref = @ref @api().post path, @requestBody(), (err, status, body, headers) -> callback(err, status, body, headers) # Private Methods configureEnvironments: -> if @application['environments']? @environments = @application['environments'] @env = 'staging' if @env == 'stg' @env = 'production' if @env == 'prod' configureAutoMerge: -> if @application['auto_merge']? @autoMerge = @application['auto_merge'] if @force @autoMerge = false configureRequiredContexts: -> if @application['required_contexts']? @requiredContexts = @application['required_contexts'] if @force @requiredContexts = [ ] exports.Deployment = Deployment