Skip to content

Commit 60f0e98

Browse files
committed
relase: make github operations perfect
1 parent b2238da commit 60f0e98

File tree

6 files changed

+188
-51
lines changed

6 files changed

+188
-51
lines changed

README.adoc

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ If you really want to develop semiconductors, your only choice is to join an uni
293293

294294
==== About the QEMU Buildroot setup
295295

296-
link:https://en.wikipedia.org/wiki/Buildroot[Buildroot] is a set of `make` scripts that downloads from source and compiles compatible versions of:
296+
link:https://en.wikipedia.org/wiki/Buildroot[Buildroot] is a set of Make scripts that download and compile from source compatible versions of:
297297

298298
* GCC
299299
* Linux kernel
@@ -553,7 +553,7 @@ Some times it works with the host QEMU:
553553
sudo apt-get install qemu-system-x86
554554
git clone https://github.com/cirosantilli/linux-kernel-module-cheat
555555
cd linux-kernel-module-cheat
556-
./download-latest-release
556+
./release-download-latest
557557
unzip lkmc-*.zip
558558
./run --prebuilt
559559
....
@@ -9404,22 +9404,7 @@ vim "$(./getvar --arch arm run_cmd_file)"
94049404
./"$(./getvar --arch arm run_cmd_file)"
94059405
....
94069406

9407-
Next, you will also want to give the relevant images to save them time. Zip the images with:
9408-
9409-
....
9410-
./build-all -G
9411-
./zip-img
9412-
....
9413-
9414-
Source: link:zip-img[]
9415-
9416-
This generates a zip file:
9417-
9418-
....
9419-
out/lkmc-*.zip
9420-
....
9421-
9422-
which you can then upload somewhere, e.g. GitHub release assets as in https://github.com/cirosantilli/linux-kernel-module-cheat/releases/tag/test-replay-arm
9407+
Next, you will also want to give the relevant images to save them time, see: <<zip-img>>.
94239408

94249409
Finally, do a clone of the relevant repository out of tree and reproduce the bug there, to be 100% sure that it is an actual upstream bug, and to provide developers with the cleanest possible commands.
94259410

@@ -10338,7 +10323,7 @@ This can be used to check the determinism of:
1033810323
* <<norandmaps>>
1033910324
* <<qemu-record-and-replay>>
1034010325

10341-
==== Releases
10326+
==== Release
1034210327

1034310328
This is not yet super stable, but one day maybe this script will automatically do a release:
1034410329

@@ -10348,8 +10333,46 @@ This is not yet super stable, but one day maybe this script will automatically d
1034810333

1034910334
Source: link:release[].
1035010335

10336+
When ready, that script should:
10337+
10338+
* build
10339+
* test
10340+
* package with <<release-zip>>
10341+
* upload to GitHub with link:release-create-github[]
10342+
1035110343
This should in particular enable to easily update <<prebuilt>>.
1035210344

10345+
===== release-zip
10346+
10347+
Create a zip containing all files required for <<prebuilt>>
10348+
10349+
....
10350+
./build-all -G
10351+
./release-zip
10352+
....
10353+
10354+
Source: link:release-zip[]
10355+
10356+
This generates a zip file:
10357+
10358+
....
10359+
echo "$(./getvar release_zip_file)"
10360+
....
10361+
10362+
which you can then upload somewhere.
10363+
10364+
For example, you can create or update a GitHub release and upload automatically with:
10365+
10366+
....
10367+
git push
10368+
printf "$GITHUB_TOKEN" > "$(./getvar github_token_file)"
10369+
./release-upload
10370+
....
10371+
10372+
Source: link:release-upload[]
10373+
10374+
TODO: generalize that so that people can upload to their forks.
10375+
1035310376
=== Fairy tale
1035410377

1035510378
____

common.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datetime
77
import glob
88
import imp
9+
import json
910
import os
1011
import re
1112
import shlex
@@ -15,10 +16,10 @@
1516
import subprocess
1617
import sys
1718
import time
19+
import urllib
20+
import urllib.request
1821

1922
this = sys.modules[__name__]
20-
21-
# Default paths.
2223
root_dir = os.path.dirname(os.path.abspath(__file__))
2324
data_dir = os.path.join(root_dir, 'data')
2425
p9_dir = os.path.join(data_dir, '9p')
@@ -34,8 +35,7 @@
3435
qemu_src_dir = os.path.join(submodules_dir, 'qemu')
3536
parsec_benchmark_src_dir = os.path.join(submodules_dir, 'parsec-benchmark')
3637
ccache_dir = os.path.join('/usr', 'lib', 'ccache')
37-
38-
# Other default variables.
38+
github_token_file = os.path.join(data_dir, 'github-token')
3939
arch_map = {
4040
'a': 'arm',
4141
'A': 'aarch64',
@@ -44,6 +44,9 @@
4444
arches = [arch_map[k] for k in arch_map]
4545
gem5_cpt_prefix = '^cpt\.'
4646
sha = subprocess.check_output(['git', '-C', root_dir, 'log', '-1', '--format=%H']).decode().rstrip()
47+
release_dir = os.path.join(this.out_dir, 'release')
48+
release_zip_file = os.path.join(this.release_dir, 'lkmc-{}.zip'.format(this.sha))
49+
github_repo_id = 'cirosantilli/linux-kernel-module-cheat'
4750
config_file = os.path.join(data_dir, 'config')
4851
if os.path.exists(config_file):
4952
config = imp.load_source('config', config_file)
@@ -189,6 +192,39 @@ def get_toolchain_tool(tool):
189192
global this
190193
return glob.glob(os.path.join(this.host_bin_dir, '*-buildroot-*-{}'.format(tool)))[0]
191194

195+
def github_make_request(
196+
authenticate=False,
197+
data=None,
198+
extra_headers=None,
199+
path='',
200+
subdomain='api',
201+
url_params=None,
202+
**extra_request_args
203+
):
204+
global this
205+
if extra_headers is None:
206+
extra_headers = {}
207+
headers = {'Accept': 'application/vnd.github.v3+json'}
208+
headers.update(extra_headers)
209+
if authenticate:
210+
with open(this.github_token_file, 'r') as f:
211+
token = f.read().rstrip()
212+
headers['Authorization'] = 'token ' + token
213+
if url_params is not None:
214+
path += '?' + urllib.parse.urlencode(url_params)
215+
request = urllib.request.Request(
216+
'https://' + subdomain + '.github.com/repos/' + github_repo_id + path,
217+
headers=headers,
218+
data=data,
219+
**extra_request_args
220+
)
221+
response_body = urllib.request.urlopen(request).read().decode()
222+
if response_body:
223+
_json = json.loads(response_body)
224+
else:
225+
_json = {}
226+
return _json
227+
192228
def log_error(msg):
193229
print('error: {}'.format(msg), file=sys.stderr)
194230

@@ -340,7 +376,7 @@ def run_cmd(
340376
#signal.signal(signal.SIGPIPE, sigpipe_old)
341377
return proc.returncode
342378

343-
def setup(parser, **extra_args):
379+
def setup(parser):
344380
'''
345381
Parse the command line arguments, and setup several variables based on them.
346382
Typically done after getting inputs from the command line arguments.

release

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
#!/usr/bin/env python3
22

3+
'''
4+
https://upload.com/cirosantilli/linux-kernel-module-cheat#release
5+
'''
6+
37
import imp
48
import os
59
import subprocess
610

711
import common
8-
zip_img = imp.load_source('zip_img', os.path.join(common.root_dir, 'zip-img'))
12+
release_zip = imp.load_source('release_zip', os.path.join(common.root_dir, 'release-zip'))
13+
release_upload = imp.load_source('release_upload', os.path.join(common.root_dir, 'release-upload'))
14+
15+
# TODO factor those out so we don't redo the same thing multiple times.
16+
# subprocess.check_call([os.path.join(common.root_dir, 'test')])
17+
# subprocess.check_call([os.path.join(common.root_dir, ''bench-all', '-A', '-u'])
918

10-
subprocess.check_call([os.path.join(common.root_dir, 'test')])
1119
# A clean release requires a full rebuild unless we hack it :-(
1220
# We can't just use our curent build as it contains packages we've
1321
# installed in random experiments. And with EXT2: we can't easily
1422
# know what the smallest root filesystem size is and use it either...
1523
# https://stackoverflow.com/questions/47320800/how-to-clean-only-target-in-buildroot
1624
subprocess.check_call([os.path.join(common.root_dir, 'build-all')])
17-
zip_img.main()
18-
tag = 'sha-{}'.format(common.sha)
19-
subprocess.check_call(['git', 'tag', '-f', tag])
20-
subprocess.check_call(['git', 'push', '--tags'])
21-
# TODO
22-
# - https://stackoverflow.com/questions/41022470/curl-request-to-add-file-to-github-release
23-
# - https://stackoverflow.com/questions/38627115/upload-files-to-github-directory-using-github-api
24-
# upload_basename = 'images-{}.zip'.format(common.sha)
25-
#curl "https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases/tags/${tag}/assets?access_token=$(cat data/access_token)&tag_name=${upload_basename}" \
26-
# --header 'Content-Type: application/zip' \
27-
# --upload-file "${common_out_dir}/${upload_basename}" \
28-
# -H 'Accept: application/vnd.github.v3+json' \
29-
# -X POST \
30-
#;
31-
subprocess.check_call(['./bench-all', '-A', '-u'])
25+
release_zip.main()
26+
subprocess.check_call(['git', 'push'])
27+
release_upload.main()
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
#!/usr/bin/env python3
22

33
'''
4-
Download the latest release from GitHub:
4+
Usage: https://github.com/cirosantilli/linux-kernel-module-cheat#prebuilt
5+
6+
Implementation:
57
https://stackoverflow.com/questions/24987542/is-there-a-link-to-github-for-downloading-a-file-in-the-latest-release-of-a-repo/50540591#50540591
68
'''
79

8-
import json
910
import urllib.request
1011

11-
_json = json.loads(urllib.request.urlopen(urllib.request.Request(
12-
'https://api.github.com/repos/cirosantilli/linux-kernel-module-cheat/releases',
13-
headers={'Accept' : 'application/vnd.github.full+json"text/html'}
14-
)).read())
12+
import common
13+
14+
_json = common.github_make_request(path='/releases')
1515
asset = _json[0]['assets'][0]
1616
urllib.request.urlretrieve(asset['browser_download_url'], asset['name'])

release-upload

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python3
2+
3+
'''
4+
Usage: https://github.com/cirosantilli/linux-kernel-module-cheat#release-zip
5+
6+
Implementation:
7+
8+
* https://stackoverflow.com/questions/5207269/how-to-release-a-build-artifact-asset-on-github-with-a-script/52354732#52354732
9+
* https://stackoverflow.com/questions/38153418/can-someone-give-a-python-requests-example-of-uploading-a-release-asset-in-githu/52354681#52354681
10+
'''
11+
12+
import json
13+
import os
14+
import sys
15+
16+
import urllib.error
17+
18+
import common
19+
20+
def main():
21+
repo = common.github_repo_id
22+
tag = 'sha-{}'.format(common.sha)
23+
upload_path = common.release_zip_file
24+
25+
# Check the release already exists.
26+
try:
27+
_json = common.github_make_request(path='/releases/tags/' + tag)
28+
except urllib.error.HTTPError as e:
29+
if e.code == 404:
30+
release_exists = False
31+
else:
32+
raise e
33+
else:
34+
release_exists = True
35+
release_id = _json['id']
36+
37+
# Create release if not yet created.
38+
if not release_exists:
39+
_json = common.github_make_request(
40+
authenticate=True,
41+
data=json.dumps({
42+
'tag_name': tag,
43+
'name': tag,
44+
'prerelease': True,
45+
}).encode(),
46+
path='/releases'
47+
)
48+
release_id = _json['id']
49+
50+
asset_name = os.path.split(upload_path)[1]
51+
52+
# Clear the prebuilts for a upload.
53+
_json = common.github_make_request(
54+
path=('/releases/' + str(release_id) + '/assets'),
55+
)
56+
for asset in _json:
57+
if asset['name'] == asset_name:
58+
_json = common.github_make_request(
59+
authenticate=True,
60+
path=('/releases/assets/' + str(asset['id'])),
61+
method='DELETE',
62+
)
63+
break
64+
65+
# Upload the prebuilt.
66+
with open(upload_path, 'br') as myfile:
67+
content = myfile.read()
68+
_json = common.github_make_request(
69+
authenticate=True,
70+
data=content,
71+
extra_headers={'Content-Type': 'application/zip'},
72+
path=('/releases/' + str(release_id) + '/assets'),
73+
subdomain='uploads',
74+
url_params={'name': asset_name},
75+
)
76+
77+
if __name__ == '__main__':
78+
main()

zip-img renamed to release-zip

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
#!/usr/bin/env python3
22

3+
'''
4+
https://github.com/cirosantilli/linux-kernel-module-cheat#release-zip
5+
'''
6+
37
import os
48
import subprocess
59
import zipfile
610

711
import common
812

913
def main():
10-
outfile = os.path.join(common.out_dir, 'lkmc-{}.zip'.format(common.sha))
11-
if os.path.exists(outfile):
12-
os.unlink(outfile)
13-
zipf = zipfile.ZipFile(outfile, 'w', zipfile.ZIP_DEFLATED)
14+
os.makedirs(common.release_dir, exist_ok=True)
15+
if os.path.exists(common.release_zip_file):
16+
os.unlink(common.release_zip_file)
17+
zipf = zipfile.ZipFile(common.release_zip_file, 'w', zipfile.ZIP_DEFLATED)
1418
for arch in common.arches:
1519
common.setup(common.get_argparse(default_args={'arch': arch}))
1620
zipf.write(common.qcow2_file, arcname=os.path.relpath(common.qcow2_file, common.root_dir))

0 commit comments

Comments
 (0)