|
2 | 2 |
|
3 | 3 | require 'ddtrace/ext/git'
|
4 | 4 |
|
| 5 | +require 'open3' |
| 6 | + |
5 | 7 | module Datadog
|
6 | 8 | module CI
|
7 | 9 | module Ext
|
8 | 10 | # Defines constants for CI tags
|
9 | 11 | # rubocop:disable Metrics/ModuleLength:
|
10 | 12 | module Environment
|
11 |
| - TAG_STAGE_NAME = 'ci.stage.name' |
12 | 13 | TAG_JOB_NAME = 'ci.job.name'
|
13 | 14 | TAG_JOB_URL = 'ci.job.url'
|
14 | 15 | TAG_PIPELINE_ID = 'ci.pipeline.id'
|
15 | 16 | TAG_PIPELINE_NAME = 'ci.pipeline.name'
|
16 | 17 | TAG_PIPELINE_NUMBER = 'ci.pipeline.number'
|
17 | 18 | TAG_PIPELINE_URL = 'ci.pipeline.url'
|
18 | 19 | TAG_PROVIDER_NAME = 'ci.provider.name'
|
| 20 | + TAG_STAGE_NAME = 'ci.stage.name' |
19 | 21 | TAG_WORKSPACE_PATH = 'ci.workspace_path'
|
20 | 22 |
|
21 | 23 | PROVIDERS = [
|
@@ -53,6 +55,11 @@ def tags(env)
|
53 | 55 | tags = {}
|
54 | 56 | end
|
55 | 57 |
|
| 58 | + # Fill out tags from local git as fallback |
| 59 | + extract_local_git.each do |key, value| |
| 60 | + tags[key] ||= value |
| 61 | + end |
| 62 | + |
56 | 63 | tags.reject { |_, v| v.nil? }
|
57 | 64 | end
|
58 | 65 |
|
@@ -312,6 +319,108 @@ def extract_bitrise(env)
|
312 | 319 | }
|
313 | 320 | end
|
314 | 321 |
|
| 322 | + def git_commit_users |
| 323 | + # Get committer and author information in one command. |
| 324 | + output = exec_git_command("git show -s --format='%an\t%ae\t%at\t%cn\t%ce\t%ct'") |
| 325 | + return unless output |
| 326 | + |
| 327 | + fields = output.split("\t").each(&:strip!) |
| 328 | + |
| 329 | + { |
| 330 | + author_name: fields[0], |
| 331 | + author_email: fields[1], |
| 332 | + # Because we can't get a reliable UTC time from all recent versions of git |
| 333 | + # We have to rely on converting the date to UTC ourselves. |
| 334 | + author_date: Time.at(fields[2].to_i).utc.to_datetime.iso8601, |
| 335 | + committer_name: fields[3], |
| 336 | + committer_email: fields[4], |
| 337 | + # Because we can't get a reliable UTC time from all recent versions of git |
| 338 | + # We have to rely on converting the date to UTC ourselves. |
| 339 | + committer_date: Time.at(fields[5].to_i).utc.to_datetime.iso8601 |
| 340 | + } |
| 341 | + rescue => e |
| 342 | + Datadog.logger.debug("Unable to read git commit users: #{e.message} at #{e.backtrace.first}") |
| 343 | + nil |
| 344 | + end |
| 345 | + |
| 346 | + def git_repository_url |
| 347 | + exec_git_command('git ls-remote --get-url') |
| 348 | + rescue => e |
| 349 | + Datadog.logger.debug("Unable to read git repository url: #{e.message} at #{e.backtrace.first}") |
| 350 | + nil |
| 351 | + end |
| 352 | + |
| 353 | + def git_commit_message |
| 354 | + exec_git_command('git show -s --format=%s') |
| 355 | + rescue => e |
| 356 | + Datadog.logger.debug("Unable to read git commit message: #{e.message} at #{e.backtrace.first}") |
| 357 | + nil |
| 358 | + end |
| 359 | + |
| 360 | + def git_branch |
| 361 | + exec_git_command('git rev-parse --abbrev-ref HEAD') |
| 362 | + rescue => e |
| 363 | + Datadog.logger.debug("Unable to read git branch: #{e.message} at #{e.backtrace.first}") |
| 364 | + nil |
| 365 | + end |
| 366 | + |
| 367 | + def git_commit_sha |
| 368 | + exec_git_command('git rev-parse HEAD') |
| 369 | + rescue => e |
| 370 | + Datadog.logger.debug("Unable to read git commit SHA: #{e.message} at #{e.backtrace.first}") |
| 371 | + nil |
| 372 | + end |
| 373 | + |
| 374 | + def git_tag |
| 375 | + exec_git_command('git tag --points-at HEAD') |
| 376 | + rescue => e |
| 377 | + Datadog.logger.debug("Unable to read git tag: #{e.message} at #{e.backtrace.first}") |
| 378 | + nil |
| 379 | + end |
| 380 | + |
| 381 | + def git_base_directory |
| 382 | + exec_git_command('git rev-parse --show-toplevel') |
| 383 | + rescue => e |
| 384 | + Datadog.logger.debug("Unable to read git base directory: #{e.message} at #{e.backtrace.first}") |
| 385 | + nil |
| 386 | + end |
| 387 | + |
| 388 | + def exec_git_command(cmd) |
| 389 | + out, status = Open3.capture2e(cmd) |
| 390 | + |
| 391 | + raise "Failed to run git command #{cmd}: #{out}" unless status.success? |
| 392 | + |
| 393 | + out.strip! # There's always a "\n" at the end of the command output |
| 394 | + |
| 395 | + return nil if out.empty? |
| 396 | + |
| 397 | + out |
| 398 | + end |
| 399 | + |
| 400 | + def extract_local_git |
| 401 | + env = { |
| 402 | + TAG_WORKSPACE_PATH => git_base_directory, |
| 403 | + Datadog::Ext::Git::TAG_REPOSITORY_URL => git_repository_url, |
| 404 | + Datadog::Ext::Git::TAG_COMMIT_SHA => git_commit_sha, |
| 405 | + Datadog::Ext::Git::TAG_BRANCH => git_branch, |
| 406 | + Datadog::Ext::Git::TAG_TAG => git_tag, |
| 407 | + Datadog::Ext::Git::TAG_COMMIT_MESSAGE => git_commit_message |
| 408 | + } |
| 409 | + |
| 410 | + if (commit_users = git_commit_users) |
| 411 | + env.merge!( |
| 412 | + Datadog::Ext::Git::TAG_COMMIT_AUTHOR_NAME => commit_users[:author_name], |
| 413 | + Datadog::Ext::Git::TAG_COMMIT_AUTHOR_EMAIL => commit_users[:author_email], |
| 414 | + Datadog::Ext::Git::TAG_COMMIT_AUTHOR_DATE => commit_users[:author_date], |
| 415 | + Datadog::Ext::Git::TAG_COMMIT_COMMITTER_NAME => commit_users[:committer_name], |
| 416 | + Datadog::Ext::Git::TAG_COMMIT_COMMITTER_EMAIL => commit_users[:committer_email], |
| 417 | + Datadog::Ext::Git::TAG_COMMIT_COMMITTER_DATE => commit_users[:committer_date] |
| 418 | + ) |
| 419 | + end |
| 420 | + |
| 421 | + env |
| 422 | + end |
| 423 | + |
315 | 424 | def branch_or_tag(branch_or_tag)
|
316 | 425 | branch = tag = nil
|
317 | 426 | if branch_or_tag.include?('tags/')
|
|
0 commit comments