diff --git a/app/controllers/trains_controller.rb b/app/controllers/trains_controller.rb index 059a2a443..0f28a7953 100644 --- a/app/controllers/trains_controller.rb +++ b/app/controllers/trains_controller.rb @@ -122,6 +122,7 @@ def train_params :tag_platform_releases, :notifications_enabled, :tag_releases, + :tag_prefix, :tag_suffix, :patch_version_bump_only, :approvals_enabled, @@ -163,6 +164,7 @@ def train_update_params :tag_platform_releases, :notifications_enabled, :tag_releases, + :tag_prefix, :tag_suffix, :patch_version_bump_only, :approvals_enabled, diff --git a/app/javascript/controllers/domain/release_suffix_help_controller.js b/app/javascript/controllers/domain/release_suffix_help_controller.js deleted file mode 100644 index 6d6abaac6..000000000 --- a/app/javascript/controllers/domain/release_suffix_help_controller.js +++ /dev/null @@ -1,30 +0,0 @@ -import {Controller} from "@hotwired/stimulus"; - -export default class extends Controller { - static values = { - version: String, - versionSuffixCurrent: String, - prefix: String - } - - static targets = [ - "input", - "helpText", - ] - - initialize() { - this.__set(this.versionSuffixCurrentValue); - } - - set() { - this.__set(this.inputTarget.value); - } - - __set(suffix) { - if (suffix !== "") { - this.helpTextTarget.innerHTML = this.prefixValue + this.versionValue + "-" + suffix; - } else { - this.helpTextTarget.innerHTML = this.prefixValue + this.versionValue; - } - } -} diff --git a/app/javascript/controllers/string_affix_controller.js b/app/javascript/controllers/string_affix_controller.js new file mode 100644 index 000000000..16d3bb330 --- /dev/null +++ b/app/javascript/controllers/string_affix_controller.js @@ -0,0 +1,41 @@ +import {Controller} from "@hotwired/stimulus"; + +export default class extends Controller { + static values = { + baseString: String, + separator: { type: String, default: "-" }, + commonPrefix: String, + } + + static targets = [ + "suffixInput", + "prefixInput", + "helpText", + ] + + initialize() { + this.__set(); + } + + set() { + this.__set(); + } + + __set() { + const prefix = this.prefixInputTarget.value; + const suffix = this.suffixInputTarget.value; + const baseString = this.baseStringValue; + const separator = this.separatorValue; + const commonPrefix = this.commonPrefixValue; + + let result = `${commonPrefix}${baseString}`; + if (prefix) { + result = `${prefix}${separator}${result}`; + } + if (suffix) { + result = `${result}${separator}${suffix}`; + } + + this.helpTextTarget.textContent = result; + } +} diff --git a/app/models/release.rb b/app/models/release.rb index a2a595137..35776a4d1 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -558,6 +558,7 @@ def copy_approvals_allowed? def base_tag_name tag = "v#{release_version}" + tag = train.tag_prefix + "-" + tag if train.tag_prefix.present? tag += "-hotfix" if hotfix? tag += "-" + train.tag_suffix if train.tag_suffix.present? tag diff --git a/app/models/train.rb b/app/models/train.rb index 6c3666b12..d8a47574e 100644 --- a/app/models/train.rb +++ b/app/models/train.rb @@ -26,6 +26,7 @@ # stop_automatic_releases_on_failure :boolean default(FALSE), not null # tag_all_store_releases :boolean default(FALSE) # tag_platform_releases :boolean default(FALSE) +# tag_prefix :string # tag_releases :boolean default(TRUE) # tag_suffix :string # version_current :string diff --git a/app/views/trains/_form.html.erb b/app/views/trains/_form.html.erb index 916a56860..2fec29ec9 100644 --- a/app/views/trains/_form.html.erb +++ b/app/views/trains/_form.html.erb @@ -237,7 +237,7 @@ <%= f.with_advanced_section(heading: "Tag Your Releases") do |section| %> <% section.with_description do %> By default, a tag is created at the end of the release with the final version of the release. - You can turn off creation of tag. Or, you can add an optional suffix to your tags. + You can turn off creation of tag. Or, you can add an optional prefix or suffix to your tags. <% end %> <%= render partial: "release_tag_form", locals: { form: section.F } %> diff --git a/app/views/trains/_release_tag_form.html.erb b/app/views/trains/_release_tag_form.html.erb index 41476f654..ffd7ad8eb 100644 --- a/app/views/trains/_release_tag_form.html.erb +++ b/app/views/trains/_release_tag_form.html.erb @@ -5,18 +5,22 @@ hide_child: @train.tag_releases?) do |component| %> <% component.with_child do %>
-
" - data-domain--release-suffix-help-version-suffix-current-value="<%= @train.tag_suffix %>" - data-domain--release-suffix-help-prefix-value="v"> +
" + data-string-affix-common-prefix-value="v"> + <%= form.labeled_text_field :tag_prefix, "Tag prefix", + placeholder: "Eg., foo", + autocomplete: "off", + data: { string_affix_target: "prefixInput", + action: "string-affix#set" } %> <%= form.labeled_text_field :tag_suffix, "Tag suffix", placeholder: "Eg., nightly", autocomplete: "off", - data: { domain__release_suffix_help_target: "input", - action: "domain--release-suffix-help#set" } %> + data: { string_affix_target: "suffixInput", + action: "string-affix#set" } %>
- This is appended to the tag name of the release, as follows:  - + These are appended to the tag name of the release, as follows:  +
diff --git a/db/migrate/20241224064815_add_config_tag_prefix_to_train.rb b/db/migrate/20241224064815_add_config_tag_prefix_to_train.rb new file mode 100644 index 000000000..601ee8b01 --- /dev/null +++ b/db/migrate/20241224064815_add_config_tag_prefix_to_train.rb @@ -0,0 +1,5 @@ +class AddConfigTagPrefixToTrain < ActiveRecord::Migration[7.2] + def change + add_column :trains, :tag_prefix, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 97d40fd5b..fe24a6bdf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_12_23_190337) do +ActiveRecord::Schema[7.2].define(version: 2024_12_24_064815) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "pgcrypto" @@ -919,6 +919,7 @@ t.boolean "patch_version_bump_only", default: false, null: false t.boolean "approvals_enabled", default: false, null: false t.boolean "freeze_version", default: false + t.string "tag_prefix" t.boolean "copy_approvals", default: false t.boolean "auto_apply_patch_changes", default: true t.index ["app_id"], name: "index_trains_on_app_id" diff --git a/lib/tasks/anonymize.rake b/lib/tasks/anonymize.rake index f1e97eb1d..000bf81c0 100644 --- a/lib/tasks/anonymize.rake +++ b/lib/tasks/anonymize.rake @@ -49,7 +49,7 @@ namespace :anonymize do whitelist "name", "slug", "description", "status", "branching_strategy", "version_seeded_with", "version_current", "repeat_duration", "build_queue_wait_time", "build_queue_size", "backmerge_strategy", "manual_release", "tag_platform_releases", "tag_all_store_releases", "compact_build_notes", "tag_releases", "build_queue_enabled", - "kickoff_at", "versioning_strategy", "send_build_notes", "notifications_enabled", "tag_suffix", "tag_platform_releases" + "kickoff_at", "versioning_strategy", "send_build_notes", "notifications_enabled", "tag_suffix", "tag_prefix", "tag_platform_releases" whitelist_timestamps anonymize("app_id") { |field| app.id } anonymize("notification_channel") { |field| {"id" => "dummy", "name" => "test", "is_private" => false} } diff --git a/spec/factories/trains.rb b/spec/factories/trains.rb index fe0aa824a..6e0f70df9 100644 --- a/spec/factories/trains.rb +++ b/spec/factories/trains.rb @@ -12,6 +12,7 @@ tag_platform_releases { false } tag_all_store_releases { false } tag_releases { true } + tag_prefix { nil } tag_suffix { nil } versioning_strategy { "semver" } approvals_enabled { true } diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index b1eaa6b77..7b4097846 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -487,6 +487,71 @@ end end + context "when tag prefix" do + let(:prefix) { "foo" } + let(:train) { create(:train, :active, tag_prefix: prefix) } + + it "saves a new tag with the prefix + base name" do + allow_any_instance_of(GithubIntegration).to receive(:create_release!) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3") + end + + it "saves prefix + base name + last commit sha" do + raise_times(GithubIntegration, release_exists_error, :create_release!, 1) + commit = create(:commit, :without_trigger, release:) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3-#{commit.short_sha}") + end + + it "saves base prefix + name + last commit sha + time" do + raise_times(GithubIntegration, release_exists_error, :create_release!, 2) + + freeze_time do + now = Time.now.to_i + commit = create(:commit, :without_trigger, release:) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3-#{commit.short_sha}-#{now}") + end + end + end + + context "when tag prefix and tag suffix" do + let(:prefix) { "foo" } + let(:suffix) { "nightly" } + let(:train) { create(:train, :active, tag_prefix: prefix, tag_suffix: suffix) } + + it "saves a new tag with the prefix + base name + suffix" do + allow_any_instance_of(GithubIntegration).to receive(:create_release!) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3-#{suffix}") + end + + it "saves prefix + base name + suffix + last commit sha" do + raise_times(GithubIntegration, release_exists_error, :create_release!, 1) + commit = create(:commit, :without_trigger, release:) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3-#{suffix}-#{commit.short_sha}") + end + + it "saves base prefix + name + suffix + last commit sha + time" do + raise_times(GithubIntegration, release_exists_error, :create_release!, 2) + + freeze_time do + now = Time.now.to_i + commit = create(:commit, :without_trigger, release:) + + release.create_vcs_release! + expect(release.tag_name).to eq("#{prefix}-v1.2.3-#{suffix}-#{commit.short_sha}-#{now}") + end + end + end + context "when release tag disabled" do let(:train) { create(:train, :active, tag_releases: false) }