diff --git a/app/models/release.rb b/app/models/release.rb index cba80ad30caaba9aecf4c0830f2d9d29f10e912a..7a09ee459a6fc991b1829daaa3a2a423ee22e4aa 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -6,6 +6,7 @@ class Release < ActiveRecord::Base cache_markdown_field :description belongs_to :project + belongs_to :author, class_name: 'User' validates :description, :project, :tag, presence: true end diff --git a/app/models/user.rb b/app/models/user.rb index dbd754dd25a002cd16b123e5b5150cdb8e316af8..f20756d1cc3dce2c47d0e2fdb08756cbd4492d9d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -130,6 +130,7 @@ def update_tracked_fields!(request) has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent + has_many :releases, dependent: :nullify, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb index 8d1fdbe11c333b0655eea24f54902ee1b0f64734..ab2dc5337aa2117c4553212eaef4e7618a13626a 100644 --- a/app/services/create_release_service.rb +++ b/app/services/create_release_service.rb @@ -13,8 +13,13 @@ def execute(tag_name, release_description) if release error('Release already exists', 409) else - release = project.releases.new({ tag: tag_name, description: release_description }) - release.save + release = project.releases.create!( + tag: tag_name, + name: tag_name, + sha: existing_tag.dereferenced_target.sha, + author: current_user, + description: release_description + ) success(release) end diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index 35390f5082cafaad5c8df49edbdfa9c1413b50ee..6bb9bb3988ed6a5f38e34090aa0787699b3f64b3 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -20,7 +20,7 @@ def execute(tag_name, target, message, release_description = nil) end if new_tag - if release_description + if release_description.present? CreateReleaseService.new(@project, @current_user) .execute(tag_name, release_description) end diff --git a/changelogs/unreleased/ac-releases-name-sha-author.yml b/changelogs/unreleased/ac-releases-name-sha-author.yml new file mode 100644 index 0000000000000000000000000000000000000000..e84b82847eb70c52517a81440bae0b3f06a36a7f --- /dev/null +++ b/changelogs/unreleased/ac-releases-name-sha-author.yml @@ -0,0 +1,5 @@ +--- +title: Add name, author_id, and sha to releases table +merge_request: 23763 +author: +type: added diff --git a/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb b/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb new file mode 100644 index 0000000000000000000000000000000000000000..60815e0c31a5ccdd29f89009915808b6111c4433 --- /dev/null +++ b/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddNameAuthorIdAndShaToReleases < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column :releases, :author_id, :integer + add_column :releases, :name, :string + add_column :releases, :sha, :string + end +end diff --git a/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb b/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb new file mode 100644 index 0000000000000000000000000000000000000000..f6350a4994470e8d9291f2197c244d19178b060e --- /dev/null +++ b/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddAuthorIdIndexAndFkToReleases < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :releases, :author_id + + add_concurrent_foreign_key :releases, :users, column: :author_id, on_delete: :nullify + end + + def down + remove_foreign_key :releases, column: :author_id + + remove_concurrent_index :releases, column: :author_id + end +end diff --git a/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb b/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb new file mode 100644 index 0000000000000000000000000000000000000000..e152dc87bc182b9f879314b07d60014ba9774599 --- /dev/null +++ b/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class BackfillReleasesNameWithTagName < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + update_column_in_batches(:releases, :name, Release.arel_table[:tag]) + end + + def down + # no-op + end +end diff --git a/db/schema.rb b/db/schema.rb index e5e19eb774521b66e25ab4ea4c29db2be0e7fda1..1a6a16decee95fbcfcb991b3743738143100a1fa 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.define(version: 20181204154019) do +ActiveRecord::Schema.define(version: 20181212104941) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1803,6 +1803,10 @@ t.datetime "updated_at" t.text "description_html" t.integer "cached_markdown_version" + t.integer "author_id" + t.string "name" + t.string "sha" + t.index ["author_id"], name: "index_releases_on_author_id", using: :btree t.index ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree t.index ["project_id"], name: "index_releases_on_project_id", using: :btree end @@ -2423,6 +2427,7 @@ add_foreign_key "protected_tags", "projects", name: "fk_8e4af87648", on_delete: :cascade add_foreign_key "push_event_payloads", "events", name: "fk_36c74129da", on_delete: :cascade add_foreign_key "releases", "projects", name: "fk_47fe2a0596", on_delete: :cascade + add_foreign_key "releases", "users", column: "author_id", name: "fk_8e4456f90f", on_delete: :nullify add_foreign_key "remote_mirrors", "projects", on_delete: :cascade add_foreign_key "repository_languages", "projects", on_delete: :cascade add_foreign_key "resource_label_events", "issues", on_delete: :cascade diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index d10d4f2f7465012732675e0eaa630d3d2fd73652..3cd8ede830ccdeed3d2e35b5b486f11b720a842b 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -27,7 +27,8 @@ project_tree: - :award_emoji - notes: :author - - :releases + - releases: + :author - project_members: - :user - merge_requests: diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb index d80c65cf8bb48bb58d89ad5d119b317cd1749d4a..18047c74a5d81ce7e91463df358abd458248c3de 100644 --- a/spec/factories/releases.rb +++ b/spec/factories/releases.rb @@ -1,6 +1,7 @@ FactoryBot.define do factory :release do tag "v1.1.0" + name { tag } description "Awesome release" project end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index bae5b21c26f8af72c1d6ea60dc1fcc580535a627..b5f63630e8d0869ac84c3e121db1f1347c5c2a18 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -63,6 +63,7 @@ snippets: - award_emoji - user_agent_detail releases: +- author - project project_members: - created_by diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index d3bfde181bc244835c81c9f859bc0460e6c56c4c..24b1f2d995b24332d10b6a9966b4212a7c77516c 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -112,8 +112,11 @@ ProjectSnippet: - visibility_level Release: - id +- name - tag +- sha - description +- author_id - project_id - created_at - updated_at diff --git a/spec/migrations/backfill_releases_name_with_tag_name_spec.rb b/spec/migrations/backfill_releases_name_with_tag_name_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..6f436de84b786cdaf26d62a3e309a565494498ca --- /dev/null +++ b/spec/migrations/backfill_releases_name_with_tag_name_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20181212104941_backfill_releases_name_with_tag_name.rb') + +describe BackfillReleasesNameWithTagName, :migration do + let(:releases) { table(:releases) } + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + + let(:namespace) { namespaces.create(name: 'foo', path: 'foo') } + let(:project) { projects.create!(namespace_id: namespace.id) } + let(:release) { releases.create!(project_id: project.id, tag: 'v1.0.0') } + + it 'defaults name to tag value' do + expect(release.tag).to be_present + + migrate! + + release.reload + expect(release.name).to eq(release.tag) + end +end diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 3f86347c3ae2f6a631fcdcec76463414481809c3..51725eeacac62626a63d9306c911250e7b5fa8a3 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -7,6 +7,7 @@ describe 'associations' do it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:author).class_name('User') } end describe 'validation' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ff075e65c763b2539b433e00bb70a61622d7c50b..8b3021113bc47344babe8181235ca94b270ea220 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -45,6 +45,7 @@ it { is_expected.to have_many(:uploads) } it { is_expected.to have_many(:reported_abuse_reports).dependent(:destroy).class_name('AbuseReport') } it { is_expected.to have_many(:custom_attributes).class_name('UserCustomAttribute') } + it { is_expected.to have_many(:releases).dependent(:nullify) } describe "#abuse_report" do let(:current_user) { create(:user) } diff --git a/spec/services/create_release_service_spec.rb b/spec/services/create_release_service_spec.rb index ac0a0458f5635185ff06fd7f57b52ed3c51cdd82..1a2dd0b39eef2f428531089252e81fc33af55466 100644 --- a/spec/services/create_release_service_spec.rb +++ b/spec/services/create_release_service_spec.rb @@ -6,6 +6,8 @@ let(:tag_name) { project.repository.tag_names.first } let(:description) { 'Awesome release!' } let(:service) { described_class.new(project, user) } + let(:tag) { project.repository.find_tag(tag_name) } + let(:sha) { tag.dereferenced_target.sha } it 'creates a new release' do result = service.execute(tag_name, description) @@ -13,6 +15,9 @@ release = project.releases.find_by(tag: tag_name) expect(release).not_to be_nil expect(release.description).to eq(description) + expect(release.name).to eq(tag_name) + expect(release.sha).to eq(sha) + expect(release.author).to eq(user) end it 'raises an error if the tag does not exist' do