From 2e92d1c1ab8cb07d2134334f5a671f066f156315 Mon Sep 17 00:00:00 2001 From: s3lph Date: Sun, 4 Nov 2018 02:35:33 +0100 Subject: [PATCH] Testing automated release, simplified packaging stage --- .gitlab-ci.yml | 32 +++++++---- CHANGELOG.md | 17 ++++++ package/release.py | 137 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 12 deletions(-) create mode 100644 CHANGELOG.md create mode 100755 package/release.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff40b95..880eb01 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,7 +4,7 @@ image: s3lph/matemat-ci:20181103-01 stages: - test - build -- staging +- deploy @@ -45,15 +45,15 @@ build_docker: build_wheel: stage: build script: - - python3.6 setup.py egg_info --tag-build "+$CI_COMMIT_SHA" --tag-date bdist_wheel - - python3.6 setup.py egg_info --tag-build "+$CI_COMMIT_REF_NAME" --tag-date bdist_wheel + - python3.6 setup.py egg_info bdist_wheel + - cd dist + - sha256sum *.whl > SHA256SUMS artifacts: paths: - "dist/*.whl" + - dist/SHA256SUMS only: - 27-deployment - - staging - - master - tags build_debian: @@ -70,14 +70,14 @@ build_debian: - rm -rf matemat/usr/bin - find . -type f -exec sed -re "s#${PYTHON_BIN}#/usr/bin/python3.6#g" -i {} \; - dpkg-deb --build matemat - - mv matemat.deb "matemat_${MATEMAT_VERSION}+${CI_COMMIT_REF_NAME}-1_all.deb" + - mv matemat.deb "matemat_${MATEMAT_VERSION}-1_all.deb" + - sha256sum *.deb > SHA256SUMS artifacts: paths: - "package/debian/*.deb" + - package/debian/SHA256SUMS only: - 27-deployment - - staging - - master - tags build_archlinux: @@ -94,20 +94,19 @@ build_archlinux: - rm -rf matemat/usr/bin - sed -re "s/__VERSION__/${MATEMAT_VERSION}/g" -i PKGBUILD - sudo -u nobody makepkg -c - - mv matemat-${MATEMAT_VERSION}-1-any.pkg.tar.xz "matemat-${MATEMAT_VERSION}+${CI_COMMIT_REF_NAME}-1-any.pkg.tar.xz" + - sha256sum *.pkg.tar.xz > SHA256SUMS artifacts: paths: - "package/archlinux/*.pkg.tar.xz" + - package/archlinux/SHA256SUMS only: - 27-deployment - - staging - - master - tags staging: - stage: staging + stage: deploy script: - eval $(ssh-agent -s) - ssh-add - <<<"$STAGING_SSH_PRIVATE_KEY" @@ -117,3 +116,12 @@ staging: url: https://matemat.kernelpanic.lol/ only: - staging + + + +release: + stage: deploy + script: + - python package/release.py + only: + - tags diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a8aa755 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,17 @@ +# Matemat Changelog + + +## Version 0.1 + +This is only a test for the release CI task - please ignore. + +The packages attached to this release have not been tested. + +### Changes + + +- Added CI release task. +- Went back to Python 3.6 for Debian packaging. + + + diff --git a/package/release.py b/package/release.py new file mode 100755 index 0000000..65b6599 --- /dev/null +++ b/package/release.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 + +from typing import Any, Dict, Optional, Tuple + +import os +import sys +import json +import urllib.request +import http.client +from urllib.error import HTTPError + + +def parse_changelog(tag: str) -> Optional[str]: + release_changelog: str = '' + with open('CHANGELOG.md', 'r') as f: + in_target: bool = False + done: bool = False + for line in f.readlines(): + if in_target: + if f'' in line: + done = True + break + release_changelog += line + elif f'' in line: + in_target = True + continue + if not done: + return None + return release_changelog + + +def fetch_single_shafile(url: str) -> str: + req = urllib.request.Request(url) + try: + resp: http.client.HTTPResponse = urllib.request.urlopen(req) + except HTTPError as e: + print(e.read().decode()) + sys.exit(1) + resp_data: bytes = resp.readline() + shafile: str = resp_data.decode() + filename: str = shafile.strip().split(' ')[-1].strip() + return filename + + +def fetch_wheel_url(base_url: str) -> Optional[Tuple[str, str]]: + wheel_sha_url: str = f'{base_url}/dist/SHA256SUMS?job=build_wheel' + wheel_filename: str = fetch_single_shafile(wheel_sha_url) + wheel_url: str = f'{base_url}/dist/{wheel_filename}?job=build_wheel' + return wheel_url, wheel_sha_url + + +def fetch_debian_url(base_url: str) -> Optional[Tuple[str, str]]: + debian_sha_url: str = f'{base_url}/package/debian/SHA256SUMS?job=build_debian' + debian_filename: str = fetch_single_shafile(debian_sha_url) + debian_url: str = f'{base_url}/package/debian/{debian_filename}?job=build_debian' + return debian_url, debian_sha_url + + +def fetch_arch_url(base_url: str) -> Optional[Tuple[str, str]]: + arch_sha_url: str = f'{base_url}/package/archlinux/SHA256SUMS?job=build_archlinux' + arch_filename: str = fetch_single_shafile(arch_sha_url) + arch_url: str = f'{base_url}/package/archlinux/{arch_filename}?job=build_archlinux' + return arch_url, arch_sha_url + + +def main(): + api_token: Optional[str] = os.getenv('GITLAB_API_TOKEN') + release_tag: Optional[str] = os.getenv('CI_COMMIT_TAG') + project_name: Optional[str] = os.getenv('CI_PROJECT_PATH') + project_id: Optional[str] = os.getenv('CI_PROJECT_ID') + if api_token is None: + print('GITLAB_API_TOKEN is not set.', file=sys.stderr) + sys.exit(1) + if release_tag is None: + print('CI_COMMIT_TAG is not set.', file=sys.stderr) + sys.exit(1) + if project_name is None: + print('CI_PROJECT_PATH is not set.', file=sys.stderr) + sys.exit(1) + if project_id is None: + print('CI_PROJECT_ID is not set.', file=sys.stderr) + sys.exit(1) + + changelog: Optional[str] = parse_changelog(release_tag) + if changelog is None: + print('Changelog could not be parsed.', file=sys.stderr) + sys.exit(1) + + base_url: str = f'https://gitlab.com/{project_name}/-/jobs/artifacts/{release_tag}/raw' + + wheel_url, wheel_sha_url = fetch_wheel_url(base_url) + debian_url, debian_sha_url = fetch_wheel_url(base_url) + arch_url, arch_sha_url = fetch_wheel_url(base_url) + + augmented_changelog = f'''{changelog.strip()} + +### Download + +- [Python Wheel]({wheel_url}) ([sha256]({wheel_sha_url})) +- [Debian Package]({debian_url}) ([sha256]({debian_sha_url})) +- [Arch Linux Package]({arch_url}) ([sha256]({arch_sha_url}))''' + + encoder = json.encoder.JSONEncoder() + decoder = json.decoder.JSONDecoder() + post_body: str = encoder.encode({'description': augmented_changelog}) + + gitlab_release_api_url: str = \ + f'https://gitlab.com/api/v4/projects/{project_id}/repository/tags/{release_tag}/release' + headers: Dict[str, str] = { + 'Private-Token': api_token + } + + request = urllib.request.Request( + gitlab_release_api_url, + post_body.encode('utf-8'), + headers=headers, + method='POST' + ) + try: + response: http.client.HTTPResponse = urllib.request.urlopen(request) + except HTTPError as e: + print(e.read().decode()) + sys.exit(1) + response_bytes: bytes = response.read() + response_str: str = response_bytes.decode() + response_data: Dict[str, Any] = decoder.decode(response_str) + + if response_data['tag_name'] != release_tag: + print('Something went wrong...', file=sys.stderr) + print(response_str, file=sys.stderr) + sys.exit(1) + + print(response_data['description']) + + +if __name__ == '__main__': + main()