Merge branch 'releases-feature'
This commit is contained in:
commit
a43a218c98
14 changed files with 362 additions and 203 deletions
|
@ -39,6 +39,7 @@ v 8.2.0 (unreleased)
|
|||
- Improve Continuous Integration graphs page
|
||||
- Make color of "Accept Merge Request" button consistent with current build status
|
||||
- Add ignore white space option in merge request diff and commit and compare view
|
||||
- Ability to add release notes (markdown text and attachments) to git tags (aka Releases)
|
||||
|
||||
v 8.1.4
|
||||
- Fix bug where manually merged branches in a MR would end up with an empty diff (Stan Hu)
|
||||
|
|
|
@ -1,79 +1,5 @@
|
|||
# Repositories
|
||||
|
||||
## List project repository tags
|
||||
|
||||
Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
|
||||
|
||||
```
|
||||
GET /projects/:id/repository/tags
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID of a project
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"commit": {
|
||||
"author_name": "John Smith",
|
||||
"author_email": "john@example.com",
|
||||
"authored_date": "2012-05-28T04:42:42-07:00",
|
||||
"committed_date": "2012-05-28T04:42:42-07:00",
|
||||
"committer_name": "Jack Smith",
|
||||
"committer_email": "jack@example.com",
|
||||
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
|
||||
"message": "Initial commit",
|
||||
"parents_ids": [
|
||||
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
|
||||
]
|
||||
},
|
||||
"name": "v1.0.0",
|
||||
"message": null
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Create a new tag
|
||||
|
||||
Creates new tag in the repository that points to the supplied ref.
|
||||
|
||||
```
|
||||
POST /projects/:id/repository/tags
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID of a project
|
||||
- `tag_name` (required) - The name of a tag
|
||||
- `ref` (required) - Create tag using commit SHA, another tag name, or branch name.
|
||||
- `message` (optional) - Creates annotated tag.
|
||||
|
||||
```json
|
||||
{
|
||||
"commit": {
|
||||
"author_name": "John Smith",
|
||||
"author_email": "john@example.com",
|
||||
"authored_date": "2012-05-28T04:42:42-07:00",
|
||||
"committed_date": "2012-05-28T04:42:42-07:00",
|
||||
"committer_name": "Jack Smith",
|
||||
"committer_email": "jack@example.com",
|
||||
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
|
||||
"message": "Initial commit",
|
||||
"parents_ids": [
|
||||
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
|
||||
]
|
||||
},
|
||||
"name": "v1.0.0",
|
||||
"message": null
|
||||
}
|
||||
```
|
||||
The message will be `nil` when creating a lightweight tag otherwise
|
||||
it will contain the annotation.
|
||||
|
||||
It returns 200 if the operation succeed. In case of an error,
|
||||
405 with an explaining error message is returned.
|
||||
|
||||
## List repository tree
|
||||
|
||||
Get a list of repository files and directories in a project.
|
||||
|
|
106
doc/api/tags.md
Normal file
106
doc/api/tags.md
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Tags
|
||||
|
||||
## List project repository tags
|
||||
|
||||
Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
|
||||
|
||||
```
|
||||
GET /projects/:id/repository/tags
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID of a project
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"commit": {
|
||||
"author_name": "John Smith",
|
||||
"author_email": "john@example.com",
|
||||
"authored_date": "2012-05-28T04:42:42-07:00",
|
||||
"committed_date": "2012-05-28T04:42:42-07:00",
|
||||
"committer_name": "Jack Smith",
|
||||
"committer_email": "jack@example.com",
|
||||
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
|
||||
"message": "Initial commit",
|
||||
"parents_ids": [
|
||||
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"tag": "1.0.0",
|
||||
"description": "Amazing release. Wow"
|
||||
},
|
||||
"name": "v1.0.0",
|
||||
"message": null
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Create a new tag
|
||||
|
||||
Creates a new tag in the repository that points to the supplied ref.
|
||||
|
||||
```
|
||||
POST /projects/:id/repository/tags
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID of a project
|
||||
- `tag_name` (required) - The name of a tag
|
||||
- `ref` (required) - Create tag using commit SHA, another tag name, or branch name.
|
||||
- `message` (optional) - Creates annotated tag.
|
||||
- `release_description` (optional) - Add release notes to the git tag and store it in the GitLab database.
|
||||
|
||||
```json
|
||||
{
|
||||
"commit": {
|
||||
"author_name": "John Smith",
|
||||
"author_email": "john@example.com",
|
||||
"authored_date": "2012-05-28T04:42:42-07:00",
|
||||
"committed_date": "2012-05-28T04:42:42-07:00",
|
||||
"committer_name": "Jack Smith",
|
||||
"committer_email": "jack@example.com",
|
||||
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
|
||||
"message": "Initial commit",
|
||||
"parents_ids": [
|
||||
"2a4b78934375d7f53875269ffd4f45fd83a84ebe"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"tag": "1.0.0",
|
||||
"description": "Amazing release. Wow"
|
||||
},
|
||||
"name": "v1.0.0",
|
||||
"message": null
|
||||
}
|
||||
```
|
||||
The message will be `nil` when creating a lightweight tag otherwise
|
||||
it will contain the annotation.
|
||||
|
||||
It returns 200 if the operation succeed. In case of an error,
|
||||
405 with an explaining error message is returned.
|
||||
|
||||
|
||||
## New release
|
||||
|
||||
Add release notes to the existing git tag
|
||||
|
||||
```
|
||||
PUT /projects/:id/repository/:tag/release
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
- `id` (required) - The ID of a project
|
||||
- `tag` (required) - The name of a tag
|
||||
- `description` (required) - Release notes with markdown support
|
||||
|
||||
```json
|
||||
{
|
||||
"tag": "1.0.0",
|
||||
"description": "Amazing release. Wow"
|
||||
}
|
||||
```
|
|
@ -13,5 +13,6 @@
|
|||
- [Project users](add-user/add-user.md)
|
||||
- [Protected branches](protected_branches.md)
|
||||
- [Web Editor](web_editor.md)
|
||||
- [Releases](releases.md)
|
||||
- [Merge Requests](merge_requests.md)
|
||||
- ["Work In Progress" Merge Requests](wip_merge_requests.md)
|
||||
|
|
20
doc/workflow/releases.md
Normal file
20
doc/workflow/releases.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Releases
|
||||
|
||||
You can turn any git tag into a release, by adding a note to it.
|
||||
Release notes behave like any other markdown form in GitLab so you can write text and drag-n-drop files to it.
|
||||
Release notes are stored in the database of GitLab.
|
||||
|
||||
There are several ways to add release notes:
|
||||
|
||||
* In the interface, when you create a new git tag with GitLab
|
||||
* In the interface, by adding a note to an existing git tag
|
||||
* with the GitLab API
|
||||
|
||||
## New tag page with release notes text area
|
||||
|
||||
![new_tag](releases/new_tag.png)
|
||||
|
||||
## Tags page with button to add or edit release notes for existing git tag
|
||||
|
||||
![tags](releases/tags.png)
|
||||
|
BIN
doc/workflow/releases/new_tag.png
Normal file
BIN
doc/workflow/releases/new_tag.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
BIN
doc/workflow/releases/tags.png
Normal file
BIN
doc/workflow/releases/tags.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
|
@ -52,5 +52,6 @@ module API
|
|||
mount Labels
|
||||
mount Settings
|
||||
mount Keys
|
||||
mount Tags
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,25 +95,6 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
class RepoTag < Grape::Entity
|
||||
expose :name
|
||||
expose :message do |repo_obj, _options|
|
||||
if repo_obj.respond_to?(:message)
|
||||
repo_obj.message
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
expose :commit do |repo_obj, options|
|
||||
if repo_obj.respond_to?(:commit)
|
||||
repo_obj.commit
|
||||
elsif options[:project]
|
||||
options[:project].repository.commit(repo_obj.target)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class RepoObject < Grape::Entity
|
||||
expose :name
|
||||
|
||||
|
@ -341,5 +322,34 @@ module API
|
|||
expose :user_oauth_applications
|
||||
expose :after_sign_out_path
|
||||
end
|
||||
|
||||
class Release < Grape::Entity
|
||||
expose :tag, :description
|
||||
end
|
||||
|
||||
class RepoTag < Grape::Entity
|
||||
expose :name
|
||||
expose :message do |repo_obj, _options|
|
||||
if repo_obj.respond_to?(:message)
|
||||
repo_obj.message
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
expose :commit do |repo_obj, options|
|
||||
if repo_obj.respond_to?(:commit)
|
||||
repo_obj.commit
|
||||
elsif options[:project]
|
||||
options[:project].repository.commit(repo_obj.target)
|
||||
end
|
||||
end
|
||||
|
||||
expose :release, using: Entities::Release do |repo_obj, options|
|
||||
if options[:project]
|
||||
options[:project].releases.find_by(tag: repo_obj.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,41 +16,6 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
# Get a project repository tags
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# Example Request:
|
||||
# GET /projects/:id/repository/tags
|
||||
get ":id/repository/tags" do
|
||||
present user_project.repo.tags.sort_by(&:name).reverse,
|
||||
with: Entities::RepoTag, project: user_project
|
||||
end
|
||||
|
||||
# Create tag
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# tag_name (required) - The name of the tag
|
||||
# ref (required) - Create tag from commit sha or branch
|
||||
# message (optional) - Specifying a message creates an annotated tag.
|
||||
# Example Request:
|
||||
# POST /projects/:id/repository/tags
|
||||
post ':id/repository/tags' do
|
||||
authorize_push_project
|
||||
message = params[:message] || nil
|
||||
result = CreateTagService.new(user_project, current_user).
|
||||
execute(params[:tag_name], params[:ref], message)
|
||||
|
||||
if result[:status] == :success
|
||||
present result[:tag],
|
||||
with: Entities::RepoTag,
|
||||
project: user_project
|
||||
else
|
||||
render_api_error!(result[:message], 400)
|
||||
end
|
||||
end
|
||||
|
||||
# Get a project repository tree
|
||||
#
|
||||
# Parameters:
|
||||
|
|
61
lib/api/tags.rb
Normal file
61
lib/api/tags.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
module API
|
||||
# Git Tags API
|
||||
class Tags < Grape::API
|
||||
before { authenticate! }
|
||||
before { authorize! :download_code, user_project }
|
||||
|
||||
resource :projects do
|
||||
# Get a project repository tags
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# Example Request:
|
||||
# GET /projects/:id/repository/tags
|
||||
get ":id/repository/tags" do
|
||||
present user_project.repo.tags.sort_by(&:name).reverse,
|
||||
with: Entities::RepoTag, project: user_project
|
||||
end
|
||||
|
||||
# Create tag
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# tag_name (required) - The name of the tag
|
||||
# ref (required) - Create tag from commit sha or branch
|
||||
# message (optional) - Specifying a message creates an annotated tag.
|
||||
# Example Request:
|
||||
# POST /projects/:id/repository/tags
|
||||
post ':id/repository/tags' do
|
||||
authorize_push_project
|
||||
message = params[:message] || nil
|
||||
result = CreateTagService.new(user_project, current_user).
|
||||
execute(params[:tag_name], params[:ref], message, params[:release_description])
|
||||
|
||||
if result[:status] == :success
|
||||
present result[:tag],
|
||||
with: Entities::RepoTag,
|
||||
project: user_project
|
||||
else
|
||||
render_api_error!(result[:message], 400)
|
||||
end
|
||||
end
|
||||
|
||||
# Add release notes to tag
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a project
|
||||
# tag (required) - The name of the tag
|
||||
# description (required) - Release notes with markdown support
|
||||
# Example Request:
|
||||
# PUT /projects/:id/repository/tags
|
||||
put ':id/repository/:tag/release', requirements: { tag: /.*/ } do
|
||||
authorize_push_project
|
||||
required_attributes! [:description]
|
||||
release = user_project.releases.find_or_initialize_by(tag: params[:tag])
|
||||
release.update_attributes(description: params[:description])
|
||||
|
||||
present release, with: Entities::Release
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
8
lib/tasks/grape.rake
Normal file
8
lib/tasks/grape.rake
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace :grape do
|
||||
desc 'Print compiled grape routes'
|
||||
task routes: :environment do
|
||||
API::API.routes.each do |route|
|
||||
puts route
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,81 +11,6 @@ describe API::API, api: true do
|
|||
let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
|
||||
let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
|
||||
|
||||
describe "GET /projects/:id/repository/tags" do
|
||||
it "should return an array of project tags" do
|
||||
get api("/projects/#{project.id}/repository/tags", user)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.first['name']).to eq(project.repo.tags.sort_by(&:name).reverse.first.name)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /projects/:id/repository/tags' do
|
||||
context 'lightweight tags' do
|
||||
it 'should create a new tag' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v7.0.1',
|
||||
ref: 'master'
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq('v7.0.1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'annotated tag' do
|
||||
it 'should create a new annotated tag' do
|
||||
# Identity must be set in .gitconfig to create annotated tag.
|
||||
repo_path = project.repository.path_to_repo
|
||||
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.name #{user.name}))
|
||||
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.email #{user.email}))
|
||||
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v7.1.0',
|
||||
ref: 'master',
|
||||
message: 'Release 7.1.0'
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq('v7.1.0')
|
||||
expect(json_response['message']).to eq('Release 7.1.0')
|
||||
end
|
||||
end
|
||||
|
||||
it 'should deny for user without push access' do
|
||||
post api("/projects/#{project.id}/repository/tags", user2),
|
||||
tag_name: 'v1.9.0',
|
||||
ref: '621491c677087aa243f165eab467bfdfbee00be1'
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it 'should return 400 if tag name is invalid' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v 1.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Tag name invalid')
|
||||
end
|
||||
|
||||
it 'should return 400 if tag already exists' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v8.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(201)
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v8.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Tag already exists')
|
||||
end
|
||||
|
||||
it 'should return 400 if ref name is invalid' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'mytag',
|
||||
ref: 'foo'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Invalid reference name')
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/repository/tree" do
|
||||
context "authorized user" do
|
||||
before { project.team << [user2, :reporter] }
|
||||
|
|
135
spec/requests/api/tags_spec.rb
Normal file
135
spec/requests/api/tags_spec.rb
Normal file
|
@ -0,0 +1,135 @@
|
|||
require 'spec_helper'
|
||||
require 'mime/types'
|
||||
|
||||
describe API::API, api: true do
|
||||
include ApiHelpers
|
||||
include RepoHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
let!(:project) { create(:project, creator_id: user.id) }
|
||||
let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) }
|
||||
let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) }
|
||||
|
||||
describe "GET /projects/:id/repository/tags" do
|
||||
let(:tag_name) { project.repository.tag_names.sort.reverse.first }
|
||||
let(:description) { 'Awesome release!' }
|
||||
|
||||
context 'without releases' do
|
||||
it "should return an array of project tags" do
|
||||
get api("/projects/#{project.id}/repository/tags", user)
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.first['name']).to eq(tag_name)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with releases' do
|
||||
before do
|
||||
release = project.releases.find_or_initialize_by(tag: tag_name)
|
||||
release.update_attributes(description: description)
|
||||
get api("/projects/#{project.id}/repository/tags", user)
|
||||
end
|
||||
|
||||
it "should return an array of project tags with release info" do
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.first['name']).to eq(tag_name)
|
||||
expect(json_response.first['release']['description']).to eq(description)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST /projects/:id/repository/tags' do
|
||||
context 'lightweight tags' do
|
||||
it 'should create a new tag' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v7.0.1',
|
||||
ref: 'master'
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq('v7.0.1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'lightweight tags with release notes' do
|
||||
it 'should create a new tag' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v7.0.1',
|
||||
ref: 'master',
|
||||
release_description: 'Wow'
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq('v7.0.1')
|
||||
expect(json_response['release']['description']).to eq('Wow')
|
||||
end
|
||||
end
|
||||
|
||||
context 'annotated tag' do
|
||||
it 'should create a new annotated tag' do
|
||||
# Identity must be set in .gitconfig to create annotated tag.
|
||||
repo_path = project.repository.path_to_repo
|
||||
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.name #{user.name}))
|
||||
system(*%W(#{Gitlab.config.git.bin_path} --git-dir=#{repo_path} config user.email #{user.email}))
|
||||
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v7.1.0',
|
||||
ref: 'master',
|
||||
message: 'Release 7.1.0'
|
||||
|
||||
expect(response.status).to eq(201)
|
||||
expect(json_response['name']).to eq('v7.1.0')
|
||||
expect(json_response['message']).to eq('Release 7.1.0')
|
||||
end
|
||||
end
|
||||
|
||||
it 'should deny for user without push access' do
|
||||
post api("/projects/#{project.id}/repository/tags", user2),
|
||||
tag_name: 'v1.9.0',
|
||||
ref: '621491c677087aa243f165eab467bfdfbee00be1'
|
||||
expect(response.status).to eq(403)
|
||||
end
|
||||
|
||||
it 'should return 400 if tag name is invalid' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v 1.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Tag name invalid')
|
||||
end
|
||||
|
||||
it 'should return 400 if tag already exists' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v8.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(201)
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'v8.0.0',
|
||||
ref: 'master'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Tag already exists')
|
||||
end
|
||||
|
||||
it 'should return 400 if ref name is invalid' do
|
||||
post api("/projects/#{project.id}/repository/tags", user),
|
||||
tag_name: 'mytag',
|
||||
ref: 'foo'
|
||||
expect(response.status).to eq(400)
|
||||
expect(json_response['message']).to eq('Invalid reference name')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'PUT /projects/:id/repository/:tag/release' do
|
||||
let(:tag_name) { project.repository.tag_names.first }
|
||||
let(:description) { 'Awesome release!' }
|
||||
|
||||
it 'should create description for existing git tag' do
|
||||
put api("/projects/#{project.id}/repository/#{tag_name}/release", user),
|
||||
description: description
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
expect(json_response['tag']).to eq(tag_name)
|
||||
expect(json_response['description']).to eq(description)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue