Skip to content

Commit

Permalink
chore(release): Scripts to publish automatically a release. (#852)
Browse files Browse the repository at this point in the history
  • Loading branch information
GerardPaligot authored and monperrus committed Sep 29, 2016
1 parent 3bd2965 commit 7a4a80d
Show file tree
Hide file tree
Showing 2 changed files with 348 additions and 0 deletions.
165 changes: 165 additions & 0 deletions doc/_release/deploy_archives.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import json as json_converter
import os
import re
import requests


def _file_value(settings_filename, expected):
with open(settings_filename) as settings:
for line in settings:
key, value = line.split(':')[:2]
if key == expected:
return value
raise EOFError


def _os_value(key, default_value=None):
try:
return os.environ[key]
except KeyError:
return default_value


class GitHubRelease(object):
base_url = 'https://api.github.com/repos/INRIA/spoon'

def __init__(self, settings_file):
super(GitHubRelease, self).__init__()
self.settings_file = settings_file

def _headers(self):
return {
'Authorization': 'Token ' + _file_value(self.settings_file, 'TOKEN')
}

def get(self, url):
response = requests.get(self.base_url + url, headers=self._headers())
return json_converter.loads(response.text)

def post(self, url, data=None, json=None, headers=None):
if not json:
json = {}
if not headers:
headers = self._headers()
if not data:
data = {}
response = requests.post(self.base_url + url, data=data, json=json, headers=headers)
return json_converter.loads(response.text)

def delete(self, url):
requests.delete(self.base_url + url, headers=self._headers())

def _create(self, tag, name):
return self.post('/releases', json={
'tag_name': tag,
'name': name,
'body': 'Changelog here.'
})

def _upload_asset(self, upload_url, filename):
self.base_url = upload_url.replace('{?name,label}', '?name={}'.format(os.path.basename(filename)))
headers = self._headers()
headers['Content-Type'] = 'application/zip'
data = open(filename, 'r').read()
return self.post('', data=data, headers=headers)

def perform(self, tag, name, assets):
release = self._create(tag, name)
for asset in assets:
self._upload_asset(release['upload_url'], asset[1])


class GforgeRelease(object):
base_url = 'https://gforge.inria.fr'
id_spoon = '86'
group_spoon = '73'
session = requests.Session()

def __init__(self, settings_file):
super(GforgeRelease, self).__init__()
self.settings_file = settings_file

def get(self, url, params=None):
if not params:
params = {}
return self.session.get(self.base_url + url, params=params)

def post(self, url, data=None, files=None):
if not data:
data = {}
if not files:
files = {}
return self.session.post(self.base_url + url, data=data, files=files)

def login(self, return_to='/'):
self.session = requests.Session()
url = '/plugins/authbuiltin/post-login.php'
response = self.get(url)
form_key = re.search('<input type="hidden" name="form_key" value="(.*)" />', response.text)
payload = {
'form_loginname': _file_value(self.settings_file, 'USERNAME'),
'form_pw': _file_value(self.settings_file, 'PASSWORD_FORGE'),
'return_to': return_to,
'form_key': form_key.group(1),
'login': 'Identification'
}
return self.get(url, payload)

def _create(self, name, asset):
self.login('/frs/?view=qrs&group_id={}'.format(self.group_spoon))
url = '/frs/?group_id={}&action=addrelease'.format(self.group_spoon)
payload = {
'package_id': self.id_spoon,
'release_name': re.search('Spoon ([0-9]+.[0-9]+.[0-9]+)', name).group(1),
'type_id': asset[0],
'processor_id': '100',
'release_changes': 'Changelog here.',
'release_notes': '',
'preformatted': '1',
'submit': 'Create release'
}
files = {
'userfile': open(asset[1], 'r')
}
return self.post(url, data=payload, files=files)

def _upload_asset(self, release_id, asset):
self.login(
'/frs/?view=editrelease&group_id={}&package_id={}&release_id={}'
.format(self.group_spoon, self.id_spoon, release_id))
url = '/frs/?group_id={}&package_id={}&release_id={}&action=addfile' \
.format(self.group_spoon, self.id_spoon, release_id)
payload = {
'type_id': asset[0],
'processor_id': '100',
'submit': 'Add This File'
}
files = {
'userfile': open(asset[1], 'r')
}
return self.post(url, data=payload, files=files)

def perform(self, name, assets):
response = self._create(name, assets[0])
release_id = re.search('<tr id="releaseid([0-9]+)" class="bgcolor-white ff">', response.text).group(1)
for asset in assets[1:]:
self._upload_asset(release_id, asset)


type_ = _os_value('TYPE', 'minor')
settings_file = _os_value('SETTINGS_PATH', '/builds/resources/settings.txt')
release = _os_value('RELEASE')

tag_name = 'spoon-core-{}'.format(release)
name = 'Spoon {}'.format(release)
assets = [
('3000', 'target/{}.jar'.format(tag_name)),
('5000', 'target/{}-jar-with-dependencies.jar'.format(tag_name)),
('8200', 'target/{}-javadoc.jar'.format(tag_name)),
('5000', 'target/{}-sources.jar'.format(tag_name))
]
github = GitHubRelease(settings_file)
github.perform(tag_name, name, assets)

gforge = GforgeRelease(settings_file)
gforge.perform(name, assets)
183 changes: 183 additions & 0 deletions doc/_release/deploy_production.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#!/bin/bash
#
# Deploys a new release of Spoon. This script uses the maven
# release plugin to deploy the project or rollback if we got any
# error during the deployment.
# Note that this script doesn't make the git clone. Think to do it by yourself
# or to execute this script in a Spoon repository.

USER_SERVER="spoon-bot"
SERVER="${USER_SERVER}@scm.gforge.inria.fr"
HOST_DESTINATION="/home/groups/spoon/"
FOLDER_DESTINATION="spoon.git"
DESTINATION="${HOST_DESTINATION}${FOLDER_DESTINATION}/"

# Determine the type.

MAJOR=0
MINOR=1
PATCH=2
TYPES=('major' 'minor' 'patch')
if [ -z "$TYPE" ]; then
TYPE='minor'
fi
if ! [[ ${TYPES[*]} =~ "$TYPE" ]]; then
echo "Error: type should be 'major', 'minor' or 'patch'!"
exit 1
fi
if [[ ${TYPES[$PATCH]} = $TYPE ]]; then
git checkout stable
fi

# Save the current release version.

RELEASE_TEXT=$(grep "^spoon_release:" doc/_jekyll/_config.yml | cut -d' ' -f2-)
REGEX="^\"([0-9]+).([0-9]+).([0-9]+)\"$"
if [[ $RELEASE_TEXT =~ $REGEX ]]; then
RVERSIONS[0]="${BASH_REMATCH[1]}"
RVERSIONS[1]="${BASH_REMATCH[2]}"
RVERSIONS[2]="${BASH_REMATCH[3]}"
else
echo "Error: Can't get the last release version from jekyll config file."
exit 1
fi

# Save the next version.

if [[ ${TYPES[$MAJOR]} = $TYPE ]]; then
NSVERSIONS[0]=$((RVERSIONS[0] + 1))
NSVERSIONS[1]=1
NSVERSIONS[2]=0
NRVERSIONS[0]=$((RVERSIONS[0] + 1))
NRVERSIONS[1]=0
NRVERSIONS[2]=0
elif [[ ${TYPES[$MINOR]} = $TYPE ]]; then
NSVERSIONS[0]=${RVERSIONS[0]}
NSVERSIONS[1]=$((RVERSIONS[1] + 2))
NSVERSIONS[2]=0
NRVERSIONS[0]=${RVERSIONS[0]}
NRVERSIONS[1]=$((RVERSIONS[1] + 1))
NRVERSIONS[2]=0
elif [[ ${TYPES[$PATCH]} = $TYPE ]]; then
NSVERSIONS[0]=${RVERSIONS[0]}
NSVERSIONS[1]=$((RVERSIONS[1] + 1))
NSVERSIONS[2]=0
NRVERSIONS[0]=${RVERSIONS[0]}
NRVERSIONS[1]=${RVERSIONS[1]}
NRVERSIONS[2]=$((RVERSIONS[2] + 1))
fi

OLD_RELEASE="${RVERSIONS[0]}.${RVERSIONS[1]}.${RVERSIONS[2]}"
NEXT_SNAPSHOT="${NSVERSIONS[0]}.${NSVERSIONS[1]}.${NSVERSIONS[2]}-SNAPSHOT"
NEXT_RELEASE="${NRVERSIONS[0]}.${NRVERSIONS[1]}.${NRVERSIONS[2]}"
TAG="spoon-core-$NEXT_RELEASE"

echo "You'll create a $TYPE version $NEXT_RELEASE and the next snapshot will be $NEXT_SNAPSHOT"

# Release to Maven Central.

mvn release:clean
if [ "$?" -ne 0 ]; then
echo "Can't clean the project for the release!"
mvn release:rollback
if [ "$?" -ne 0 ]; then
echo "Can't rollback at the clean step!"
fi
exit 1
fi

mvn release:prepare -DreleaseVersion=$NEXT_RELEASE -DdevelopmentVersion=$NEXT_SNAPSHOT -Dtag=$TAG
if [ "$?" -ne 0 ]; then
echo "Can't prepare the project for the release!"
mvn release:rollback
if [ "$?" -ne 0 ]; then
echo "Can't rollback at the prepare step!"
fi
exit 1
fi

mvn release:perform -Dusername=$USER_SERVER
if [ "$?" -ne 0 ]; then
echo "Can't perform the project for the release!"
mvn release:rollback
if [ "$?" -ne 0 ]; then
echo "Can't rollback at the perform step!"
fi
exit 1
fi

# Updates Jekyll documentation.

sed -i -re "s/^spoon_release: \"[0-9]+.[0-9]+.[0-9]+\"/spoon_release: \"$NEXT_RELEASE\"/;s/^sidebar_version: version [0-9]+.[0-9]+.[0-9]+/sidebar_version: version $NEXT_RELEASE/;s/^spoon_snapshot: \"[0-9]+.[0-9]+.[0-9]+-SNAPSHOT\"/spoon_snapshot: \"$NEXT_SNAPSHOT\"/" doc/_config.yml
if [ "$?" -ne 0 ]; then
echo "Can't update new versions in the jekyll config file."
echo "rollback at the previous state..."
git checkout doc/_config.yml
exit 1
fi

DATE=$(date +"%B %d, %Y: Spoon $NEXT_RELEASE is released.")
DATE="$(tr '[:lower:]' '[:upper:]' <<< ${DATE:0:1})${DATE:1}"
DATE="- $DATE"
awk -i inplace -v date="$DATE" '{print} /^<!-- .* Marker comment. -->$/ {print date}' doc/doc_homepage.md
if [ "$?" -ne 0 ]; then
echo "Can't update news feed in the website."
echo "rollback at the previous state..."
git checkout doc/doc_homepage.md
exit 1
fi

# Updates Readme.

sed -i -re "s/<version>$OLD_RELEASE<\/version>/<version>$NEXT_RELEASE<\/version>/;s/<version>[0-9]+.[0-9]+.[0-9]+-SNAPSHOT<\/version>/<version>$NEXT_SNAPSHOT<\/version>/" README.md
if [ "$?" -ne 0 ]; then
echo "Can't update new versions in the README file."
echo "rollback at the previous state..."
git checkout README.md
exit 1
fi

# Commit changes.

echo "What is changes?"

git diff
git add . --all
git commit -m "docs(version): Updates documentation."
if [[ ${TYPES[$PATCH]} = $TYPE ]]; then
git push origin stable
else
git push origin master
fi

# Updates stable branch.

if [[ ${TYPES[$PATCH]} != $TYPE ]]; then
git checkout master
git branch -D stable
git checkout -b stable
git push origin stable -f
fi

# Retrieves all commits and tag from GitHub repo to INRIA Forge.

ssh -A $SERVER "cd ${DESTINATION} && git fetch origin master:master"
if [ "$?" -ne 0 ]; then
echo "Error when you fetch sources from GitHub for the master branch!"
exit 1
fi

ssh -A $SERVER "cd ${DESTINATION} && git fetch origin stable:stable"
if [ "$?" -ne 0 ]; then
echo "Error when you fetch sources from GitHub for the stable branch!"
exit 1
fi

ssh -A $SERVER "cd ${DESTINATION} && git fetch --tags"
if [ "$?" -ne 0 ]; then
echo "Error when you fetch tags!"
exit 1
fi

echo RELEASE="$NEXT_RELEASE" > target/variables.properties
echo SNAPSHOT="$NEXT_SNAPSHOT" >> target/variables.properties

0 comments on commit 7a4a80d

Please sign in to comment.