Class: Fastlane::Helper::GithubHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb

Class Method Summary collapse

Class Method Details

.comment_on_pr(project_slug:, pr_number:, body:, reuse_identifier: SecureRandom.uuid) ⇒ Object

Creates (or updates an existing) GitHub PR Comment



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 154

def self.comment_on_pr(project_slug:, pr_number:, body:, reuse_identifier: SecureRandom.uuid)
  client = github_client
  comments = client.issue_comments(project_slug, pr_number)

  reuse_marker = "<!-- REUSE_ID: #{reuse_identifier} -->"

  existing_comment = comments.find do |comment|
    # Only match comments posted by the owner of the GitHub Token, and with the given reuse ID
    comment.user.id == client.user.id and comment.body.include?(reuse_marker)
  end

  comment_body = reuse_marker + body

  if existing_comment.nil?
    client.add_comment(project_slug, pr_number, comment_body)
  else
    client.update_comment(project_slug, existing_comment.id, comment_body)
  end

  reuse_identifier
end

.create_milestone(repository, newmilestone_number, newmilestone_duedate, newmilestone_duration, number_of_days_from_code_freeze_to_release, need_submission) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 83

def self.create_milestone(repository, newmilestone_number, newmilestone_duedate, newmilestone_duration, number_of_days_from_code_freeze_to_release, need_submission)
  # If there is a review process, we want to submit the binary 3 days before its release
  #
  # Using 3 days is mostly for historical reasons where we release the apps on Monday and submit them on Friday.
  days_until_submission = need_submission ? (number_of_days_from_code_freeze_to_release - 3) : newmilestone_duration
  submission_date = newmilestone_duedate.to_datetime.next_day(days_until_submission)
  release_date = newmilestone_duedate.to_datetime.next_day(number_of_days_from_code_freeze_to_release)
  comment = "Code freeze: #{newmilestone_duedate.to_datetime.strftime('%B %d, %Y')} App Store submission: #{submission_date.strftime('%B %d, %Y')} Release: #{release_date.strftime('%B %d, %Y')}"

  options = {}
  options[:due_on] = newmilestone_duedate
  options[:description] = comment
  github_client().create_milestone(repository, newmilestone_number, options)
end

.create_release(repository:, version:, target: nil, description:, assets:, prerelease:) ⇒ Object

Creates a Release on GitHub as a Draft

Parameters:

  • repository (String)

    The repository to create the GitHub release on. Typically a repo slug (<org>/<repo>).

  • version (String)

    The version for which to create this release. Will be used both as the name of the tag and the name of the release.

  • target (String?) (defaults to: nil)

    The commit SHA or branch name that this release will point to when it’s published and creates the tag. If nil (the default), will use the repo’s current HEAD commit at the time this method is called. Unused if the tag already exists.

  • description (String)

    The text to use as the release’s body / description (typically the release notes)

  • assets (Array<String>)

    List of file paths to attach as assets to the release

  • prerelease (TrueClass|FalseClass)

    Indicates if this should be created as a pre-release (i.e. for alpha/beta)



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 109

def self.create_release(repository:, version:, target: nil, description:, assets:, prerelease:)
  release = github_client().create_release(
    repository,
    version, # tag name
    name: version, # release name
    target_commitish: target || Git.open(Dir.pwd).log.first.sha,
    draft: true,
    prerelease: prerelease,
    body: description
  )
  assets.each do |file_path|
    github_client().upload_asset(release[:url], file_path, content_type: 'application/octet-stream')
  end
end

.download_file_from_tag(repository:, tag:, file_path:, download_folder:) ⇒ String

Downloads a file from the given GitHub tag

Parameters:

  • repository (String)

    The repository name (including the organization)

  • tag (String)

    The name of the tag we’re downloading from

  • file_path (String)

    The path, inside the project folder, of the file to download

  • download_folder (String)

    The folder which the file should be downloaded into

Returns:

  • (String)

    The path of the downloaded file, or nil if something went wrong



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 132

def self.download_file_from_tag(repository:, tag:, file_path:, download_folder:)
  repository = repository.delete_prefix('/').chomp('/')
  file_path = file_path.delete_prefix('/').chomp('/')
  file_name = File.basename(file_path)
  download_path = File.join(download_folder, file_name)

  download_url = github_client.contents(repository,
                                        path: file_path,
                                        ref: tag).download_url
  begin
    uri = URI.parse(download_url)
    uri.open do |remote_file|
      File.write(download_path, remote_file.read)
    end
  rescue OpenURI::HTTPError
    return nil
  end

  download_path
end

.get_last_milestone(repository) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 58

def self.get_last_milestone(repository)
  options = {}
  options[:state] = 'open'

  milestones = github_client().list_milestones(repository, options)
  return nil if milestones.nil?

  last_stone = nil
  milestones.each do |mile|
    mile_vcomps = mile[:title].split[0].split('.')
    if last_stone.nil?
      last_stone = mile unless mile_vcomps.length < 2
    else
      begin
        last_vcomps = last_stone[:title].split[0].split('.')
        last_stone = mile if Integer(mile_vcomps[0]) > Integer(last_vcomps[0]) || Integer(mile_vcomps[1]) > Integer(last_vcomps[1])
      rescue StandardError
        puts 'Found invalid milestone'
      end
    end
  end

  last_stone
end

.get_milestone(repository, release) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 37

def self.get_milestone(repository, release)
  miles = github_client().list_milestones(repository)
  mile = nil

  miles&.each do |mm|
    mile = mm if mm[:title].start_with?(release)
  end

  return mile
end

.get_prs_for_milestone(repository, milestone) ⇒ <Sawyer::Resource>

Fetch all the PRs for a given milestone

Parameters:

  • repository (String)

    The repository name, including the organization (e.g. ‘wordpress-mobile/wordpress-ios`)

  • milestone (String)

    The name of the milestone we want to fetch the list of PRs for (e.g.: ‘16.9`)

Returns:

  • (<Sawyer::Resource>)

    A list of the PRs for the given milestone, sorted by number



54
55
56
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 54

def self.get_prs_for_milestone(repository, milestone)
  github_client.search_issues(%(type:pr milestone:"#{milestone}" repo:#{repository}))[:items].sort_by(&:number)
end

.github_clientObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 22

def self.github_client
  @@client ||= begin
    client = Octokit::Client.new(access_token: github_token!)

    # Fetch the current user
    user = client.user
    UI.message("Logged in as: #{user.name}")

    # Auto-paginate to ensure we're not missing data
    client.auto_paginate = true

    client
  end
end

.github_token!Object



11
12
13
14
15
16
17
18
19
20
# File 'lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb', line 11

def self.github_token!
  token = [
    'GHHELPER_ACCESS', # For historical reasons / backward compatibility
    'GITHUB_TOKEN',    # Used by the `gh` CLI tool
  ].map { |key| ENV[key] }
          .compact
          .first

  token || UI.user_error!('Please provide a GitHub authentication token via the `GITHUB_TOKEN` environment variable')
end