From 3703cc4bbbb2d6562533c25648cc26269e419ab2 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 27 Jul 2018 14:04:35 +0900 Subject: [PATCH 1/2] Squashed commit of the following: commit c35ca6594eb1d29cac46362d09036f3d128143ed Merge: 87da74fb98a 13ea4b387dd Author: Shinya Maeda Date: Fri Jul 27 13:25:22 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit 87da74fb98aef1f664553ca2b8406ca154e4c19f Author: Shinya Maeda Date: Thu Jul 26 20:27:45 2018 +0900 Remove unncessary GENERAL_ARCHIVE_FILE_TYPE commit 5a3cfc1fdc8e81dd5647e275f87c0da2d93235b4 Author: Shinya Maeda Date: Thu Jul 26 20:19:44 2018 +0900 Expand entities in JobRequest::Artifacts commit 660f885ebb25a19182e601181050683d2b6134f6 Author: Shinya Maeda Date: Thu Jul 26 20:06:14 2018 +0900 Add tests commit 60bca3dcfd055647a9f43523b79d5eebdc4bdc5a Author: Shinya Maeda Date: Thu Jul 26 19:30:52 2018 +0900 Simplify build runner presenter commit 81d1951d5562bec4086d719748360f3f24df4168 Author: Shinya Maeda Date: Thu Jul 26 19:18:53 2018 +0900 Simplify `scope :test_reports` in job_artifacts commit 15d1d76ca1cb97501c82471eb1c927290071dcfb Merge: f3327b2912d ffbfd18ce2f Author: Shinya Maeda Date: Thu Jul 26 19:01:53 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit f3327b2912d0b169e7a059dca7b4d15e77567075 Author: Shinya Maeda Date: Thu Jul 26 19:01:44 2018 +0900 Fix "or string" to "or a string". Use be_valid commit 9aaae6d60f7537f55f862f4d61de7a0d3a3b6bc2 Author: Shinya Maeda Date: Wed Jul 25 21:25:57 2018 +0900 Fix spec file name - build_runner_presenter_spec.rb commit 41c64c190e2e2efa7ab91a0daa0598da2d755f05 Author: Shinya Maeda Date: Wed Jul 25 21:18:12 2018 +0900 Rename to Ci::BuildRunnerPresenter commit e9762299eb66c8f88734f80d05d38b9616a8fde8 Author: Shinya Maeda Date: Wed Jul 25 21:14:44 2018 +0900 Split methods into three in Ci::Builds::RunnerPresenter commit 6e73070313a782eb63d4fbcbe324d9acaf67334b Author: Shinya Maeda Date: Wed Jul 25 20:23:53 2018 +0900 Remove redandant as: :artifacts commit 063f647e4829d9c71a71d227f9946bb47b93691f Author: Shinya Maeda Date: Wed Jul 25 20:04:58 2018 +0900 Fix specs commit a45975afd9b9391390c1adafbeab72c970e97b64 Author: Shinya Maeda Date: Wed Jul 25 18:18:53 2018 +0900 Created a separate presenter commit 431ad666e080124c90e13cbaf0d4f0969aa7b2f2 Author: Shinya Maeda Date: Wed Jul 25 18:10:04 2018 +0900 Simplified config presenter commit 2e106569ea258f5f7556a8b454a6dd0e9cbe6902 Author: Shinya Maeda Date: Wed Jul 25 17:25:05 2018 +0900 Skip file_format setting if the file_type is trace commit 0572bd8357a2e9ea16118a0bd85264e3fb799322 Merge: 30ae33daa1d 6cb30f83255 Author: Shinya Maeda Date: Wed Jul 25 17:13:55 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit 30ae33daa1d4afcb57e6335fba62a3c5fc98468a Author: Shinya Maeda Date: Wed Jul 25 17:13:23 2018 +0900 Fix spec commit ccb6eb75187030ff0fd3c6e69f89eeca79d2a929 Merge: 1ebaaaf2094 34c57e09b9f Author: Shinya Maeda Date: Tue Jul 24 14:27:48 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit 1ebaaaf2094c47c03e16745d2f8af736ec102b76 Merge: bfdf565800b dc7b4b7bb97 Author: Shinya Maeda Date: Mon Jul 23 14:22:29 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit bfdf565800b58e838a760aa01d2fadb64e2d768f Merge: 681bd6a878a 44dbeccbe10 Author: Shinya Maeda Date: Fri Jul 20 19:10:47 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit 681bd6a878ad2a77c278f5619b51c542d7382aa2 Author: Shinya Maeda Date: Fri Jul 20 18:19:46 2018 +0900 Specify DOWNTIME=false commit 59c4e31390e0d616d69babf8ac857e98f2dc774e Author: Shinya Maeda Date: Fri Jul 20 18:14:44 2018 +0900 Wrap long lines commit 3d85788edbe73fc74c72854508e47fe259d99236 Author: Shinya Maeda Date: Fri Jul 20 18:05:31 2018 +0900 Checking filr_format and file_type paring commit 3c92a22faf6278e7a2d1ee13bd978bc659b72452 Author: Shinya Maeda Date: Fri Jul 20 16:07:21 2018 +0900 Fix build presenter spec commit 36e69897b0524cdee6060c928c03af734afae664 Author: Shinya Maeda Date: Fri Jul 20 16:02:09 2018 +0900 Erase test reports at the proper timing commit 402ae97ecf7f9e3fe541f2d6abef6e47ab740452 Author: Shinya Maeda Date: Fri Jul 20 15:46:56 2018 +0900 Make GENERAL_ARCHIVE_FILE_TYPE as a single entry commit 75f75b3f5988398fff0660ca5f04aec756ab03bb Author: Shinya Maeda Date: Fri Jul 20 15:42:16 2018 +0900 Implement config artifact presenter commit 9ecaee914defba5f12a7a06375ea2876b4328d7f Author: Shinya Maeda Date: Fri Jul 20 14:27:54 2018 +0900 Introduce ARCHIVE_LEGACY_TRACES_MIGRATION_VERSION check commit 34ea9610ab9a249a576ee435f365b9e1fcca7f00 Merge: d88523ca884 b60364c0f37 Author: Shinya Maeda Date: Fri Jul 20 13:46:52 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit d88523ca88420354f61bd36f533c62a6ca474423 Author: Shinya Maeda Date: Thu Jul 19 21:00:40 2018 +0900 Revert unnecessary change commit d9beb10ede5e4e8abe388fadbd6412640293917a Author: Shinya Maeda Date: Thu Jul 19 20:57:03 2018 +0900 Remove scattering around erase_test_reports! commit c79f361ca01f8dbc0d395edee5fab7f5a0697934 Author: Shinya Maeda Date: Thu Jul 19 20:53:00 2018 +0900 Rever archive_metadata refactoring (For simplifying) commit 55bc71a404d8cf5fa87e187f6e88da92ab95afa9 Author: Shinya Maeda Date: Thu Jul 19 20:45:19 2018 +0900 Use array_of_strings_or_string in Command commit 8a576b18c8ab8ead2344e2885aaf2fde11af0328 Author: Shinya Maeda Date: Thu Jul 19 20:40:06 2018 +0900 Fix spec commit a2cda62fb922184aaf0e78699e06846c96565e0d Author: Shinya Maeda Date: Thu Jul 19 18:27:11 2018 +0900 Fix presenter spec commit 95502e605af9bcf1a61dbeb26f9be4d181f8a7ba Author: Shinya Maeda Date: Thu Jul 19 18:23:41 2018 +0900 Fix artifact migratable commit a3930853c93862007ba6814511bc32042c7f4986 Author: Shinya Maeda Date: Thu Jul 19 18:15:41 2018 +0900 Increment migration version to use `file_format` when archiving traces commit e31121cb5e617b0f05e375c2150ece0e38e5e0d6 Author: Shinya Maeda Date: Thu Jul 19 17:57:15 2018 +0900 Impolement job_artifact.test_reports method commit e54707fdf97392839cb2c4711160bd3bc89da196 Author: Shinya Maeda Date: Thu Jul 19 16:49:27 2018 +0900 Fix erase method commit 20e95824341af1ebc5877d28dc5eba26f73eddf9 Author: Shinya Maeda Date: Thu Jul 19 16:28:00 2018 +0900 Fix spec commit 7ade498101d02573b20a2405ebe0bdb8efd8aa3b Merge: e7be6b2b362 98eccfc44c5 Author: Shinya Maeda Date: Thu Jul 19 12:37:22 2018 +0900 Merge branch 'master-ce' into artifact-format-v2 commit e7be6b2b3624ba44d56143084731cb9a6168f974 Merge: 5a8d4930e01 9bdc9b1ae69 Author: Shinya Maeda Date: Wed Jul 18 15:43:36 2018 +0900 Merge branch 'master' into artifact-format-v2 commit 5a8d4930e0127aae311bfa3da70d9ab9637791e3 Author: Shinya Maeda Date: Wed Jul 18 15:43:28 2018 +0900 Evaluate artifact_format commit c3ce06aa9bc6481b37a16d175adf0fd1c37a1bc0 Author: Shinya Maeda Date: Mon Jul 16 22:27:46 2018 +0900 Fix sending junit.xml commit e5ce3668ee65217aba610d5311efd5e82bacddf3 Author: Shinya Maeda Date: Mon Jul 16 19:02:06 2018 +0900 Add spec for Gitlab::Ci::Config::Entry::Artifacts commit ede107caf13fb215045576dcce18e20eec776df1 Author: Shinya Maeda Date: Mon Jul 16 17:58:28 2018 +0900 Revert refactoring commit 15531ba9feff669b2ac05936e0feaee1856c1571 Author: Shinya Maeda Date: Mon Jul 16 17:57:31 2018 +0900 Revert refactoring commit 14821f3babcc210bc52e4e825adc8333752fbc88 Author: Shinya Maeda Date: Mon Jul 16 17:55:41 2018 +0900 Add spec for file format. Add spec for config_artifacts commit 882faeab57ab39d18f72abd9b65d286db92e1011 Author: Shinya Maeda Date: Mon Jul 16 17:20:28 2018 +0900 Add file_format to factory commit 3cd0513e254db15141cd748f6209179f462974f2 Author: Shinya Maeda Date: Mon Jul 16 17:12:52 2018 +0900 Rename migration file properly commit f511933b5f618fc47d1512554878913922dfba61 Author: Shinya Maeda Date: Mon Jul 16 17:09:57 2018 +0900 Revert artifacts_archive_file refactoring commit e295e8cbdee065ee3af6dd82f512729554237cad Author: Shinya Maeda Date: Mon Jul 16 16:03:26 2018 +0900 Dry up the converion in Entry::Reports commit b0ffa42f6410be4718e7a36cb21f7b585421750e Author: Shinya Maeda Date: Mon Jul 16 15:50:42 2018 +0900 Set file_format at callers commit f3dc7a2e02901c79a9e572514a1b731c680e43cc Author: Shinya Maeda Date: Mon Jul 16 15:47:51 2018 +0900 Use presenter for presenting artifacts hash to runner commit e5299526138be90d65cf13368134e734b46f7597 Author: Shinya Maeda Date: Mon Jul 16 14:59:09 2018 +0900 Support deleting junit artifact. Make wording explicit commit cc81c34acf23323257d190c23030d0a89265bccc Author: Shinya Maeda Date: Mon Jul 16 14:35:12 2018 +0900 Add changelog commit abde0f2ab5c5c1d99b2f94a049984877bb5a4d77 Merge: 4c87e5b388f fabf6a5634f Author: Shinya Maeda Date: Mon Jul 16 13:22:22 2018 +0900 Merge branch 'master' into artifact-format-v2 commit 4c87e5b388fb098fb6da71e17a47fa204033e4ac Author: Shinya Maeda Date: Fri Jul 13 17:33:07 2018 +0900 Fix static analysis commit bc96346be6990b75da9a36055814b24b5b805707 Author: Shinya Maeda Date: Fri Jul 13 16:43:02 2018 +0900 Fix Config::Entry::Artifacts commit aac284613b9db43e3021198dc5b43b81806f1bce Author: Shinya Maeda Date: Fri Jul 13 14:40:20 2018 +0900 Generalized by DEFAULT_FILE_FORMAT commit a79299fdbb0ed74000ca37cff8fef8268cd29b13 Author: Shinya Maeda Date: Fri Jul 13 13:55:02 2018 +0900 Cleanup API::Entities::JobRequest::Artifacts commit 1650249214768c23f6f46ec62c0c54448017eeb5 Author: Shinya Maeda Date: Fri Jul 13 13:25:52 2018 +0900 Simplified file_type relations commit 981da91bc4c255ff992870e4e4c4393696f5bece Merge: e79808425eb 924146a8d6b Author: Shinya Maeda Date: Fri Jul 13 13:18:20 2018 +0900 Merge branch 'master' into artifact-format-v2 commit e79808425eb63c322a997e71d606d97b85e42048 Author: Shinya Maeda Date: Thu Jul 12 18:16:52 2018 +0900 Remove unnecessary change commit a531bd7487955143489d286a0fb2e5d0984acc52 Author: Shinya Maeda Date: Thu Jul 12 17:40:35 2018 +0900 Fix errors typo commit 57d6f21821c8ad934874c1aac3f627335c64c80d Author: Shinya Maeda Date: Thu Jul 12 13:32:35 2018 +0900 Use the correct type name commit da4ca63f25a27a1268317952061c81a28516653f Author: Shinya Maeda Date: Thu Jul 12 13:29:21 2018 +0900 Refactor job_artifacts_metadata to job_artifacts_archive_metadata commit 4098a8f10f92a6efa48080f8925809e251066f9d Author: Shinya Maeda Date: Thu Jul 12 13:23:55 2018 +0900 Add job_artifacts_junit relation commit 5342f07e100253713dbf50eb303da1977484077f Author: Shinya Maeda Date: Thu Jul 12 13:14:03 2018 +0900 Fix raw to raw? commit 15e0abcb22d9db3d8ef955e647f0a5d0a49c26b6 Merge: 31252fe8d75 ba38931d90b Author: Shinya Maeda Date: Thu Jul 12 13:12:38 2018 +0900 Merge branch 'master' into artifact-format-v2 commit 31252fe8d751319c5390f898f66f0af4a8581013 Author: Shinya Maeda Date: Wed Jul 11 19:05:51 2018 +0900 Temporaly use type Hash for reports commit 583165c0349f40e7be16a8039dbffb4139f94921 Author: Shinya Maeda Date: Wed Jul 11 15:27:21 2018 +0900 Revert unnecessary change commit eb48369b8311b538f46f59a31f4a6d3f8c9e68e1 Author: Shinya Maeda Date: Wed Jul 11 15:21:46 2018 +0900 Use file_format raw for trace commit fb69ae8349d58499ad21965c0d1cf95e2b79a8e3 Author: Shinya Maeda Date: Wed Jul 11 15:20:10 2018 +0900 Check the presence of the file_format commit c0840224bc8789d35da032c2a0ee48aa9f2232aa Author: Shinya Maeda Date: Wed Jul 11 15:16:19 2018 +0900 Add format_restriction validation commit d64fbd388cb2294447df5185366d8b5016591949 Merge: 7ec81e7c7d1 c2a0a3ab1ae Author: Shinya Maeda Date: Wed Jul 11 15:11:44 2018 +0900 Merge branch 'master' into artifact-format-v2 commit 7ec81e7c7d115f77d712892dfc79db72b9f5bc7a Author: Shinya Maeda Date: Fri Jul 6 20:23:54 2018 +0900 Artifacts presenter (Halfway) commit a3ccbe4c3a9b7d3095fe1929dee5fd9c57e168e0 Author: Shinya Maeda Date: Fri Jul 6 20:22:52 2018 +0900 Fix schema.rb commit b630c670c707548799c6852e4465ef94fb4a0572 Author: Shinya Maeda Date: Fri Jul 6 19:26:03 2018 +0900 Allow reports type under artifacts. Allow junit keyword in it. commit e7e37612487b556320d27f4fe0de32cd4ec20720 Author: Shinya Maeda Date: Fri Jul 6 19:25:10 2018 +0900 Change column name to artifact_format commit f3f25d56a7c627f4bb9d91d19de175273a7a6a81 Author: Shinya Maeda Date: Fri Jul 6 18:02:21 2018 +0900 Rename metadata to archive_metadata, and compress to file_format commit d7e0709319ab8fe35a2598a3d484eb89b1885934 Author: Shinya Maeda Date: Fri Jul 6 17:47:18 2018 +0900 Validate compression. Clean up schema commit beb5990e7e3bfbb308245dc97284aaf9700bd982 Author: Shinya Maeda Date: Thu Jul 5 19:06:54 2018 +0900 Make compression params at the first level commit 1e2e1c0db5412e1aed3bf47562350c20c69dc1a6 Author: Shinya Maeda Date: Thu Jul 5 16:31:03 2018 +0900 Reorganize components --- app/models/ci/build.rb | 22 +++-- app/models/ci/job_artifact.rb | 27 +++++- app/presenters/ci/build_runner_presenter.rb | 43 +++++++++ changelogs/unreleased/artifact-format-v2.yml | 5 + ...945_add_file_format_to_ci_job_artifacts.rb | 7 ++ db/schema.rb | 1 + lib/api/entities.rb | 8 +- lib/api/runner.rb | 18 ++-- lib/gitlab/ci/config/entry/artifacts.rb | 13 ++- lib/gitlab/ci/config/entry/commands.rb | 13 +-- lib/gitlab/ci/config/entry/reports.rb | 32 +++++++ lib/gitlab/ci/config/entry/validators.rb | 14 +++ lib/gitlab/ci/trace.rb | 2 + spec/factories/ci/builds.rb | 7 ++ spec/factories/ci/job_artifacts.rb | 14 +++ spec/fixtures/junit.xml.gz | Bin 0 -> 568 bytes .../gitlab/ci/config/entry/artifacts_spec.rb | 17 ++++ .../gitlab/ci/config/entry/commands_spec.rb | 3 +- .../gitlab/ci/config/entry/reports_spec.rb | 53 +++++++++++ spec/models/ci/build_spec.rb | 44 ++++++++- spec/models/ci/job_artifact_spec.rb | 50 ++++++++++ .../ci/build_runner_presenter_spec.rb | 86 ++++++++++++++++++ spec/requests/api/jobs_spec.rb | 4 +- spec/requests/api/runner_spec.rb | 54 ++++++++++- spec/services/ci/retry_build_service_spec.rb | 4 +- .../projects/update_pages_service_spec.rb | 2 +- 26 files changed, 505 insertions(+), 38 deletions(-) create mode 100644 app/presenters/ci/build_runner_presenter.rb create mode 100644 changelogs/unreleased/artifact-format-v2.yml create mode 100644 db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb create mode 100644 lib/gitlab/ci/config/entry/reports.rb create mode 100644 spec/fixtures/junit.xml.gz create mode 100644 spec/lib/gitlab/ci/config/entry/reports_spec.rb create mode 100644 spec/presenters/ci/build_runner_presenter_spec.rb diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index db86400128c..0e5dfb1bd02 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -22,9 +22,10 @@ module Ci has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id has_many :job_artifacts, class_name: 'Ci::JobArtifact', foreign_key: :job_id, dependent: :destroy, inverse_of: :job # rubocop:disable Cop/ActiveRecordDependent - has_one :job_artifacts_archive, -> { where(file_type: Ci::JobArtifact.file_types[:archive]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id - has_one :job_artifacts_metadata, -> { where(file_type: Ci::JobArtifact.file_types[:metadata]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id - has_one :job_artifacts_trace, -> { where(file_type: Ci::JobArtifact.file_types[:trace]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id + + Ci::JobArtifact.file_types.each do |key, value| + has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id + end has_one :metadata, class_name: 'Ci::BuildMetadata' has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build @@ -386,6 +387,10 @@ module Ci trace.exist? end + def has_test_reports? + job_artifacts.test_reports.any? + end + def has_old_trace? old_trace.present? end @@ -453,16 +458,21 @@ module Ci save end + def erase_test_reports! + job_artifacts.test_reports.destroy_all + end + def erase(opts = {}) return false unless erasable? erase_artifacts! + erase_test_reports! erase_trace! update_erased!(opts[:erased_by]) end def erasable? - complete? && (artifacts? || has_trace?) + complete? && (artifacts? || has_test_reports? || has_trace?) end def erased? @@ -539,10 +549,6 @@ module Ci Gitlab::Ci::Build::Image.from_services(self) end - def artifacts - [options[:artifacts]] - end - def cache cache = options[:cache] diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 3b952391b7e..054b714f8ac 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -4,11 +4,17 @@ module Ci include ObjectStorage::BackgroundMove extend Gitlab::Ci::Model + TEST_REPORT_FILE_TYPES = %w[junit].freeze + DEFAULT_FILE_NAMES = { junit: 'junit.xml' }.freeze + TYPE_AND_FORMAT_PAIRS = { archive: :zip, metadata: :gzip, trace: :raw, junit: :gzip }.freeze + belongs_to :project belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id mount_uploader :file, JobArtifactUploader + validates :file_format, presence: true, unless: :trace?, on: :create + validate :valid_file_format?, unless: :trace?, on: :create before_save :set_size, if: :file_changed? after_save :update_project_statistics_after_save, if: :size_changed? after_destroy :update_project_statistics_after_destroy, unless: :project_destroyed? @@ -17,14 +23,33 @@ module Ci scope :with_files_stored_locally, -> { where(file_store: [nil, ::JobArtifactUploader::Store::LOCAL]) } + scope :test_reports, -> do + types = self.file_types.select { |file_type| TEST_REPORT_FILE_TYPES.include?(file_type) }.values + + where(file_type: types) + end + delegate :exists?, :open, to: :file enum file_type: { archive: 1, metadata: 2, - trace: 3 + trace: 3, + junit: 4 } + enum file_format: { + raw: 1, + zip: 2, + gzip: 3 + } + + def valid_file_format? + unless TYPE_AND_FORMAT_PAIRS[self.file_type&.to_sym] == self.file_format&.to_sym + errors.add(:file_format, 'Invalid file format with specified file type') + end + end + def update_file_store # The file.object_store is set during `uploader.store!` # which happens after object is inserted/updated diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb new file mode 100644 index 00000000000..02f6c5bdf81 --- /dev/null +++ b/app/presenters/ci/build_runner_presenter.rb @@ -0,0 +1,43 @@ +module Ci + class BuildRunnerPresenter < SimpleDelegator + def artifacts + return unless options[:artifacts] + + list = [] + list << create_archive(options[:artifacts]) + list << create_reports(options[:artifacts][:reports], expire_in: options[:artifacts][:expire_in]) + list.flatten.compact + end + + private + + def create_archive(artifacts) + return unless artifacts[:untracked] || artifacts[:paths] + + { + artifact_type: :archive, + artifact_format: :zip, + name: artifacts[:name], + untracked: artifacts[:untracked], + paths: artifacts[:paths], + when: artifacts[:when], + expire_in: artifacts[:expire_in] + } + end + + def create_reports(reports, expire_in:) + return unless reports&.any? + + reports.map do |k, v| + { + artifact_type: k.to_sym, + artifact_format: :gzip, + name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES[k.to_sym], + paths: v, + when: 'always', + expire_in: expire_in + } + end + end + end +end diff --git a/changelogs/unreleased/artifact-format-v2.yml b/changelogs/unreleased/artifact-format-v2.yml new file mode 100644 index 00000000000..e264e0a9fa1 --- /dev/null +++ b/changelogs/unreleased/artifact-format-v2.yml @@ -0,0 +1,5 @@ +--- +title: Extend gitlab-ci.yml to request junit.xml test reports +merge_request: 20390 +author: +type: added diff --git a/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb b/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb new file mode 100644 index 00000000000..63c188693f3 --- /dev/null +++ b/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb @@ -0,0 +1,7 @@ +class AddFileFormatToCiJobArtifacts < ActiveRecord::Migration + DOWNTIME = false + + def change + add_column :ci_job_artifacts, :file_format, :integer, limit: 2 + end +end diff --git a/db/schema.rb b/db/schema.rb index 8ae0197d1b4..a5f7b8149c6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -393,6 +393,7 @@ ActiveRecord::Schema.define(version: 20180722103201) do t.datetime_with_timezone "expire_at" t.string "file" t.binary "file_sha256" + t.integer "file_format", limit: 2 end add_index "ci_job_artifacts", ["expire_at", "job_id"], name: "index_ci_job_artifacts_on_expire_at_and_job_id", using: :btree diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e883687f2db..4be7707d3e7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1236,7 +1236,13 @@ module API end class Artifacts < Grape::Entity - expose :name, :untracked, :paths, :when, :expire_in + expose :name + expose :untracked + expose :paths + expose :when + expose :expire_in + expose :artifact_type + expose :artifact_format end class Cache < Grape::Entity diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 06c034444a1..c7595493e11 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -109,7 +109,7 @@ module API if result.valid? if result.build Gitlab::Metrics.add_event(:build_found) - present result.build, with: Entities::JobRequest::Response + present Ci::BuildRunnerPresenter.new(result.build), with: Entities::JobRequest::Response else Gitlab::Metrics.add_event(:build_not_found) header 'X-GitLab-Last-Update', new_update @@ -231,6 +231,10 @@ module API requires :id, type: Integer, desc: %q(Job's ID) optional :token, type: String, desc: %q(Job's authentication token) optional :expire_in, type: String, desc: %q(Specify when artifacts should expire) + optional :artifact_type, type: String, desc: %q(The type of artifact), + default: 'archive', values: Ci::JobArtifact.file_types.keys + optional :artifact_format, type: String, desc: %q(The format of artifact), + default: 'zip', values: Ci::JobArtifact.file_formats.keys optional 'file.path', type: String, desc: %q(path to locally stored body (generated by Workhorse)) optional 'file.name', type: String, desc: %q(real filename as send in Content-Disposition (generated by Workhorse)) optional 'file.type', type: String, desc: %q(real content type as send in Content-Type (generated by Workhorse)) @@ -254,29 +258,29 @@ module API bad_request!('Missing artifacts file!') unless artifacts file_to_large! unless artifacts.size < max_artifacts_size - bad_request!("Already uploaded") if job.job_artifacts_archive - expire_in = params['expire_in'] || Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in - job.build_job_artifacts_archive( + job.job_artifacts.build( project: job.project, file: artifacts, - file_type: :archive, + file_type: params['artifact_type'], + file_format: params['artifact_format'], file_sha256: artifacts.sha256, expire_in: expire_in) if metadata - job.build_job_artifacts_metadata( + job.job_artifacts.build( project: job.project, file: metadata, file_type: :metadata, + file_format: :gzip, file_sha256: metadata.sha256, expire_in: expire_in) end if job.update(artifacts_expire_in: expire_in) - present job, with: Entities::JobRequest::Response + present Ci::BuildRunnerPresenter.new(job), with: Entities::JobRequest::Response else render_validation_error!(job) end diff --git a/lib/gitlab/ci/config/entry/artifacts.rb b/lib/gitlab/ci/config/entry/artifacts.rb index 8275aacee9b..e80f9d2e452 100644 --- a/lib/gitlab/ci/config/entry/artifacts.rb +++ b/lib/gitlab/ci/config/entry/artifacts.rb @@ -6,13 +6,16 @@ module Gitlab # Entry that represents a configuration of job artifacts. # class Artifacts < Node + include Configurable include Validatable include Attributable - ALLOWED_KEYS = %i[name untracked paths when expire_in].freeze + ALLOWED_KEYS = %i[name untracked paths reports when expire_in].freeze attributes ALLOWED_KEYS + entry :reports, Entry::Reports, description: 'Report-type artifacts.' + validations do validates :config, type: Hash validates :config, allowed_keys: ALLOWED_KEYS @@ -21,6 +24,7 @@ module Gitlab validates :name, type: String validates :untracked, boolean: true validates :paths, array_of_strings: true + validates :reports, type: Hash validates :when, inclusion: { in: %w[on_success on_failure always], message: 'should be on_success, on_failure ' \ @@ -28,6 +32,13 @@ module Gitlab validates :expire_in, duration: true end end + + helpers :reports + + def value + @config[:reports] = reports_value if @config.key?(:reports) + @config + end end end end diff --git a/lib/gitlab/ci/config/entry/commands.rb b/lib/gitlab/ci/config/entry/commands.rb index 65d19db249c..9f66f11be9b 100644 --- a/lib/gitlab/ci/config/entry/commands.rb +++ b/lib/gitlab/ci/config/entry/commands.rb @@ -9,18 +9,7 @@ module Gitlab include Validatable validations do - include LegacyValidationHelpers - - validate do - unless string_or_array_of_strings?(config) - errors.add(:config, - 'should be a string or an array of strings') - end - end - - def string_or_array_of_strings?(field) - validate_string(field) || validate_array_of_strings(field) - end + validates :config, array_of_strings_or_string: true end def value diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb new file mode 100644 index 00000000000..5963f3eb90c --- /dev/null +++ b/lib/gitlab/ci/config/entry/reports.rb @@ -0,0 +1,32 @@ +module Gitlab + module Ci + class Config + module Entry + ## + # Entry that represents a configuration of job artifacts. + # + class Reports < Node + include Validatable + include Attributable + + ALLOWED_KEYS = %i[junit].freeze + + attributes ALLOWED_KEYS + + validations do + validates :config, type: Hash + validates :config, allowed_keys: ALLOWED_KEYS + + with_options allow_nil: true do + validates :junit, array_of_strings_or_string: true + end + end + + def value + @config.transform_values { |v| Array(v) } + end + end + end + end + end +end diff --git a/lib/gitlab/ci/config/entry/validators.rb b/lib/gitlab/ci/config/entry/validators.rb index 55658900628..b3c889ee92f 100644 --- a/lib/gitlab/ci/config/entry/validators.rb +++ b/lib/gitlab/ci/config/entry/validators.rb @@ -130,6 +130,20 @@ module Gitlab end end + class ArrayOfStringsOrStringValidator < RegexpValidator + def validate_each(record, attribute, value) + unless validate_array_of_strings_or_string(value) + record.errors.add(attribute, 'should be an array of strings or a string') + end + end + + private + + def validate_array_of_strings_or_string(values) + validate_array_of_strings(values) || validate_string(values) + end + end + class TypeValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) type = options[:with] diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb index ee54b893598..93e219a21f9 100644 --- a/lib/gitlab/ci/trace.rb +++ b/lib/gitlab/ci/trace.rb @@ -164,6 +164,8 @@ module Gitlab def create_build_trace!(job, path) File.open(path) do |stream| + # TODO: Set `file_format: :raw` after we've cleaned up legacy traces migration + # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20307 job.create_job_artifacts_trace!( project: job.project, file_type: :trace, diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 83cb4750741..8bd1f1ae4e0 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -187,6 +187,13 @@ FactoryBot.define do end end + trait :test_reports do + after(:create) do |build| + create(:ci_job_artifact, :junit, job: build) + build.reload + end + end + trait :expired do artifacts_expire_at 1.minute.ago end diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb index 3d3287d8168..a6a87782fe7 100644 --- a/spec/factories/ci/job_artifacts.rb +++ b/spec/factories/ci/job_artifacts.rb @@ -4,6 +4,7 @@ FactoryBot.define do factory :ci_job_artifact, class: Ci::JobArtifact do job factory: :ci_build file_type :archive + file_format :zip trait :remote_store do file_store JobArtifactUploader::Store::REMOTE @@ -15,6 +16,7 @@ FactoryBot.define do trait :archive do file_type :archive + file_format :zip after(:build) do |artifact, _| artifact.file = fixture_file_upload( @@ -24,6 +26,7 @@ FactoryBot.define do trait :metadata do file_type :metadata + file_format :gzip after(:build) do |artifact, _| artifact.file = fixture_file_upload( @@ -33,6 +36,7 @@ FactoryBot.define do trait :trace do file_type :trace + file_format :raw after(:build) do |artifact, evaluator| artifact.file = fixture_file_upload( @@ -40,6 +44,16 @@ FactoryBot.define do end end + trait :junit do + file_type :junit + file_format :gzip + + after(:build) do |artifact, evaluator| + artifact.file = fixture_file_upload( + Rails.root.join('spec/fixtures/junit.xml.gz'), 'application/x-gzip') + end + end + trait :correct_checksum do after(:build) do |artifact, evaluator| artifact.file_sha256 = Digest::SHA256.file(artifact.file.path).hexdigest diff --git a/spec/fixtures/junit.xml.gz b/spec/fixtures/junit.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..88b7de6fa61e74a61375f2deb63a8f6efb5dc064 GIT binary patch literal 568 zcmV-80>}LyiwGEP$xT}T|8jG1Wn(UQZEOH?b8uy2E_iKh0K}AEPunmMz~A#JPM(BX zO=-?)1|=ln3EsAcjXg8hIf_SO8=u4A+fQlBpE9PQZQA4rdD zi(CMO-~zAn(Tt@yLn-sc;U?y&dS8ni`c=Wh{9L;;tMy`vfof4;A+jc^vYm=? zF0GhAcZzvi=1I@S2j`pFH`z1d_=blbzFm?91%^R_vMnsfzc~boL$C}y^t}pq0xnEP zwU}k&A=$%mv#@-!A3V$tbJ0}WMM6)^YDKk3=+={t)Rr($VEnCIEFqOiGSRO0Do_gp z8@qzKo+bj~ou^uS{NzcO<;l8OMdK{*L?2vyPw`|lC7RPs(`+4+>&bkY zBmh5?xA zRoQkmO_kld`eSW~PsAbqraF`h{FOSy9eIfVR3GAVf%iN+M6Z{a%l|5I8H3XCryrm) zObp6yZlc#(JSZ08Z*%33T=L=V(k=wj5d!hh#n false, 'paths' => %w(out/), 'when' => 'always', - 'expire_in' => '7d' }] + 'expire_in' => '7d', + "artifact_type" => "archive", + "artifact_format" => "zip" }] end let(:expected_cache) do @@ -1420,6 +1422,56 @@ describe API::Runner, :clean_gitlab_redis_shared_state do end end end + + context 'when artifact_type is archive' do + context 'when artifact_format is zip' do + let(:params) { { artifact_type: :archive, artifact_format: :zip } } + + it 'stores junit test report' do + upload_artifacts(file_upload, headers_with_token, params) + + expect(response).to have_gitlab_http_status(201) + expect(job.reload.job_artifacts_archive).not_to be_nil + end + end + + context 'when artifact_format is gzip' do + let(:params) { { artifact_type: :archive, artifact_format: :gzip } } + + it 'returns an error' do + upload_artifacts(file_upload, headers_with_token, params) + + expect(response).to have_gitlab_http_status(400) + expect(job.reload.job_artifacts_archive).to be_nil + end + end + end + + context 'when artifact_type is junit' do + context 'when artifact_format is gzip' do + let(:file_upload) { fixture_file_upload('spec/fixtures/junit.xml.gz') } + let(:params) { { artifact_type: :junit, artifact_format: :gzip } } + + it 'stores junit test report' do + upload_artifacts(file_upload, headers_with_token, params) + + expect(response).to have_gitlab_http_status(201) + expect(job.reload.job_artifacts_junit).not_to be_nil + end + end + + context 'when artifact_format is raw' do + let(:file_upload) { fixture_file_upload('spec/fixtures/junit.xml.gz') } + let(:params) { { artifact_type: :junit, artifact_format: :raw } } + + it 'returns an error' do + upload_artifacts(file_upload, headers_with_token, params) + + expect(response).to have_gitlab_http_status(400) + expect(job.reload.job_artifacts_junit).to be_nil + end + end + end end context 'when artifacts are being stored outside of tmp path' do diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb index ecf5d849d3f..18d52082399 100644 --- a/spec/services/ci/retry_build_service_spec.rb +++ b/spec/services/ci/retry_build_service_spec.rb @@ -24,7 +24,7 @@ describe Ci::RetryBuildService do artifacts_file artifacts_metadata artifacts_size created_at updated_at started_at finished_at queued_at erased_by erased_at auto_canceled_by job_artifacts job_artifacts_archive - job_artifacts_metadata job_artifacts_trace].freeze + job_artifacts_metadata job_artifacts_trace job_artifacts_junit].freeze IGNORE_ACCESSORS = %i[type lock_version target_url base_tags trace_sections @@ -38,7 +38,7 @@ describe Ci::RetryBuildService do let(:another_pipeline) { create(:ci_empty_pipeline, project: project) } let(:build) do - create(:ci_build, :failed, :artifacts, :expired, :erased, + create(:ci_build, :failed, :artifacts, :test_reports, :expired, :erased, :queued, :coverage, :tags, :allowed_to_fail, :on_tag, :triggered, :trace_artifact, :teardown_environment, description: 'my-job', stage: 'test', stage_id: stage.id, diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index a4c103e6f30..36b619ba9be 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -79,7 +79,7 @@ describe Projects::UpdatePagesService do context "for a valid job" do before do create(:ci_job_artifact, file: file, job: build) - create(:ci_job_artifact, file_type: :metadata, file: metadata, job: build) + create(:ci_job_artifact, file_type: :metadata, file_format: :gzip, file: metadata, job: build) build.reload end From 8b3c7f57b249b087a36eb36588223d1c7c4dbafe Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 27 Jul 2018 14:32:24 +0900 Subject: [PATCH 2/2] Avoid using destroy_all --- app/models/ci/build.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0e5dfb1bd02..35b20bc1e0b 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -459,7 +459,8 @@ module Ci end def erase_test_reports! - job_artifacts.test_reports.destroy_all + # TODO: Use fast_destroy_all in the context of https://gitlab.com/gitlab-org/gitlab-ce/issues/35240 + job_artifacts_junit&.destroy end def erase(opts = {})