-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathgitlab-release
executable file
·154 lines (134 loc) · 5.22 KB
/
gitlab-release
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
import argparse
import os
import sys
from distutils.version import LooseVersion
from urllib.parse import urljoin, quote_plus
import requests
class GitlabReleaseError(RuntimeError):
pass
class GitlabRelease:
def __init__(self, debug=False):
self.env = {}
self.fetch_all_env()
self.api_project_url = self.get_api_project_url()
self.debug = debug
def fetch_env_var(self, name, msg):
if name not in self.env:
try:
self.env[name] = os.environ[name]
except KeyError:
raise GitlabReleaseError('Missing environment variable \'{}\': {}'.format(name, msg))
return self.env[name]
def is_gitlab_v9(self):
gl_version = self.fetch_env_var('CI_SERVER_VERSION', '')
return LooseVersion(gl_version) >= LooseVersion('9.0.0')
def get_tag(self):
tag_env = 'CI_BUILD_TAG'
if self.is_gitlab_v9():
tag_env = 'CI_COMMIT_TAG'
return self.fetch_env_var(tag_env, 'Releases can only be created on tag build.')
def fetch_all_env(self):
env = {
'CI_PROJECT_URL': '',
'CI_PROJECT_ID': '',
'GITLAB_ACCESS_TOKEN': "You must specifiy the private token linked to your GitLab account.\n"
'You probably need to add a GITLAB_ACCESS_TOKEN variable to your project.',
}
for var, msg in env.items():
self.fetch_env_var(var, msg)
def get_api_project_url(self):
api_version = 'v3'
if self.is_gitlab_v9():
api_version = 'v4'
return urljoin(self.env['CI_PROJECT_URL'],
'/api/{}/projects/{}'.format(api_version, self.env['CI_PROJECT_ID']))
def post_file(self, filename):
url = '/'.join((self.api_project_url, 'uploads'))
files = {'file': open(filename, 'rb')}
res = self.request('post', url, files=files)
return res.json()['markdown']
def set_release(self, message, update=False):
url = '/'.join((self.api_project_url, 'repository/tags', self.get_tag(), 'release'))
headers = {'Content-Type': 'application/json'}
body = {'description': message}
method = 'put' if update else 'post'
res = self.request(method, url, headers=headers, json=body)
return res.json()
def fetch_release(self):
url = '/'.join((self.api_project_url, 'repository/tags', self.get_tag()))
res = self.request('get', url)
return res.json()['release']
def request(self, method, url, **kwargs):
if 'headers' not in kwargs:
kwargs['headers'] = {}
kwargs['headers']['PRIVATE-TOKEN'] = self.env['GITLAB_ACCESS_TOKEN']
if self.debug:
print(url)
if 'body' in kwargs['headers']:
print(kwargs['headers']['body'])
res = requests.request(method, url, **kwargs)
res.raise_for_status()
if self.debug:
print(res.content)
return res
def create_release(self, message, files):
links = ['* ' + self.post_file(filename) for filename in files]
links.insert(0, message)
existing_release = self.fetch_release()
update = False
if existing_release is not None:
links = [existing_release['description'], '---'] + links
update = True
return self.set_release("\n\n".join(links), update)
if __name__ == '__main__':
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description='''
This program is intended to be used in a GitLab CI job in a Runner with Docker.
### 1. Configure your `.gitlab-ci.yml`
To make an automatic release you need to add something like this to the file
`.gitlab-ci.yml` in your project.
```yaml
stages:
- build
- publish
build:
stage: build
script:
- my_build_command
artifacts:
expire_in: '1 hour'
paths:
- compiled-$CI_BUILD_TAG.exe
- doc-$CI_BUILD_TAG.pdf
publish:
image: inetprocess/gitlab-release
stage: publish
only:
- tags
script:
- gitlab-release compiled-$CI_BUILD_TAG.exe doc-$CI_BUILD_TAG.pdf
```
### 2. Generate a personnal access token
Generate a new [Personal Access Token]
(https://docs.gitlab.com/ee/api/README.html#personal-access-tokens)
from your user profile.
### 3. Configure your project
Set a [secret variable](https://docs.gitlab.com/ce/ci/variables/#secret-variables)
in your project named `GITLAB_ACCESS_TOKEN` with the token you have generated in
the previous step.
'''
)
parser.add_argument('-m', '--message', default='',
help='Markdown message before the files list in the release note')
parser.add_argument('files', nargs='*',
help='Files to link in the release.')
parser.add_argument('-d', '--debug', action='store_true',
help='Print debug messages')
args = parser.parse_args()
try:
release = GitlabRelease(args.debug)
info = release.create_release(args.message, args.files)
print("Release: {tag_name} created.\n{description}".format_map(info))
except GitlabReleaseError as err:
print(err)
sys.exit(1)