Overriding Issue Creation Date when raising a Gitlab Issue
If you're manually migrating existing issues into Gitlab, you may want to override the date that an issue/ticket reports as being raised on.
I wanted to do this recently as GILS's new label timelines functionality means that importing older issues is worthwhile (as it makes it easier to see the full history, even if some of it predates my use of Gitlab).
Unfortunately, Gitlab's UI doesn't provide a means to do this, but the API does.
When I was looking, there weren't any search hits on how to go about changing the creation date of an issue, so this post aims to correct that by detailing the process of filing a Gitlab issue with a custom creation date.
The API
The Issues API allows you to raise issues programatically, however it's important to note that:
- You will need to authenticate with the token of a user who has admin privileges or is owner of the project/group you're creating the issue in.
- Once you've got sufficient access, including a ISO 8601 date in
created_at
will override the creation date. - If your privileges are insufficient, you won't get an error back from the API, Gitlab will just ignore
created_at
. - You can only override
created_at
when creating an issue, it's not possible to change it afterwards as the edit endpoint doesn't support it.
Note: If you're intending to also import issue comments, you can override the date on comments via the Notes API (however, you can't override the author).
Token Creation
If you don't already have a token, you can create one as follows:
- Log into your Gitlab account
- Click your avatar in the top right
- Choose
Preferences
- Select
Access Tokens
on the left - Provide a name (and, if you wish, an expiration date)
- Tick the
api
scope - Click
Create personal access token
Basic API Request
The syntax for calling the API is fairly straight-forward:
- It's a
POST
request - You should sumbit form-encoded data
- The request path is
/api/v4/projects/$PROJECT_NAME/issues
- Where
$PROJECT_NAME
includes a forward slash, it should be url-encoded (to%2F
)
At it's simplest, it can be achieved with curl
:
curl -X POST https://$MY_GITLAB/api/v4/projects/jira-projects%2FMISC/issues \
--header "PRIVATE-TOKEN: $MY_TOKEN" \
--data-urlencode "created_at=2021-06-03T18:21:36Z" \
--data-urlencode "title=MISC-46 Dice rolls on random.bentasker.co.uk may not be consistently random" \
--data-urlencode "description=See [MISC-46](https://projects.bentasker.co.uk/jira_projects/browse/MISC-46.html)"
Giving an issue like this one.
Linking to a Milestone
If issues are associated with a specific version/sprint, you'll probably want to link issues to a specific milestone. Whilst this can be done manually after the fact, there is something to be said for doing this programatically.
Unfortunately, whilst this linking is supported, Gitlab haven't made it easy.
The milestone that the web interface shows is not the ID you need, with the API docs noting:
Basically, you need the internal ID, which isn't displayed in the UI.
Although the API documents suggest assigning an issue to the milestone and then retrieving it, that's often not a very palatable option: in 6 months time, do you want to be trying to remember why that issue was assigned to a milestone and then removed from it?
Thankfully, it's not actually necessary to assign (or make any other changes to) an issue:
- Browse to any issue in the project.
- Hit
F12
to open Developer Tools and switch to the network tab. - Click
Edit
in the milestone box in Gitlab's UI - In Developer Tools find the POST request to
/api/graphql
. - Verify that the request body includes
operationName: projectMilestones
.
If you now expand the response body you'll see some JSON giving the global ID of each of the (open) milestones in the project
You need the integer from the end of attribute id
, so in the screenshot above gid://gitlab/Milestone/32
yields ID 32
.
To create an issue in Milestone v0.1
, you can place a request like this
curl -X POST https://$MY_GITLAB/api/v4/projects/jira-projects%2FMISC/issues \
--header "PRIVATE-TOKEN: $MY_TOKEN" \
--data-urlencode "created_at=2021-06-03T18:21:36Z" \
--data-urlencode "title=HLS-7 Implement use of getopt" \
--data-urlencode "description=See [HLS-7](https://projects.bentasker.co.uk/jira_projects/browse/HLS-7.html)" \
--data-urlencode "milestone_id=32"
Giving the issue here.
Labels
The API will also allow you to add arbitrary labels to issues. There's no need to pre-create the labels, if the label doesn't already exist, Gitlab will create it:
curl -X POST https://$MY_GITLAB/api/v4/projects/misc%2Ftest_proj/issues \
-v \
--header "PRIVATE-TOKEN: $MY_TOKEN" \
--data-urlencode "created_at=2016-03-11T03:45:40Z" \
--data-urlencode "description=See [foo](http://example.invalid) blah blah foo" \
--data-urlencode "title=Test Issues" \
--data-urlencode "milestone_id=32" \
--data-urlencode "labels=new label,bug,another label"
Conclusion
Having to resort to API calls in order to override a field isn't necessarily the greatest user experience, but needing to override created_at
should also be sufficiently rare that Gitlab probably felt it wasn't worth cluttering the UI with.
Once you know how, it's quite easy to raise issues with customised dates, allowing you to import issues into Gitlab, either as a placeholder (like in the examples above) or the full issue.
The API is quite limited in terms of what it'll allow you to override, so if you're importing a full project, you're better off using one of Gitlab's Import Tools if there's one available for your data source.
But, for smaller or selective imports, it's useful to be able to at least ensure that issues are ordered correctly.