Class: DamageControl::Build

Inherits:
Object
  • Object
show all
Defined in:
lib/damagecontrol/build.rb,
app/controllers/rscm_ext.rb,
lib/damagecontrol/publisher/execute.rb

Overview

Represents build-related data organised in the following file structure:

File structure:

.damagecontrol/
  SomeProject/
    project.yaml
    checkout/
    changesets/
      2802/
        changeset.yaml         (serialised ChangeSet object)
        diffs/                 (serialised diff files)
        builds/                
          2005280271234500/    (timestamp of build start)
            stdout.log
            stderr.log
            artifacts/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(project_name, changeset_identifier, time, build_reason) ⇒ Build

Creates a new Build for a project‘s changeset, created at time.



34
35
36
# File 'lib/damagecontrol/build.rb', line 34

def initialize(project_name, changeset_identifier, time, build_reason)
  @project_name, @changeset_identifier, @time, @build_reason = project_name, changeset_identifier, time, build_reason
end

Instance Attribute Details

#timeObject (readonly)

TODO: we want to store the following additional info for a build (time related)

* Total Duration
* Duration of checkpoints (compile, test, javadocs...) - should be configurable in project.
*


31
32
33
# File 'lib/damagecontrol/build.rb', line 31

def time
  @time
end

Instance Method Details

#changesetObject

Our associated changeset



49
50
51
# File 'lib/damagecontrol/build.rb', line 49

def changeset
  project.changeset(@changeset_identifier)
end

#dirObject

The directory of the build



124
125
126
# File 'lib/damagecontrol/build.rb', line 124

def dir
  Directories.build_dir(@project_name, @changeset_identifier, @time)
end

#execute(command, env = {}) ⇒ Object

Executes command with the environment variables env and persists the command for future reference. This will prevent the same build from being executed in the future.

Raises:



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/damagecontrol/build.rb', line 55

def execute(command, env={})
  command_file = Directories.build_command_file(@project_name, @changeset_identifier, @time)
  raise BuildException.new("This build has already been executed and cannot be re-executed. It was executed with '#{File.open(command_file).read}'") if File.exist?(command_file)
  FileUtils.mkdir_p(File.dirname(command_file))
  File.open(command_file, "w") do |io|
    io.write(command)
  end
  command_line = "#{command} > #{stdout} 2> #{stderr}"

  begin
    with_working_dir(checkout_dir) do
      env.each {|k,v| ENV[k]=v}
      Log.info "Executing '#{command_line}'"
      Log.info "Execution environment:"
      ENV.each {|k,v| Log.info("#{k}=#{v}")}
      IO.popen(command_line) do |io|
        File.open(pid_file, "w") do |pid_io|
          pid_io.write(pid)
        end
        
        # there is nothing to read, since we're redirecting to file,
        # but we still need to read in order to block until the process is done.
        # TODO: don't redirect stdout - we want to intercept checkpoints
        io.read
      end
    end
  ensure
    exit_code = $? >> 8
    File.open(exit_code_file, "w") do |io|
      io.write(exit_code)
    end
  end
end

#execute_publisher_dirObject



16
17
18
# File 'lib/damagecontrol/publisher/execute.rb', line 16

def execute_publisher_dir
  File.expand_path("#{dir}/execute_publisher")
end

#execute_publisher_stderrObject



12
13
14
# File 'lib/damagecontrol/publisher/execute.rb', line 12

def execute_publisher_stderr
  File.expand_path("#{execute_publisher_dir}/stderr.log")
end

#execute_publisher_stdoutObject



8
9
10
# File 'lib/damagecontrol/publisher/execute.rb', line 8

def execute_publisher_stdout
  File.expand_path("#{execute_publisher_dir}/stdout.log")
end

#exit_codeObject

Returns the exit code of the build process, or nil if the process was killed



90
91
92
93
94
95
96
# File 'lib/damagecontrol/build.rb', line 90

def exit_code
  if(File.exist?(exit_code_file))
    File.read(exit_code_file).to_i
  else
    nil
  end
end

#identifierObject

Our unique id within the changeset



39
40
41
# File 'lib/damagecontrol/build.rb', line 39

def identifier
  time.ymdHMS
end

#killObject



111
112
113
# File 'lib/damagecontrol/build.rb', line 111

def kill
  Process.kill("SIGHUP", pid)
end

#pidObject

Returns the pid of the build process



107
108
109
# File 'lib/damagecontrol/build.rb', line 107

def pid
  File.read(pid_file).to_i
end

#projectObject

Our associated project



44
45
46
# File 'lib/damagecontrol/build.rb', line 44

def project
  Project.load(@project_name)
end

#small_imageObject



7
8
9
# File 'app/controllers/rscm_ext.rb', line 7

def small_image
  exit_code == 0 ? "/images/green-16.gif" : "/images/red-16.gif"
end

#status_messageObject



102
103
104
# File 'lib/damagecontrol/build.rb', line 102

def status_message
  successful? ? "Successful" : "Failed"
end

#stderrObject



119
120
121
# File 'lib/damagecontrol/build.rb', line 119

def stderr
  Directories.stderr(@project_name, @changeset_identifier, @time)
end

#stdoutObject



115
116
117
# File 'lib/damagecontrol/build.rb', line 115

def stdout
  Directories.stdout(@project_name, @changeset_identifier, @time)
end

#successful?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/damagecontrol/build.rb', line 98

def successful?
  exit_code == 0
end