diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb index 217f7e834..9e2725b9a 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb @@ -13,7 +13,8 @@ def self.run(params) milestone = Fastlane::Helper::GithubHelper.get_milestone(repository, milestone_title) UI.user_error!("Milestone #{milestone_title} not found.") if milestone.nil? - Fastlane::Helper::GithubHelper.github_client().update_milestone(repository, milestone[:number], state: 'closed') + token = Fastlane::Helper::GithubHelper.github_token + Fastlane::Helper::GithubHelper.github_client(token).update_milestone(repository, milestone[:number], state: 'closed') end def self.description diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb index d0e9094ed..d10033da8 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb @@ -27,7 +27,8 @@ def self.run(params) target: params[:target], description: release_notes, assets: assets, - prerelease: prerelease + prerelease: prerelease, + githubtoken: params[:githubtoken] ) UI.message('Done') end @@ -82,6 +83,11 @@ def self.available_options optional: true, default_value: false, is_string: false), + FastlaneCore::ConfigItem.new(key: :githubtoken, + env_name: 'GITHUB_TOKEN', + description: 'The GitHub OAuth access token', + optional: true, + type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb index defbfc207..9b72d03ec 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb @@ -14,7 +14,8 @@ def self.run(params) branch_prot[:enforce_admins] = nil branch_prot[:required_pull_request_reviews] = { url: "#{branch_url}/protection/required_pull_request_reviews", dismiss_stale_reviews: false, require_code_owner_reviews: false } - Fastlane::Helper::GithubHelper.github_client().unprotect_branch(repository, branch_name, branch_prot) + token = Fastlane::Helper::GithubHelper.github_token + Fastlane::Helper::GithubHelper.github_client(token).unprotect_branch(repository, branch_name, branch_prot) end def self.description diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb index 8026b860d..c703233df 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb @@ -13,7 +13,8 @@ def self.run(params) branch_prot[:restrictions] = { url: "#{branch_url}/protection/restrictions", users_url: "#{branch_url}/protection/restrictions/users", teams_url: "#{branch_url}/protection/restrictions/teams", users: [], teams: [] } branch_prot[:enforce_admins] = nil branch_prot[:required_pull_request_reviews] = { url: "#{branch_url}/protection/required_pull_request_reviews", dismiss_stale_reviews: false, require_code_owner_reviews: false } - Fastlane::Helper::GithubHelper.github_client().protect_branch(repository, branch_name, branch_prot) + token = Fastlane::Helper::GithubHelper.github_token + Fastlane::Helper::GithubHelper.github_client(token).protect_branch(repository, branch_name, branch_prot) end def self.description diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb index ca145bcac..4f5a36cdf 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb @@ -27,7 +27,8 @@ def self.run(params) end UI.message("New milestone: #{mile_title}") - Fastlane::Helper::GithubHelper.github_client().update_milestone(repository, milestone[:number], title: mile_title) + token = Fastlane::Helper::GithubHelper.github_token + Fastlane::Helper::GithubHelper.github_client(token).update_milestone(repository, milestone[:number], title: mile_title) end def self.is_frozen(milestone) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb index 581b078f3..2620779a2 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb @@ -19,9 +19,13 @@ def self.github_token! token || UI.user_error!('Please provide a GitHub authentication token via the `GITHUB_TOKEN` environment variable') end - def self.github_client + # Creates a client for the GitHub API + # + # @param [String] accesstoken GitHub OAuth access token + # + def self.github_client(accesstoken) @@client ||= begin - client = Octokit::Client.new(access_token: github_token!) + client = Octokit::Client.new(access_token: accesstoken) # Fetch the current user user = client.user @@ -35,7 +39,7 @@ def self.github_client end def self.get_milestone(repository, release) - miles = github_client().list_milestones(repository) + miles = github_client(github_token!).list_milestones(repository) mile = nil miles&.each do |mm| @@ -52,14 +56,14 @@ def self.get_milestone(repository, release) # @return [] A list of the PRs for the given milestone, sorted by number # def self.get_prs_for_milestone(repository, milestone) - github_client.search_issues(%(type:pr milestone:"#{milestone}" repo:#{repository}))[:items].sort_by(&:number) + github_client(github_token!).search_issues(%(type:pr milestone:"#{milestone}" repo:#{repository}))[:items].sort_by(&:number) end def self.get_last_milestone(repository) options = {} options[:state] = 'open' - milestones = github_client().list_milestones(repository, options) + milestones = github_client(github_token!).list_milestones(repository, options) return nil if milestones.nil? last_stone = nil @@ -92,7 +96,7 @@ def self.create_milestone(repository, newmilestone_number, newmilestone_duedate, options = {} options[:due_on] = newmilestone_duedate options[:description] = comment - github_client().create_milestone(repository, newmilestone_number, options) + github_client(github_token!).create_milestone(repository, newmilestone_number, options) end # Creates a Release on GitHub as a Draft @@ -105,9 +109,11 @@ def self.create_milestone(repository, newmilestone_number, newmilestone_duedate, # @param [String] description The text to use as the release's body / description (typically the release notes) # @param [Array] assets List of file paths to attach as assets to the release # @param [TrueClass|FalseClass] prerelease Indicates if this should be created as a pre-release (i.e. for alpha/beta) + # @param [String?] githubtoken GitHub OAuth access token # - def self.create_release(repository:, version:, target: nil, description:, assets:, prerelease:) - release = github_client().create_release( + def self.create_release(repository:, version:, target: nil, description:, assets:, prerelease:, githubtoken: nil) + token = githubtoken || github_token! + release = github_client(token).create_release( repository, version, # tag name name: version, # release name @@ -117,7 +123,7 @@ def self.create_release(repository:, version:, target: nil, description:, assets body: description ) assets.each do |file_path| - github_client().upload_asset(release[:url], file_path, content_type: 'application/octet-stream') + github_client(token).upload_asset(release[:url], file_path, content_type: 'application/octet-stream') end end @@ -135,9 +141,9 @@ def self.download_file_from_tag(repository:, tag:, file_path:, download_folder:) 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 + download_url = github_client(github_token!).contents(repository, + path: file_path, + ref: tag).download_url begin uri = URI.parse(download_url) uri.open do |remote_file| @@ -152,7 +158,7 @@ def self.download_file_from_tag(repository:, tag:, file_path:, download_folder:) # Creates (or updates an existing) GitHub PR Comment def self.comment_on_pr(project_slug:, pr_number:, body:, reuse_identifier: SecureRandom.uuid) - client = github_client + client = github_client(github_token!) comments = client.issue_comments(project_slug, pr_number) reuse_marker = "" diff --git a/spec/github_helper_spec.rb b/spec/github_helper_spec.rb index 18875fcbe..136152037 100644 --- a/spec/github_helper_spec.rb +++ b/spec/github_helper_spec.rb @@ -15,6 +15,7 @@ end before do + allow(described_class).to receive(:github_token!).and_return('') allow(described_class).to receive(:github_client).and_return(client) end @@ -72,7 +73,6 @@ end before do - allow(described_class).to receive(:github_token!).and_return('') allow(Octokit::Client).to receive(:new).and_return(client) end @@ -82,13 +82,13 @@ end it 'is not nil' do - expect(described_class.github_client).not_to be_nil + expect(described_class.github_client('')).not_to be_nil end it 'memoizes the client' do expect(Octokit::Client).to receive(:new).once - described_class.github_client - described_class.github_client + described_class.github_client('') + described_class.github_client('') end end @@ -103,6 +103,7 @@ end before do + allow(described_class).to receive(:github_token!).and_return('') allow(described_class).to receive(:github_client).and_return(client) end @@ -128,6 +129,7 @@ def mock_milestone(title) end before do + allow(described_class).to receive(:github_token!).and_return('') allow(described_class).to receive(:github_client).and_return(client) end @@ -171,4 +173,55 @@ def mock_comment(body: ' Test', user_id: 1234) instance_double('Comment', id: 1234, body: body, user: instance_double('User', id: user_id)) end end + + describe 'create_release' do + let(:client) do + instance_double( + Octokit::Client, + user: instance_double('User', name: 'test') + ) + end + + before do + allow(described_class).to receive(:github_client).and_return(client) + allow(client).to receive(:create_release) + end + + after do + ENV['GITHUB_TOKEN'] = nil + end + + it 'use the githubtoken when is passed as argument' do + expect(described_class).to receive(:github_client).with('PARAM_TOKEN') + create_release('PARAM_TOKEN') + end + + it 'when githubtoken is nil uses the one from the environment' do + ENV['GITHUB_TOKEN'] = 'GITHUB_TOKEN' + expect(described_class).to receive(:github_client).with('GITHUB_TOKEN') + create_release(nil) + end + + it 'prioritizes argument `githubtoken` over env variable `GITHUB_TOKEN` if both are present' do + ENV['GITHUB_TOKEN'] = 'GITHUB_TOKEN' + expect(described_class).to receive(:github_client).with('PARAM_TOKEN') + create_release('PARAM_TOKEN') + end + + it 'prints an error if neither `githubtoken` nor `GITHUB_TOKEN` are present' do + expect { create_release(nil) }.to raise_error(FastlaneCore::Interface::FastlaneError) + end + + def create_release(token) + described_class.create_release( + repository: '', + version: '', + target: '', + description: '', + assets: [], + prerelease: false, + githubtoken: token + ) + end + end end