Commit 177a97ec authored by Paul McCarthy's avatar Paul McCarthy 🚵
Browse files

RF: Do not open a MR for an invalid version number. Tweaks to messages

parent 49370d4a
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
This project hosts Gitlab CI automation routines for internally hosted FSL This project hosts Gitlab CI automation routines for internally hosted FSL
projects. These routines are hosted at projects. These routines are hosted at
https://git.fmrib.ox.ac.uk/fsl/fsl-ci-rules, and are applied to most FSL project https://git.fmrib.ox.ac.uk/fsl/fsl-ci-rules, and are applied to most FSL
repositories. project repositories.
Every FSL project comprises **two** git repositories: Every FSL project comprises **two** git repositories:
...@@ -16,32 +16,37 @@ Every FSL project comprises **two** git repositories: ...@@ -16,32 +16,37 @@ Every FSL project comprises **two** git repositories:
typically hosted at `https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`. typically hosted at `https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`.
_This_ repository contains CI rules which are applied to both project and recipe _This_ repository contains CI rules which are applied to both project and
repositories to facilitate automatic building and deployment of FSL conda recipe repositories to facilitate automatic building and deployment of FSL
packages. conda packages.
Currently, all implemented rules are related to the building and deployment of **Important:** The CI rules are written under the assumption that the
conda packages for FSL projects, however there is scope for adding more general following conventions hold. If these conventions are not followed, some rules
rules (e.g. testing, building/deploying documentation, etc). will not function correctly:
**Important:** The following project and recipe repository naming conventions
are strongly encouraged, in order to allow automatic resolution of repository
URLs:
1. The FSL project repository is hosted at - The FSL project repository is hosted at
`https://git.fmrib.ox.ac.uk/fsl/<project>`. `https://git.fmrib.ox.ac.uk/fsl/<project>`.
2. The accompanying conda recipe repository is hosted at - The accompanying conda recipe repository is hosted at
`https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`. `https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`.
3. The conda package name (as defined in the recipe `meta.yaml` file) is - The conda package name (as defined in the recipe `meta.yaml` file) is
`fsl-<project>`. `fsl-<project>`.
- The `master` branch of a FSL project repository is used as the current
internal/staging release.
- New stable releases are created as tags on the FSL project repository. A
tag is used as the version number for a project, and must comprise a
sequence of monotonically increasing integers, separated with dots, and
with an optional leading `v`.
## Overview ## Overview
Currently, all implemented rules are related to the building and deployment of
conda packages for FSL projects, however there is scope for adding more general
rules (e.g. testing, building/deploying documentation, etc).
When commits are merged/pushed to the master branch of a FSL project repository When commits are merged/pushed to the master branch of a FSL project repository
at `https://git.fmrib.ox.ac.uk/fsl/<project>`, the conda recipe for that project at `https://git.fmrib.ox.ac.uk/fsl/<project>`, the conda recipe for that project
(typically hosted at `https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`) is (typically hosted at `https://git.fmrib.ox.ac.uk/fsl/conda/fsl-<project>`) is
......
...@@ -68,6 +68,7 @@ def main(): ...@@ -68,6 +68,7 @@ def main():
project_ref = os.environ['PROJECT_REF'] project_ref = os.environ['PROJECT_REF']
recipe_name = os.environ['CI_PROJECT_NAME'] recipe_name = os.environ['CI_PROJECT_NAME']
recipe_url = os.environ['CI_PROJECT_URL'] recipe_url = os.environ['CI_PROJECT_URL']
recipe_ref = os.environ['CI_COMMIT_REF_NAME']
staging = os.environ['STAGING'] staging = os.environ['STAGING']
prebuild = os.environ['PREBUILD'] prebuild = os.environ['PREBUILD']
prebuild = [p.split(':', 1) for p in prebuild] prebuild = [p.split(':', 1) for p in prebuild]
...@@ -85,12 +86,13 @@ def main(): ...@@ -85,12 +86,13 @@ def main():
sprun('conda install -y -c conda-forge conda-build') sprun('conda install -y -c conda-forge conda-build')
fprint('************************************') fprint('************************************')
fprint(f'Building conda recipe for: {recipe_name}') fprint(f'Building conda recipe for: {recipe_name}')
fprint(f'Recipe URL: {recipe_url}') fprint(f'Recipe URL: {recipe_url}')
fprint(f'Pre-built packages: {prebuild}') fprint(f'Recipe revision: {recipe_ref}')
fprint( 'Revision (empty means to build release') fprint(f'Pre-built packages: {prebuild}')
fprint(f' specified in meta.yaml): {project_ref}') fprint( 'Project revision (empty means to ')
fprint(f'FSL conda channel URL: {channel_url}') fprint(f' build release specified in meta.yaml): {project_ref}')
fprint(f'FSL conda channel URL: {channel_url}')
fprint('************************************') fprint('************************************')
build_recipe('.', project_ref, output_dir, local_channel, channel_url) build_recipe('.', project_ref, output_dir, local_channel, channel_url)
......
...@@ -15,11 +15,11 @@ else ...@@ -15,11 +15,11 @@ else
fi fi
echo "************************************" echo "************************************"
echo "Deploying built conda package for: $CI_PROJECT_NAME" echo "Deploying built conda package for: $CI_PROJECT_NAME"
echo "Recipe URL: $CI_PROJECT_URL" echo "Recipe URL: $CI_PROJECT_URL"
echo "Revision (empty means to build release" echo "Project revision (empty means to "
echo " specified in meta.yaml): $PROJECT_REF" echo " build release specified in meta.yaml): $PROJECT_REF"
echo "FSL conda channel: $channel_dir" echo "FSL conda channel: $channel_dir"
echo "************************************" echo "************************************"
# copy all package files from the conda-build # copy all package files from the conda-build
......
...@@ -89,8 +89,12 @@ def main(): ...@@ -89,8 +89,12 @@ def main():
# recipe repositories. # recipe repositories.
pkgname = load_meta_yaml('meta.yaml')['package']['name'] pkgname = load_meta_yaml('meta.yaml')['package']['name']
downstream = graph.reverse().neighbors(pkgname) downstream = graph.reverse().neighbors(pkgname)
trigger_pipeline_on_packages(
upstream, downstream, gitlab_url, token, staging) if len(downstream) == 0:
print(f'{pkgname} nas no downstream dependants - nothing to do!')
else:
trigger_pipeline_on_packages(
upstream, downstream, gitlab_url, token, staging)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -13,7 +13,7 @@ import os ...@@ -13,7 +13,7 @@ import os
import re import re
import sys import sys
from fsl_ci_utils import tempdir, sprun from fsl_ci_utils import tempdir, sprun, is_valid_project_version
from fsl_ci_utils.conda import get_recipe_url from fsl_ci_utils.conda import get_recipe_url
from fsl_ci_utils.conda_api import (http_request, from fsl_ci_utils.conda_api import (http_request,
lookup_project_id, lookup_project_id,
...@@ -115,9 +115,13 @@ def main(): ...@@ -115,9 +115,13 @@ def main():
recipe['id'] = lookup_project_id(recipe['path'], GITLAB_URL, TOKEN) recipe['id'] = lookup_project_id(recipe['path'], GITLAB_URL, TOKEN)
branch = f'mnt/rel-{PROJECT_VERSION}' branch = f'mnt/rel-{PROJECT_VERSION}'
if not is_valid_project_version(PROJECT_VERSION):
print(f'{PROJECT_VERSION} is not a valid FSL version - aborting!')
sys,exit(1)
if check_mr_already_open(recipe['id'], branch, 'master'): if check_mr_already_open(recipe['id'], branch, 'master'):
print(f'A merge request from branch {branch} is ' print(f'A merge request from branch {branch} is '
f'already open on {recipe["url"]} - aborting.') f'already open on {recipe["url"]} - aborting!')
sys.exit(1) sys.exit(1)
checkout_and_patch_recipe(recipe["url"], branch, PROJECT_VERSION) checkout_and_patch_recipe(recipe["url"], branch, PROJECT_VERSION)
......
...@@ -8,13 +8,11 @@ ...@@ -8,13 +8,11 @@
import os import os
import shlex import shlex
import string
import tempfile import tempfile
import contextlib as ctxlib import contextlib as ctxlib
import subprocess as sp import subprocess as sp
import fsl_ci_utils.conda_api as api # noqa # pylint: disable=unused-import
import fsl_ci_utils.conda as conda # noqa # pylint: disable=unused-import
def fprint(*args, **kwargs): def fprint(*args, **kwargs):
"""Print with flush=True. """ """Print with flush=True. """
...@@ -54,3 +52,17 @@ def sprun(cmd, **kwargs): ...@@ -54,3 +52,17 @@ def sprun(cmd, **kwargs):
print(f'Running {cmd}') print(f'Running {cmd}')
cmd = shlex.split(cmd) cmd = shlex.split(cmd)
return sp.run(cmd, check=True, **kwargs) return sp.run(cmd, check=True, **kwargs)
def is_valid_project_version(version):
"""Return True if the given version/tag is "valid" - it must
be a sequence of integers, separated by periods, with an optional
leading 'v'.
"""
if version.lower().startswith('v'):
version = version[1:]
for part in version.split('.'):
if not all([c in string.digits for c in part]):
return False
return True
...@@ -159,7 +159,6 @@ def load_packages(channeldata : Dict, ...@@ -159,7 +159,6 @@ def load_packages(channeldata : Dict,
# multiple files for each package, each for a # multiple files for each package, each for a
# different version). Find the entry corresponding # different version). Find the entry corresponding
# to the latest version. # to the latest version.
print(f'Searching for {pkg.name} == {version} in {platform}...')
for fmeta in platformdata[platform]['packages'].values(): for fmeta in platformdata[platform]['packages'].values():
if fmeta['name'] == pkg.name and \ if fmeta['name'] == pkg.name and \
fmeta['version'] == pkg.version: fmeta['version'] == pkg.version:
......
...@@ -8,12 +8,13 @@ ...@@ -8,12 +8,13 @@
import json import json
import time import time
import datetime import datetime
import string
import base64 as b64 import base64 as b64
import functools as ft import functools as ft
import urllib.parse as urlparse import urllib.parse as urlparse
import urllib.request as urlrequest import urllib.request as urlrequest
from fsl_ci_utils import is_valid_project_version
def http_request(url, token=None, data=None, method=None): def http_request(url, token=None, data=None, method=None):
"""Submit a HTTP request to the given URL. """ """Submit a HTTP request to the given URL. """
...@@ -122,20 +123,6 @@ def lookup_project_tags(project_path, server, token): ...@@ -122,20 +123,6 @@ def lookup_project_tags(project_path, server, token):
return tags return tags
def is_acceptable(version):
"""Return True if the given version/tag is "acceptable" - it must
be a sequence of integers, separated by periods, with an optional
leading 'v'.
"""
if version.lower().startswith('v'):
version = version[1:]
for part in version.split('.'):
if not all([c in string.digits for c in part]):
return False
return True
def get_project_version(project_path, server, token): def get_project_version(project_path, server, token):
"""Return the most recent version of the specified project, returning """Return the most recent version of the specified project, returning
"YYMM.0" if the project does not have any tags. "YYMM.0" if the project does not have any tags.
...@@ -143,7 +130,7 @@ def get_project_version(project_path, server, token): ...@@ -143,7 +130,7 @@ def get_project_version(project_path, server, token):
tags = lookup_project_tags(project_path, server, token) tags = lookup_project_tags(project_path, server, token)
version = None version = None
if len(tags) >= 0 and is_acceptable(tags[0]): if len(tags) >= 0 and is_valid_project_version(tags[0]):
version = tags[0] version = tags[0]
if version is None: if version is None:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment