Skip to content
Snippets Groups Projects
Commit dea10fa9 authored by Vasilii Iakliushin's avatar Vasilii Iakliushin :palm_tree:
Browse files

Expose `created_at` field in Tags API

Contributes to #451011

**Problem**

Tags API does not provide information about tag's creation timestamp for
annotated tags. **Note** Lightweight tags don't have their own
timestamp.

**Solution**

* Add field `created_at` to Tags API response.

Changelog: added
parent 86f04401
No related branches found
No related tags found
1 merge request!147785Expose `created_at` field in Tags API
......@@ -13,6 +13,7 @@ DETAILS:
## List project repository tags
> - `version` value for the `order_by` attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95150) in GitLab 15.4.
> - `created_at` response attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/451011) in GitLab 16.11.
Get a list of repository tags from a project, sorted by update date and time in
descending order.
......@@ -67,13 +68,16 @@ Example Response:
"name": "v1.0.0",
"target": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": null,
"protected": true
"protected": true,
"created_at": "2017-07-26T11:08:53.000+02:00"
}
]
```
## Get a single repository tag
> - `created_at` response attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/451011) in GitLab 16.11.
Get a specific repository tag determined by its name. This endpoint can be
accessed without authentication if the repository is publicly accessible.
......@@ -117,12 +121,15 @@ Example Response:
"committed_date": "2015-02-01T21:56:31.000+01:00"
},
"release": null,
"protected": false
"protected": false,
"created_at": "2017-07-26T11:08:53.000+02:00"
}
```
## Create a new tag
> - `created_at` response attribute [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/451011) in GitLab 16.11.
Creates a new tag in the repository that points to the supplied ref.
```plaintext
......@@ -168,14 +175,21 @@ Example response:
"name": "v1.0.0",
"target": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": null,
"protected": false
"protected": false,
"created_at": null
}
```
The type of tag created determines the contents of `target` and `message`:
The type of tag created determines the contents of `created_at`, `target` and `message`:
- For annotated tags, `message` contains the annotation, and `target` contains the tag object's ID.
- For lightweight tags, `message` is null, and `target` contains the commit ID.
- For annotated tags:
- `created_at` contains the timestamp of tag creation.
- `message` contains the annotation.
- `target` contains the tag object's ID.
- For lightweight tags:
- `created_at` is null.
- `message` is null.
- `target` contains the commit ID.
Errors return status code `405` with an explanatory error message.
......
......@@ -23,6 +23,8 @@ class Tag < Grape::Entity
::ProtectedTag.protected?(options[:project], repo_tag.name)
end
expose :date, as: :created_at, documentation: { type: 'dateTime', example: '2023-10-12T02:16:52.000Z' }
def can_read_release?
can?(options[:current_user], :read_release, options[:project])
end
......
{
"type": "object",
"required" : [
"required": [
"name",
"message",
"commit"
],
"properties" : {
"name": { "type": "string" },
"message": { "type": ["string", "null"] },
"commit": { "$ref": "commit/basic.json" },
"target": { "type": "string" },
"properties": {
"name": {
"type": "string"
},
"message": {
"type": [
"string",
"null"
]
},
"commit": {
"$ref": "commit/basic.json"
},
"target": {
"type": "string"
},
"release": {
"oneOf": [
{ "type": "null" },
{ "$ref": "release/tag_release.json" }
{
"type": "null"
},
{
"$ref": "release/tag_release.json"
}
]
},
"protected": { "type": "boolean" }
"protected": {
"type": "boolean"
},
"created_at": {
"oneOf": [
{
"type": "null"
},
{
"type": "string"
}
]
}
},
"additionalProperties": false
}
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::Entities::Tag, feature_category: :source_code_management do
describe '#as_json' do
subject { entity.as_json }
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:repository) { project.repository }
let_it_be(:user) { create(:user) }
let(:tag) { repository.find_tag('v1.0.0') }
let(:entity) { described_class.new(tag, project: project) }
it 'includes basic fields', :aggregate_failures do
is_expected.to include(
name: 'v1.0.0',
message: 'Release',
target: 'f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8',
commit: a_kind_of(Hash),
release: nil,
protected: false,
created_at: a_kind_of(Time))
end
context 'when a tag is lightweight' do
before do
project.repository.add_tag(user, 'v1.2.3', 'master')
end
let(:tag) { repository.find_tag('v1.2.3') }
it 'returns an empty created_at' do
is_expected.to include(name: 'v1.2.3', created_at: nil)
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment