Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update release fetching to optionally match tags with a platform component #32

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ def self.run(params)
end

def self.find_latest_marketing_version(github_token, platform)
client = Octokit::Client.new(access_token: github_token)

# NOTE: `client.latest_release` returns release marked as "latest", i.e. a public release
latest_internal_release = client.releases(Helper::GitHelper.repo_name(platform), { per_page: 1 }).first
latest_internal_release = Helper::GitHelper.latest_release(Helper::GitHelper.repo_name(platform), true, github_token)

version = extract_version_from_tag_name(latest_internal_release&.tag_name)
if version.to_s.empty?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def self.create_tag_and_github_release(is_prerelease, github_token)
end

begin
client = Octokit::Client.new(access_token: github_token)
latest_public_release = client.latest_release(@constants[:repo_name])
latest_public_release = Helper::GitHelper.latest_release(@constants[:repo_name], false, github_token)

UI.message("Latest public release: #{latest_public_release.tag_name}")
UI.message("Generating #{@constants[:repo_name]} release notes for GitHub release for tag: #{tag}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ def self.create_release_task(platform, version, assignee_id, asana_access_token,
#
def self.update_asana_tasks_for_internal_release(params)
UI.message("Checking latest public release in GitHub")
client = Octokit::Client.new(access_token: params[:github_token])
latest_public_release = client.latest_release(Helper::GitHelper.repo_name(params[:platform]))

latest_public_release = Helper::GitHelper.latest_release(Helper::GitHelper.repo_name(params[:platform]), false, params[:github_token])
UI.success("Latest public release: #{latest_public_release.tag_name}")

UI.message("Extracting task IDs from git log since #{latest_public_release.tag_name} release")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ def self.prepare_release_branch(platform, version, other_action)
end

def self.prepare_hotfix_branch(github_token, platform, other_action, options)
client = Octokit::Client.new(access_token: github_token)
latest_public_release = client.latest_release(Helper::GitHelper.repo_name(platform))
latest_public_release = Helper::GitHelper.latest_release(Helper::GitHelper.repo_name(platform), false, github_token)
version = latest_public_release.tag_name
Helper::GitHubActionsHelper.set_output("last_release", version)
UI.user_error!("Unable to find latest release to hotfix") unless version
Expand Down
25 changes: 25 additions & 0 deletions lib/fastlane/plugin/ddg_apple_automation/helper/git_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,31 @@ def self.assert_branch_has_changes(release_branch)

changed_files.any?
end

def self.latest_release(repo_name, prerelease, platform = nil, github_token)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll probably change the prerelease parameter name - what it's really doing it controlling whether the function only looks for a public release, or instead looks for the most recent available release regardless of internal/public status.

client = Octokit::Client.new(access_token: github_token)

current_page = 1
page_size = 25
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to change this to something else, but I feel that 25 should be enough to always find the latest public release for a given platform.


loop do
releases = client.releases(repo_name, per_page: page_size, page: current_page)
break if releases.empty?

# If `prerelease` is true, return the latest release that matches the platform regardless of whether it's public.
# If `prerelease` is false, then ensure that the release is public.
matching_release = releases.find do |release|
(prerelease || !release.prerelease) && (platform.nil? || release.tag_name.end_with?("+#{platform}"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming we're fine to check for release.prelease as a way to determine whether a tag is public or internal. It was either this or using a regex to check the tag format, and this feels simpler, providing that it's an assumption we can rely on.

end

return matching_release if matching_release
break if releases.size < page_size

current_page += 1
end

return nil
end
end
end
end
16 changes: 12 additions & 4 deletions spec/asana_find_release_task_action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,17 @@ def test_action(platform)
end

it "returns the latest marketing version" do
allow(@client).to receive(:releases).and_return([double(tag_name: '1.0.0')])

expect(find_latest_marketing_version).to eq("1.0.0")
allow(@client).to receive(:releases).and_return(
[
double(tag_name: '2.0.0-1', prerelease: true),
double(tag_name: '2.0.0-0', prerelease: true),
double(tag_name: '1.0.0', prerelease: false),
double(tag_name: '1.0.0-1', prerelease: true),
double(tag_name: '1.0.0-0', prerelease: true)
]
)

expect(find_latest_marketing_version).to eq("2.0.0")
end

describe "when there is no latest release" do
Expand All @@ -53,7 +61,7 @@ def test_action(platform)

describe "when latest release is not a valid semver" do
it "shows error" do
allow(@client).to receive(:releases).and_return([double(tag_name: '1.0')])
allow(@client).to receive(:releases).and_return([double(tag_name: '1.0', prerelease: false)])
allow(Fastlane::UI).to receive(:user_error!)

find_latest_marketing_version
Expand Down
5 changes: 3 additions & 2 deletions spec/asana_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ def sanitize_asana_html_notes(content)
before do
@client = double("Octokit::Client")
allow(Octokit::Client).to receive(:new).and_return(@client)
allow(@client).to receive(:latest_release).and_return(double(tag_name: "7.122.0"))
allow(@client).to receive(:releases).with("iOS", { page: 1, per_page: 25 }).and_return([double(tag_name: "7.122.0", prerelease: false)])
allow(@client).to receive(:releases).with("iOS", { page: 2, per_page: 25 }).and_return([])
allow(Fastlane::Helper::GitHelper).to receive(:repo_name).and_return("iOS")

@asana_client = double("Asana::Client")
Expand All @@ -263,7 +264,7 @@ def sanitize_asana_html_notes(content)
end

it "completes the update of Asana tasks for internal release" do
expect(@client).to receive(:latest_release).with("iOS")
expect(@client).to receive(:releases).with("iOS", { page: 1, per_page: 25 })

expect(Fastlane::Helper::AsanaHelper).to receive(:fetch_release_notes).with("1234567890", "secret-token")
expect(Fastlane::Helper::ReleaseTaskHelper).to receive(:construct_release_task_description).with("Release notes content", ["1234567890"])
Expand Down
4 changes: 2 additions & 2 deletions spec/ddg_apple_automation_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def load_file(file)

@client = double("Octokit::Client")
allow(Octokit::Client).to receive(:new).and_return(@client)
allow(@client).to receive(:latest_release).and_return(double(tag_name: source_version))
allow(@client).to receive(:releases).and_return([double(tag_name: source_version, prerelease: false)])
allow(Fastlane::Helper::GitHelper).to receive(:repo_name).and_return("macOS")

allow(Fastlane::Helper::DdgAppleAutomationHelper).to receive(:validate_version_exists)
Expand Down Expand Up @@ -332,7 +332,7 @@ def load_file(file)

@client = double("Octokit::Client")
allow(Octokit::Client).to receive(:new).and_return(@client)
allow(@client).to receive(:latest_release).and_return(double(tag_name: source_version))
allow(@client).to receive(:releases).and_return([double(tag_name: source_version, prerelease: false)])
allow(Fastlane::Helper::GitHelper).to receive(:repo_name).and_return("iOS")

allow(Fastlane::Helper::DdgAppleAutomationHelper).to receive(:validate_version_exists)
Expand Down
104 changes: 104 additions & 0 deletions spec/git_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,108 @@
end
end
end

describe "#latest_release" do
subject { Fastlane::Helper::GitHelper.latest_release(repo_name, prerelease, platform, github_token) }

include_context "common setup"

context "when no releases matching platform are found" do
let(:platform) { "ios" }
let(:prerelease) { false }

before do
allow(client).to receive(:releases).with(repo_name, per_page: 25, page: 1).and_return(
[
double(tag_name: "2.0.0+macos", prerelease: false),
double(tag_name: "1.0.0+macos", prerelease: false)
]
)
end

it "returns nil" do
expect(subject).to be_nil
end
end

context "when platform is not provided" do
let(:platform) { nil }

context "and prerelease is true" do
let(:prerelease) { true }

before do
allow(client).to receive(:releases).with(repo_name, per_page: 25, page: 1).and_return(
[
double(tag_name: "1.2.3-4", prerelease: true),
double(tag_name: "1.2.2-3", prerelease: true),
double(tag_name: "1.2.3", prerelease: false)
]
)
end

it "returns the latest prerelease" do
expect(subject.tag_name).to eq("1.2.3-4")
end
end

context "and prerelease is false" do
let(:prerelease) { false }

before do
allow(client).to receive(:releases).with(repo_name, per_page: 25, page: 1).and_return(
[
double(tag_name: "2.0.0-1", prerelease: true),
double(tag_name: "1.0.0", prerelease: false),
double(tag_name: "1.0.0-1", prerelease: true)
]
)
end

it "returns the latest full release" do
expect(subject.tag_name).to eq("1.0.0")
end
end
end

context "when platform is provided" do
let(:platform) { "ios" }

context "and prerelease is true" do
let(:prerelease) { true }

before do
allow(client).to receive(:releases).with(repo_name, per_page: 25, page: 1).and_return(
[
double(tag_name: "1.0.0-1+macos", prerelease: true),
double(tag_name: "2.0.0-1+ios", prerelease: true),
double(tag_name: "1.0.0-1+ios", prerelease: true)
]
)
end

it "returns the latest prerelease with the platform suffix" do
expect(subject.tag_name).to eq("2.0.0-1+ios")
end
end

context "and prerelease is false" do
let(:prerelease) { false }

before do
allow(client).to receive(:releases).with(repo_name, per_page: 25, page: 1).and_return(
[
double(tag_name: "1.0.0+macos", prerelease: false),
double(tag_name: "1.0.0+ios", prerelease: false),
double(tag_name: "1.0.0-1+ios", prerelease: true)
]
)
end

it "returns the latest full release with the platform suffix" do
expect(subject.tag_name).to eq("1.0.0+ios")
end
end
end
end
end
6 changes: 3 additions & 3 deletions spec/tag_release_action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@
describe "#create_tag_and_github_release" do
subject { Fastlane::Actions::TagReleaseAction.create_tag_and_github_release(@params[:is_prerelease], @params[:github_token]) }

let (:latest_public_release) { double(tag_name: "1.0.0") }
let (:latest_public_release) { double(tag_name: "1.0.0", prerelease: false) }
let (:generated_release_notes) { { body: { "name" => "1.1.0", "body" => "Release notes" } } }
let (:other_action) { double(add_git_tag: nil, push_git_tags: nil, github_api: generated_release_notes, set_github_release: nil) }
let (:octokit_client) { double(latest_release: latest_public_release) }
let (:octokit_client) { double(releases: [latest_public_release]) }

shared_context "local setup" do
before(:each) do
Expand Down Expand Up @@ -174,7 +174,7 @@

shared_context "when failed to fetch latest GitHub release" do
before do
allow(octokit_client).to receive(:latest_release).and_raise(StandardError)
allow(octokit_client).to receive(:releases).and_raise(StandardError)
end
end

Expand Down