builds.rb 7.03 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
module Ci
  module API
    # Builds API
    class Builds < Grape::API
      resource :builds do
        # Runs oldest pending build by runner - Runners only
        #
        # Parameters:
        #   token (required) - The uniq token of runner
        #
        # Example Request:
        #   POST /builds/register
        post "register" do
          authenticate_runner!
          update_runner_last_contact
16
          update_runner_info
17 18 19 20 21 22
          required_attributes! [:token]
          not_found! unless current_runner.active?

          build = Ci::RegisterBuildService.new.execute(current_runner)

          if build
23
            present build, with: Entities::BuildDetails
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
          else
            not_found!
          end
        end

        # Update an existing build - Runners only
        #
        # Parameters:
        #   id (required) - The ID of a project
        #   state (optional) - The state of a build
        #   trace (optional) - The trace of a build
        # Example Request:
        #   PUT /builds/:id
        put ":id" do
          authenticate_runner!
          update_runner_last_contact
          build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id])
41 42
          forbidden!('Build has been erased!') if build.erased?

43 44 45 46 47 48 49 50 51
          build.update_attributes(trace: params[:trace]) if params[:trace]

          case params[:state].to_s
          when 'success'
            build.success
          when 'failed'
            build.drop
          end
        end
52

53 54 55 56 57 58 59
        # Send incremental log update - Runners only
        #
        # Parameters:
        #   id (required) - The ID of a build
        # Body:
        #   content of logs to append
        # Headers:
60
        #   Content-Range (required) - range of content that was sent
61
        #   BUILD-TOKEN (required) - The build authorization token
62 63
        # Example Request:
        #   PATCH /builds/:id/trace.txt
64
        patch ":id/trace.txt" do
Tomasz Maczukin's avatar
Tomasz Maczukin committed
65 66 67
          build = Ci::Build.find_by_id(params[:id])
          not_found! unless build
          authenticate_build_token!(build)
68 69
          forbidden!('Build has been erased!') if build.erased?

Tomasz Maczukin's avatar
Tomasz Maczukin committed
70 71 72 73
          error!('400 Missing header Content-Range', 400) unless request.headers.has_key?('Content-Range')
          content_range = request.headers['Content-Range']
          content_range = content_range.split('-')

74 75 76
          current_length = build.trace_length
          unless current_length == content_range[0].to_i
            return error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{current_length}" })
Tomasz Maczukin's avatar
Tomasz Maczukin committed
77 78
          end

79
          build.append_trace(request.body.read, content_range[0].to_i)
Tomasz Maczukin's avatar
Tomasz Maczukin committed
80 81 82 83

          status 202
          header 'Build-Status', build.status
          header 'Range', "0-#{build.trace_length}"
84 85
        end

86 87 88 89 90
        # Authorize artifacts uploading for build - Runners only
        #
        # Parameters:
        #   id (required) - The ID of a build
        #   token (required) - The build authorization token
91
        #   filesize (optional) - the size of uploaded file
92 93 94 95
        # Example Request:
        #   POST /builds/:id/artifacts/authorize
        post ":id/artifacts/authorize" do
          require_gitlab_workhorse!
Kamil Trzcinski's avatar
Kamil Trzcinski committed
96
          not_allowed! unless Gitlab.config.artifacts.enabled
97 98 99 100 101 102 103 104 105 106 107
          build = Ci::Build.find_by_id(params[:id])
          not_found! unless build
          authenticate_build_token!(build)
          forbidden!('build is not running') unless build.running?

          if params[:filesize]
            file_size = params[:filesize].to_i
            file_to_large! unless file_size < max_artifacts_size
          end

          status 200
Kamil Trzcinski's avatar
Kamil Trzcinski committed
108
          { TempPath: ArtifactUploader.artifacts_upload_path }
109 110 111 112 113 114 115
        end

        # Upload artifacts to build - Runners only
        #
        # Parameters:
        #   id (required) - The ID of a build
        #   token (required) - The build authorization token
116
        #   file (required) - Artifacts file
117
        #   expire_in (optional) - Specify when artifacts should expire (ex. 7d)
118 119 120 121
        # Parameters (accelerated by GitLab Workhorse):
        #   file.path - path to locally stored body (generated by Workhorse)
        #   file.name - real filename as send in Content-Disposition
        #   file.type - real content type as send in Content-Type
122
        #   metadata.path - path to locally stored body (generated by Workhorse)
123
        #   metadata.name - filename (generated by Workhorse)
124 125 126 127 128 129 130 131 132
        # Headers:
        #   BUILD-TOKEN (required) - The build authorization token, the same as token
        # Body:
        #   The file content
        #
        # Example Request:
        #   POST /builds/:id/artifacts
        post ":id/artifacts" do
          require_gitlab_workhorse!
Kamil Trzcinski's avatar
Kamil Trzcinski committed
133
          not_allowed! unless Gitlab.config.artifacts.enabled
134 135 136
          build = Ci::Build.find_by_id(params[:id])
          not_found! unless build
          authenticate_build_token!(build)
137
          forbidden!('Build is not running!') unless build.running?
138
          forbidden!('Build has been erased!') if build.erased?
139

140
          artifacts_upload_path = ArtifactUploader.artifacts_upload_path
141 142 143 144
          artifacts = uploaded_file(:file, artifacts_upload_path)
          metadata = uploaded_file(:metadata, artifacts_upload_path)

          bad_request!('Missing artifacts file!') unless artifacts
145
          file_to_large! unless artifacts.size < max_artifacts_size
146

147 148
          build.artifacts_file = artifacts
          build.artifacts_metadata = metadata
149
          build.artifacts_expire_in = params['expire_in']
150

151
          if build.save
152
            present(build, with: Entities::BuildDetails)
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
          else
            render_validation_error!(build)
          end
        end

        # Download the artifacts file from build - Runners only
        #
        # Parameters:
        #   id (required) - The ID of a build
        #   token (required) - The build authorization token
        # Headers:
        #   BUILD-TOKEN (required) - The build authorization token, the same as token
        # Example Request:
        #   GET /builds/:id/artifacts
        get ":id/artifacts" do
          build = Ci::Build.find_by_id(params[:id])
          not_found! unless build
          authenticate_build_token!(build)
          artifacts_file = build.artifacts_file

          unless artifacts_file.file_storage?
            return redirect_to build.artifacts_file.url
          end

          unless artifacts_file.exists?
            not_found!
          end

          present_file!(artifacts_file.path, artifacts_file.filename)
        end

184
        # Remove the artifacts file from build - Runners only
185 186 187 188 189 190 191 192 193 194 195 196
        #
        # Parameters:
        #   id (required) - The ID of a build
        #   token (required) - The build authorization token
        # Headers:
        #   BUILD-TOKEN (required) - The build authorization token, the same as token
        # Example Request:
        #   DELETE /builds/:id/artifacts
        delete ":id/artifacts" do
          build = Ci::Build.find_by_id(params[:id])
          not_found! unless build
          authenticate_build_token!(build)
197

198
          build.erase_artifacts!
199
        end
200 201 202 203
      end
    end
  end
end