From 35e6df6f7ec8e927f02acf9ae6f1408717914f6e Mon Sep 17 00:00:00 2001 From: Paul McCarthy <pauldmccarthy@gmail.com> Date: Thu, 22 Nov 2018 21:31:32 +0000 Subject: [PATCH] CI: Auto-zenodo deposit on releases --- .ci/zenodo.py | 92 +++++++++++++++++++++++++++++++++++++ .ci/zenodo_deposit.sh | 26 +++++++++++ .ci/zenodo_meta.json.jinja2 | 19 ++++++++ .gitlab-ci.yml | 23 ++++++++++ 4 files changed, 160 insertions(+) create mode 100644 .ci/zenodo.py create mode 100644 .ci/zenodo_deposit.sh create mode 100644 .ci/zenodo_meta.json.jinja2 diff --git a/.ci/zenodo.py b/.ci/zenodo.py new file mode 100644 index 000000000..116645ecf --- /dev/null +++ b/.ci/zenodo.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# Deposit a new version of something on zenodo. +# +# It is assumed that a deposit already exists on zenodo - you must +# specify the deposit ID of that original deposit. +# +# http://developers.zenodo.org/#rest-api + + +import os.path as op +import sys +import json + +import jinja2 as j2 +import requests + + +def deposit(zenodo_url, access_token, dep_id, upload_file, meta): + + urlbase = '{}/api/deposit/depositions'.format(zenodo_url) + headers = {'Content-Type': 'application/json'} + params = {'access_token' : access_token} + + # Create a new deposit + url = '{}/{}/actions/newversion'.format(urlbase, dep_id) + print('Creating new deposit: {}'.format(url)) + r = requests.post(url, params=params) + if r.status_code != 201: + raise RuntimeError('POST {} failed: {}'.format(url, r.status_code)) + + newurl = r.json()['links']['latest_draft'] + dep_id = newurl.split('/')[-1] + + print("New deposition ID: {}".format(dep_id)) + + # Upload the file + data = {'filename': op.basename(upload_file)} + files = {'file': open(upload_file, 'rb')} + url = '{}/{}/files'.format(urlbase, dep_id) + print('Uploading file: {}'.format(url)) + r = requests.post(url, params=params, data=data, files=files) + + if r.status_code != 201: + raise RuntimeError('POST {} failed: {}'.format(url, r.status_code)) + + # Upload the metadata + + url = '{}/{}?access_token={}'.format(urlbase, dep_id, access_token) + print('Uploading metadata: {}'.format(url)) + r = requests.put(url, data=json.dumps(meta), headers=headers) + + if r.status_code != 200: + print(r.json()) + raise RuntimeError('PUT {} failed: {}'.format(url, r.status_code)) + + # Publish + url = '{}/{}/actions/publish'.format(urlbase, dep_id) + print('Publishing: {}'.format(url)) + r = requests.post(url, params=params) + + if r.status_code != 202: + raise RuntimeError('POST {} failed: {}'.format(url, r.status_code)) + + +def make_meta(templatefile, version, date): + with open(templatefile, 'rt') as f: + template = f.read() + + template = j2.Template(template) + + env = { + 'VERSION' : version, + 'DATE' : date, + } + + return json.loads(template.render(**env)) + + +if __name__ == '__main__': + + zurl = sys.argv[1] + tkn = sys.argv[2] + depid = sys.argv[3] + upfile = sys.argv[4] + metafile = sys.argv[5] + version = sys.argv[6] + date = sys.argv[7] + + meta = make_meta(metafile, version, date) + + deposit(zurl, tkn, depid, upfile, meta) diff --git a/.ci/zenodo_deposit.sh b/.ci/zenodo_deposit.sh new file mode 100644 index 000000000..32856bb59 --- /dev/null +++ b/.ci/zenodo_deposit.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +tmp=`dirname $0` +pushd $tmp > /dev/null +thisdir=`pwd` +popd > /dev/null + +zenodo_url=$1 +zenodo_tkn=$2 +zenodo_depid=$3 + +version=`python setup.py -V` +upfile=`pwd`/dist/fslpy-"$version".tar.gz +metafile=`pwd`/.ci/zenodo_meta.json.jinja2 +date=`date +"%Y-%m-%d"` + +pip install --retries 10 requests jinja2 + +python "$thisdir"/zenodo.py \ + "$zenodo_url" \ + "$zenodo_tkn" \ + "$zenodo_depid" \ + "$upfile" \ + "$metafile" \ + "$version" \ + "$date" diff --git a/.ci/zenodo_meta.json.jinja2 b/.ci/zenodo_meta.json.jinja2 new file mode 100644 index 000000000..0da8ea8ea --- /dev/null +++ b/.ci/zenodo_meta.json.jinja2 @@ -0,0 +1,19 @@ +{ + "metadata" : { + "title" : "fslpy", + "upload_type" : "software", + "version" : "{{VERSION}}", + "publication_date" : "{{DATE}}", + "description" : "<p>The fslpy project is a <a href=\"https://fsl.fmrib.ox.ac.uk/fsl/fslwiki\">FSL</a> programming library written in Python. It is used by <a href=\"http://git.fmrib.ox.ac.uk/fsl/fsleyes/fsleyes/\">FSLeyes</a>.</p>\n\n<p>The fslpy library is developed at the Wellcome Centre for Integrative Neuroimaging (FMRIB), at the University of Oxford. It is hosted at <a href=\"https://git.fmrib.ox.ac.uk/fsl/fslpy/\">https://git.fmrib.ox.ac.uk/fsl/fslpy/</a>.</p>", + "keywords" : ["python", "mri", "neuroimaging", "neuroscience"], + "access_right" : "open", + "license" : "Apache-2.0", + "creators" : [ + { "name" : "McCarthy, Paul" }, + { "name" : "Cottaar, Michiel" }, + { "name" : "Webster, Matthew" }, + { "name" : "Fitzgibbon, Sean" }, + { "name" : "Craig, Martin" } + ] + } +} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 804ea4d68..5a7ceb6c1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,6 +77,12 @@ stages: # - TWINE_PASSWORD: - Password to use when uploading to pypi # # - TWINE_REPOSITORY_URL: - Pypi repository to upload to +# +# - ZENODO_URL: - Zenodo URL to deposit release file to. +# +# - ZENODO_TOKEN: - Zenodo access token. +# +# - ZENODO_DEPOSIT_ID: - Deposit ID of previous Zenodo deposit. ############################################################################### @@ -263,3 +269,20 @@ deploy-pypi: script: - bash ./.ci/deploy_pypi.sh + + +deploy-zenodo + <<: *only_releases + <<: *setup_ssh + stage: deploy + when: manual + image: python3.6 + + tags: + - docker + + dependencies: + - build-pypi-dist + + script: + - bash ./.ci/zenodo_deposit.sh "$ZENODO_URL" "$ZENODO_TOKEN" "$ZENODO_DEPOSIT_ID" -- GitLab