ぼざクリ タグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

110 lines
2.5 KiB

  1. #!/usr/bin/env ruby
  2. # A sample pre-deploy hook
  3. #
  4. # Checks the Github status of the build, waiting for a pending build to complete for up to 720 seconds.
  5. #
  6. # Fails unless the combined status is "success"
  7. #
  8. # These environment variables are available:
  9. # KAMAL_RECORDED_AT
  10. # KAMAL_PERFORMER
  11. # KAMAL_VERSION
  12. # KAMAL_HOSTS
  13. # KAMAL_COMMAND
  14. # KAMAL_SUBCOMMAND
  15. # KAMAL_ROLE (if set)
  16. # KAMAL_DESTINATION (if set)
  17. # Only check the build status for production deployments
  18. if ENV["KAMAL_COMMAND"] == "rollback" || ENV["KAMAL_DESTINATION"] != "production"
  19. exit 0
  20. end
  21. require "bundler/inline"
  22. # true = install gems so this is fast on repeat invocations
  23. gemfile(true, quiet: true) do
  24. source "https://rubygems.org"
  25. gem "octokit"
  26. gem "faraday-retry"
  27. end
  28. MAX_ATTEMPTS = 72
  29. ATTEMPTS_GAP = 10
  30. def exit_with_error(message)
  31. $stderr.puts message
  32. exit 1
  33. end
  34. class GithubStatusChecks
  35. attr_reader :remote_url, :git_sha, :github_client, :combined_status
  36. def initialize
  37. @remote_url = `git config --get remote.origin.url`.strip.delete_prefix("https://github.com/")
  38. @git_sha = `git rev-parse HEAD`.strip
  39. @github_client = Octokit::Client.new(access_token: ENV["GITHUB_TOKEN"])
  40. refresh!
  41. end
  42. def refresh!
  43. @combined_status = github_client.combined_status(remote_url, git_sha)
  44. end
  45. def state
  46. combined_status[:state]
  47. end
  48. def first_status_url
  49. first_status = combined_status[:statuses].find { |status| status[:state] == state }
  50. first_status && first_status[:target_url]
  51. end
  52. def complete_count
  53. combined_status[:statuses].count { |status| status[:state] != "pending"}
  54. end
  55. def total_count
  56. combined_status[:statuses].count
  57. end
  58. def current_status
  59. if total_count > 0
  60. "Completed #{complete_count}/#{total_count} checks, see #{first_status_url} ..."
  61. else
  62. "Build not started..."
  63. end
  64. end
  65. end
  66. $stdout.sync = true
  67. puts "Checking build status..."
  68. attempts = 0
  69. checks = GithubStatusChecks.new
  70. begin
  71. loop do
  72. case checks.state
  73. when "success"
  74. puts "Checks passed, see #{checks.first_status_url}"
  75. exit 0
  76. when "failure"
  77. exit_with_error "Checks failed, see #{checks.first_status_url}"
  78. when "pending"
  79. attempts += 1
  80. end
  81. exit_with_error "Checks are still pending, gave up after #{MAX_ATTEMPTS * ATTEMPTS_GAP} seconds" if attempts == MAX_ATTEMPTS
  82. puts checks.current_status
  83. sleep(ATTEMPTS_GAP)
  84. checks.refresh!
  85. end
  86. rescue Octokit::NotFound
  87. exit_with_error "Build status could not be found"
  88. end