Merge pull request #52 from ralphlange/devel/gh-actions

Add support for GitHub Actions
This commit is contained in:
Ralph Lange
2020-06-29 10:45:23 +02:00
committed by GitHub
9 changed files with 571 additions and 74 deletions

View File

@@ -37,6 +37,7 @@ skip_commits:
- '**/*.html'
- '**/*.md'
- '.travis.yml'
- '.github/workflows/*'
#---------------------------------#
# additional packages #

156
.github/workflows/build-and-test.yml vendored Normal file
View File

@@ -0,0 +1,156 @@
name: ci-scripts build/test
on:
push:
branches: [ devel/gh-actions ]
env:
SETUP_PATH: .:.ci
SET: test01
VV: 1
BASE_RECURSIVE: NO
CMP: gcc
APT: re2c
CHOCO: re2c
BREW: re2c
jobs:
unit-test:
name: Unit tests on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, windows-2019, windows-2016, macos-10.15]
steps:
- uses: actions/checkout@v2
- name: Show initial environment
run: python cue-test.py env
- name: Run unit tests
run: python cue-test.py
build-linux:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
cmp: [gcc, clang]
configuration: [default, static, debug, static-debug]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module (example app)
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-macos:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [macos-10.15]
cmp: [clang]
configuration: [default, debug]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module (example app)
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-windows:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [windows-2019, windows-2016]
cmp: [gcc, vs2019, vs2017]
configuration: [default, static, debug, static-debug]
exclude:
- os: windows-2019
cmp: vs2017
- os: windows-2016
cmp: vs2019
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module (example app)
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-rtems:
name: RTEMS${{ matrix.rtems }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
RTEMS: ${{ matrix.rtems }}
APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64 qemu-system-x86
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
cmp: [gcc]
configuration: [default, static, debug, static-debug]
rtems: ["4.9", "4.10"]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module (example app)
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-wine:
name: WINE${{ matrix.wine }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
WINE: ${{ matrix.wine }}
APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
cmp: [gcc]
configuration: [default, static, debug, static-debug]
wine: [32, 64]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module (example app)
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results

View File

@@ -1,6 +1,7 @@
<a target="_blank" href="http://semver.org">![Version][badge.version]</a>
<a target="_blank" href="https://travis-ci.org/epics-base/ci-scripts">![Travis status][badge.travis]</a>
<a target="_blank" href="https://ci.appveyor.com/project/epics-base/ci-scripts">![AppVeyor status][badge.appveyor]</a>
<a target="_blank" href="https://github.com/epics-base/ci-scripts/actions">![GitHub Actions status][badge.gh-actions]</a>
# Continuous Integration for EPICS Modules
@@ -58,12 +59,12 @@ levels as the example files.
### [Travis-CI](https://travis-ci.org/)
- Five parallel runners on Linux/Windows (one runner on MacOS)
- Use different compilers (gcc, clang)
- Use different gcc versions
- Cross-compile for Windows 32bit and 64bit using MinGW and WINE
- Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
- Ubuntu 12/14/16/18, MacOS 10.13, Windows Server v1809
- Compile natively on Linux (different versions of gcc, clang)
- Compile natively on MacOS (clang)
- Compile natively on Windows (gcc/MinGW, Visual Studio 2017)
- Cross-compile for Windows 32bit and 64bit using MinGW and WINE
- Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
- Built dependencies are cached (for faster builds).
See specific
@@ -72,8 +73,8 @@ for more details.
### [AppVeyor](https://www.appveyor.com/)
- One parallel runner (all builds are sequential)
- Use different compilers (Visual Studio, gcc/MinGW)
- Use different Visual Studio versions: \
- Windows Server 2012/2016/2019
- Compile using gcc/MinGW or different Visual Studio versions: \
2008, 2010, 2012, 2013, 2015, 2017, 2019
- Compile for Windows 32bit and 64bit
- No useful caching available.
@@ -82,15 +83,30 @@ See specific
**[ci-scripts on AppVeyor README](appveyor/README.md)**
for more details.
### [GitHub Actions](https://github.com/)
- 20 parallel runners on Linux/Windows (5 runners on MacOS)
- Ubuntu 16/18/20, MacOS 10.15, Windows Server 2016/2019
- Compile natively on Linux (gcc, clang)
- Compile natively on MacOS (clang)
- Compile natively on Windows (gcc/MinGW, Visual Studio 2017 & 2019)
- Cross-compile for Windows 32bit and 64bit using MinGW and WINE
- Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
- Caching not supported by ci-scripts yet.
See specific
**[ci-scripts on GitHub Actions README](gh-actions/README.md)**
for more details.
## How to Use the CI-Scripts
1. Get an account on a supported CI service provider platform.
1. Get an account on a supported CI service provider platform
(e.g. [Travis-CI](https://travis-ci.org/),
[AppVeyor](https://www.appveyor.com/), ...)
[AppVeyor](https://www.appveyor.com/), ...).
GitHub Actions does not require a separate account.
(More details in the specific README of the subdirectory.)
2. In your Support Module, add this ci-scripts repository
2. In your module, add this ci-scripts repository
as a Git Submodule (name suggestion: `.ci`).
```bash
git submodule add https://github.com/epics-base/ci-scripts .ci
@@ -405,6 +421,7 @@ in file LICENSE that is included with this distribution.
[badge.version]: https://badge.fury.io/gh/epics-base%2Fci-scripts.svg
[badge.travis]: https://travis-ci.org/epics-base/ci-scripts.svg?branch=master
[badge.appveyor]: https://ci.appveyor.com/api/projects/status/8b578alg974axvux?svg=true
[badge.gh-actions]: https://github.com/epics-base/ci-scripts/workflows/ci-scripts%20build/test/badge.svg
[reddit.bash]: https://www.reddit.com/r/bash/comments/393oqv/why_is_the_version_of_bash_included_in_os_x_so_old/

View File

@@ -3,8 +3,8 @@
## Features
- One parallel runner (all builds are sequential)
- Use different compilers (Visual Studio, gcc/MinGW)
- Use different Visual Studio versions: \
- Windows Server 2012/2016/2019
- Compile using gcc/MinGW or different Visual Studio versions: \
2008, 2010, 2012, 2013, 2015, 2017, 2019
- Compile for Windows 32bit and 64bit
- No useful caching available.

View File

@@ -31,6 +31,13 @@ if 'APPVEYOR' in os.environ:
elif re.match(r'^macOS', os.environ['APPVEYOR_BUILD_WORKER_IMAGE']):
ci_os = 'osx'
if 'GITHUB_ACTIONS' in os.environ:
ci_service = 'github-actions'
if os.environ['RUNNER_OS'] == 'macOS':
ci_os = 'osx'
else:
ci_os = os.environ['RUNNER_OS'].lower()
def find_in_file(regex, filename):
file = open(filename, "r")
@@ -324,8 +331,14 @@ class TestDefaultModuleURLs(unittest.TestCase):
@unittest.skipIf(ci_os != 'windows', 'VCVars test only applies to windows')
class TestVCVars(unittest.TestCase):
def test_vcvars(self):
if ci_service == 'appveyor':
if ci_service == 'travis':
os.environ['TRAVIS_COMPILER'] = 'vs2017'
else:
os.environ['CONFIGURATION'] = 'default'
if ci_service == 'github-actions' and os.environ['IMAGEOS'] == 'win16':
os.environ['CMP'] = 'vs2017'
else:
os.environ['CMP'] = 'vs2019'
cue.detect_context()
cue.with_vcvars('env')
@@ -676,7 +689,7 @@ class TestSetupForBuild(unittest.TestCase):
args = Namespace(paths=[])
cue.building_base = True
if ci_os == 'windows':
sp.check_call(['choco', 'install', 'make'])
sp.check_call(['choco', 'install', 'make', 'strawberryperl', '-ry'])
def setUp(self):
if ci_service == 'appveyor':
@@ -726,10 +739,10 @@ class TestSetupForBuild(unittest.TestCase):
@unittest.skipIf(ci_os != 'windows', 'HostArchPlatform test only applies to windows')
def test_HostArchPlatform(self):
if ci_service == 'travis':
platforms = ['x64']
else:
if ci_service == 'appveyor':
platforms = ['x86', 'x64']
else:
platforms = ['x64']
for platform in platforms:
for cc in ['vs2019', 'gcc']:
cue.ci['platform'] = platform
@@ -750,18 +763,17 @@ class TestSetupForBuild(unittest.TestCase):
self.assertTrue(re.search('-mingw$', os.environ['EPICS_HOST_ARCH']),
'EPICS_HOST_ARCH (found {0}) is not -mingw for {1} / {2}'
.format(os.environ['EPICS_HOST_ARCH'], cc, platform))
pattern = {'x86': 'mingw32', 'x64': 'mingw64'}
self.assertTrue(re.search(pattern[platform], os.environ['PATH']),
'Binary location for {0} not in PATH (found {1})'
.format(pattern[platform], os.environ['PATH']))
if ci_service == 'appveyor':
pattern = {'x86': 'mingw32', 'x64': 'mingw64'}
self.assertTrue(re.search(pattern[platform], os.environ['PATH']),
'Binary location for {0} not in PATH (found PATH = {1})'
.format(pattern[platform], os.environ['PATH']))
@unittest.skipIf(ci_os != 'windows', 'Strawberry perl test only applies to windows')
def test_StrawberryInPathVS2019(self):
if 'APPVEYOR' in os.environ:
os.environ['CMP'] = 'vs2019'
def test_StrawberryInPath(self):
cue.setup_for_build(self.args)
self.assertTrue(re.search('strawberry', os.environ['PATH'], flags=re.IGNORECASE),
'Strawberry Perl installed but location not in PATH (found {0})'
'Strawberry Perl location not in PATH (found PATH = {0})'
.format(os.environ['PATH']))
def setBase314(self, yesno):
@@ -827,5 +839,14 @@ if __name__ == "__main__":
if sys.argv[1:] == ['env']:
# testing with_vcvars
[print(K, '=', V) for K, V in os.environ.items()]
elif ci_os == 'windows' and sys.argv[1:] == ['findvs']:
from fnmatch import fnmatch
print('Available Visual Studio versions')
for base in (r'C:\Program Files (x86)', r'C:\Program Files'):
for root, dirs, files in os.walk(base):
for fname in files:
if fnmatch(fname, 'vcvarsall.bat'):
print('Found', os.path.join(root, fname))
sys.stdout.flush()
else:
unittest.main()

147
cue.py
View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
"""CI build script for Linux/MacOS/Windows on Travis/AppVeyor
"""CI build script for Linux/MacOS/Windows on Travis/AppVeyor/GitHub-Actions
"""
from __future__ import print_function
@@ -22,11 +22,10 @@ def detect_context():
ci['os'] = os.environ['TRAVIS_OS_NAME']
ci['platform'] = 'x64'
ci['compiler'] = os.environ['TRAVIS_COMPILER']
if ci['os'] == 'windows':
ci['choco'] += ['strawberryperl']
if re.match(r'^vs', ci['compiler']):
# Only Visual Studio 2017 available
ci['compiler'] = 'vs2017'
ci['choco'] += ['strawberryperl']
if re.match(r'^vs', ci['compiler']):
# Only Visual Studio 2017 available
ci['compiler'] = 'vs2017'
if 'BCFG' in os.environ:
buildconfig = os.environ['BCFG'].lower()
@@ -43,6 +42,24 @@ def detect_context():
ci['compiler'] = os.environ['CMP']
buildconfig = os.environ['CONFIGURATION'].lower()
if 'GITHUB_ACTIONS' in os.environ:
ci['service'] = 'github-actions'
if os.environ['RUNNER_OS'] == 'macOS':
ci['os'] = 'osx'
else:
ci['os'] = os.environ['RUNNER_OS'].lower()
ci['platform'] = 'x64'
if 'CMP' in os.environ:
ci['compiler'] = os.environ['CMP']
ci['choco'] += ['strawberryperl']
if 'BCFG' in os.environ:
buildconfig = os.environ['BCFG'].lower()
if re.search('static', buildconfig):
ci['static'] = True
if re.search('debug', buildconfig):
ci['debug'] = True
if 'STATIC' in os.environ:
print("{0}WARNING: Variable 'STATIC' not supported anymore; use 'BCFG' instead{1}"
.format(ANSI_RED, ANSI_RESET))
@@ -52,11 +69,6 @@ def detect_context():
.format(ANSI_RED, buildconfig, ANSI_RESET))
sys.stdout.flush()
if re.search('static', buildconfig):
ci['static'] = True
if re.search('debug', buildconfig):
ci['debug'] = True
if ci['static']:
ci['configuration'] = 'static'
else:
@@ -74,6 +86,9 @@ def detect_context():
if 'APT' in os.environ:
ci['apt'].extend(os.environ['APT'].split())
if 'BREW' in os.environ:
ci['homebrew'].extend(os.environ['BREW'].split())
ci['test'] = True
if 'TEST' in os.environ and os.environ['TEST'].lower() == 'no':
ci['test'] = False
@@ -130,6 +145,7 @@ def clear_lists():
ci['scriptsdir'] = ''
ci['choco'] = ['make']
ci['apt'] = []
ci['homebrew'] = []
clear_lists()
@@ -153,11 +169,16 @@ ANSI_CLEAR = "\033[0K"
# Travis log fold control
# from https://github.com/travis-ci/travis-rubies/blob/build/build.sh
# GitHub Actions fold control
# from https://github.com/actions/toolkit/blob/master/docs/commands.md#group-and-ungroup-log-lines
def fold_start(tag, title):
if ci['service'] == 'travis':
print('travis_fold:start:{0}{1}{2}{3}'
.format(tag, ANSI_YELLOW, title, ANSI_RESET))
elif ci['service'] == 'github-actions':
print('::group::{0}{1}{2}'
.format(ANSI_YELLOW, title, ANSI_RESET))
elif ci['service'] == 'appveyor':
print('{0}===== \\/ \\/ \\/ ===== START: {1} ====={2}'
.format(ANSI_YELLOW, title, ANSI_RESET))
@@ -168,6 +189,9 @@ def fold_end(tag, title):
if ci['service'] == 'travis':
print('\ntravis_fold:end:{0}\r'
.format(tag), end='')
elif ci['service'] == 'github-actions':
print('::endgroup::'
.format(ANSI_YELLOW, title, ANSI_RESET))
elif ci['service'] == 'appveyor':
print('{0}----- /\\ /\\ /\\ ----- END: {1} -----{2}'
.format(ANSI_YELLOW, title, ANSI_RESET))
@@ -181,7 +205,7 @@ elif 'HOME' in os.environ:
homedir = os.getenv('HOME')
cachedir = os.path.join(homedir, '.cache')
toolsdir = os.path.join(homedir, '.tools')
rtemsdir = os.path.join(homedir, '.rtems')
rtemsdir = r'/home/travis/.rtems' # Preliminary, until the next generation of toolchain
if 'CACHEDIR' in os.environ:
cachedir = os.environ['CACHEDIR']
@@ -189,8 +213,10 @@ if 'CACHEDIR' in os.environ:
vcvars_table = {
# https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#History
'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat'],
'vs2019': [r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat',
r'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat'],
'vs2017': [r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat',
r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat',
r'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat'],
'vs2015': [r'C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat'],
'vs2013': [r'C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat'],
@@ -551,32 +577,34 @@ def setup_for_build(args):
global is_base314, has_test_results, is_make3
dllpaths = []
logger.debug('Setting up the build environment')
if ci['os'] == 'windows':
if ci['service'] == 'appveyor':
if ci['compiler'] == 'vs2019':
# put strawberry perl in the PATH
os.environ['PATH'] = os.pathsep.join([os.path.join(r'C:\Strawberry\perl\site\bin'),
os.path.join(r'C:\Strawberry\perl\bin'),
os.environ['PATH']])
if ci['compiler'] == 'gcc':
if 'INCLUDE' not in os.environ:
os.environ['INCLUDE'] = ''
if ci['platform'] == 'x86':
os.environ['INCLUDE'] = os.pathsep.join(
[r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include',
os.environ['INCLUDE']])
os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin',
os.environ['PATH']])
elif ci['platform'] == 'x64':
os.environ['INCLUDE'] = os.pathsep.join(
[r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include',
os.environ['INCLUDE']])
os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin',
os.environ['PATH']])
if ci['service'] == 'travis':
os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\perl\site\bin', r'C:\Strawberry\perl\bin',
if os.path.exists(r'C:\Strawberry\perl\bin'):
# Put strawberry perl in front of the PATH (so that Git Perl is further behind)
logger.debug('Adding Strawberry Perl in front of the PATH')
os.environ['PATH'] = os.pathsep.join([r'C:\Strawberry\c\bin',
r'C:\Strawberry\perl\site\bin',
r'C:\Strawberry\perl\bin',
os.environ['PATH']])
if ci['service'] == 'appveyor' and ci['compiler'] == 'gcc':
logger.debug('Adding AppVeyor MSYS2/MinGW installation to PATH and INCLUDE')
if 'INCLUDE' not in os.environ:
os.environ['INCLUDE'] = ''
if ci['platform'] == 'x86':
os.environ['INCLUDE'] = os.pathsep.join(
[r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include',
os.environ['INCLUDE']])
os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin',
os.environ['PATH']])
elif ci['platform'] == 'x64':
os.environ['INCLUDE'] = os.pathsep.join(
[r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include',
os.environ['INCLUDE']])
os.environ['PATH'] = os.pathsep.join([r'C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin',
os.environ['PATH']])
# Find BASE location
if not building_base:
with open(os.path.join(cachedir, 'RELEASE.local'), 'r') as f:
@@ -588,6 +616,8 @@ def setup_for_build(args):
else:
places['EPICS_BASE'] = '.'
logger.debug('Using EPICS Base at %s', places['EPICS_BASE'])
detect_epics_host_arch()
if ci['os'] == 'windows':
@@ -611,6 +641,7 @@ def setup_for_build(args):
with open(cfg_base_version) as myfile:
if 'BASE_3_14=YES' in myfile.read():
is_base314 = True
logger.debug('Check if EPICS Base is a 3.14 series: %s', is_base314)
if not is_base314:
rules_build = os.path.join(places['EPICS_BASE'], 'configure', 'RULES_BUILD')
@@ -623,6 +654,7 @@ def setup_for_build(args):
# Check make version
if re.match(r'^GNU Make 3', sp.check_output(['make', '-v']).decode('ascii')):
is_make3 = True
logger.debug('Check if make is a 3.x series: %s', is_make3)
# apparently %CD% is handled automagically
os.environ['TOP'] = os.getcwd()
@@ -781,14 +813,17 @@ CROSS_COMPILER_TARGET_ARCHS += windows-x64-mingw''')
RTEMS_VERSION={0}
RTEMS_BASE={1}'''.format(os.environ['RTEMS'], rtemsdir))
# Base 3.15 doesn't have -qemu target architecture
qemu_suffix = ''
if os.path.exists(os.path.join(places['EPICS_BASE'], 'configure', 'os',
# Patch Base 3.15 that doesn't have -qemu target architecture
if not os.path.exists(os.path.join(places['EPICS_BASE'], 'configure', 'os',
'CONFIG.Common.RTEMS-pc386-qemu')):
qemu_suffix = '-qemu'
print('Adding RTEMS-pc386-qemu target to Base in {0}'.format(places['EPICS_BASE']))
sys.stdout.flush()
sp.check_call(['patch', '-p1', '-i',
os.path.join(ci['scriptsdir'], 'add-RTEMS-pc368-qemu-target.patch')],
cwd=places['EPICS_BASE'])
with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f:
f.write('''
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386{0}'''.format(qemu_suffix))
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu''')
host_ccmplr_name = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\1', ci['compiler'])
host_cmplr_ver_suffix = re.sub(r'^([a-zA-Z][^-]*(-[a-zA-Z][^-]*)*)+(-[0-9.]|)$', r'\3', ci['compiler'])
@@ -819,20 +854,24 @@ CMPLR_CLASS = clang''')
CC = {0}{2}
CCC = {1}{2}'''.format(host_ccmplr_name, host_cppcmplr_name, host_cmplr_ver_suffix))
# Add additional flags to CONFIG_SITE
flags_text = ''
# Add additional settings to CONFIG_SITE
extra_config = ''
if 'USR_CPPFLAGS' in os.environ:
flags_text += '''
extra_config += '''
USR_CPPFLAGS += {0}'''.format(os.environ['USR_CPPFLAGS'])
if 'USR_CFLAGS' in os.environ:
flags_text += '''
extra_config += '''
USR_CFLAGS += {0}'''.format(os.environ['USR_CFLAGS'])
if 'USR_CXXFLAGS' in os.environ:
flags_text += '''
extra_config += '''
USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
if flags_text:
if ci['service'] == 'github-actions' and ci['os'] == 'windows':
extra_config += '''
PERL = C:/Strawberry/perl/bin/perl -CSD'''
if extra_config:
with open(os.path.join(places['EPICS_BASE'], 'configure', 'CONFIG_SITE'), 'a') as f:
f.write(flags_text)
f.write(extra_config)
fold_end('set.up.epics_build', 'Configuring EPICS build system')
@@ -841,7 +880,7 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
if ci['os'] == 'windows' and ci['choco']:
fold_start('install.choco', 'Installing CHOCO packages')
sp.check_call(['choco', 'install'] + ci['choco'])
sp.check_call(['choco', 'install'] + ci['choco'] + ['-y', '--limitoutput', '--no-progress'])
fold_end('install.choco', 'Installing CHOCO packages')
if ci['os'] == 'linux' and ci['apt']:
@@ -849,6 +888,11 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
sp.check_call(['sudo', 'apt-get', '-y', 'install'] + ci['apt'])
fold_end('install.apt', 'Installing APT packages')
if ci['os'] == 'osx' and ci['homebrew']:
fold_start('install.homebrew', 'Installing Homebrew packages')
sp.check_call(['brew', 'install'] + ci['homebrew'])
fold_end('install.homebrew', 'Installing Homebrew packages')
if ci['os'] == 'linux' and 'RTEMS' in os.environ:
tar_name = 'i386-rtems{0}-trusty-20171203-{0}.tar.bz2'.format(os.environ['RTEMS'])
print('Downloading RTEMS {0} cross compiler: {1}'
@@ -858,7 +902,10 @@ USR_CXXFLAGS += {0}'''.format(os.environ['USR_CXXFLAGS'])
'https://github.com/mdavidsaver/rsb/releases/download/20171203-{0}/{1}'
.format(os.environ['RTEMS'], tar_name)],
cwd=toolsdir)
sp.check_call(['tar', '-C', '/', '-xmj', '-f', os.path.join(toolsdir, tar_name)])
sudo_prefix = []
if ci['service'] == 'github-actions':
sudo_prefix = ['sudo']
sp.check_call(sudo_prefix + ['tar', '-C', '/', '-xmj', '-f', os.path.join(toolsdir, tar_name)])
os.remove(os.path.join(toolsdir, tar_name))
setup_for_build(args)

57
github-actions/README.md Normal file
View File

@@ -0,0 +1,57 @@
# GitHub Actions Scripts for EPICS Modules
## Features
- 20 parallel runners on Linux/Windows (5 runners on MacOS)
- Ubuntu 16/18/20, MacOS 10.15, Windows Server 2016/2019
- Compile natively on Linux (gcc, clang)
- Compile natively on MacOS (clang)
- Compile natively on Windows (gcc/MinGW, Visual Studio 2017 & 2019)
- Cross-compile for Windows 32bit and 64bit using MinGW and WINE
- Cross-compile for RTEMS 4.9 and 4.10 (Base >= 3.15)
- Caching not supported yet.
## How to Use these Scripts
1. Add the ci-scripts respository as a Git Submodule
(see [README](../README.md) one level above).
2. Add settings files defining which dependencies in which versions
you want to build against
(see [README](../README.md) one level above).
3. Create a GitHub Actions configuration by copying one of the workflow
examples into the directory `.github/workflows` of your module.
```bash
$ mkdir -p .github/workflows
$ cp .ci/github-actions/ci-scripts-build.yml.example-full .github/workflows/ci-scripts-build.yml
```
4. Edit the workflow configuration to include the build jobs you want
GitHub Actions to run.
Build jobs are specified in the `jobs: <job-name>: strategy:`
declaration. The `matrix:` element specifies the axes as configuration
parameters with their lists of values,
`env:` (on the build level) controls the setting of environment variables
(which can be matrix parameters).
The `runs-on:` setting specifies the image (operating system) of the
runner.
The `name:` is what shows up in the web interface for the workflow,
builds and jobs, and the elements under `steps:` describe the actions
executed for each job of the matrix.
Please check the comments in the examples for more hints, and the
[GitHub Actions documentation](https://help.github.com/en/actions)
for a lot more options and details.
5. Push your changes and click on the `Actions` tab of your GitHub repository
page to see your build results.
## Caches
GitHub Actions provides caching of dependencies.
However, since their cache restore and create algorithm is fundamentally
different from those used by Travis and AppVeyor, this will require some
more changes in ci-scripts to work. Be patient.

View File

@@ -0,0 +1,155 @@
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
# Set the 'name:' properties to values that work for you (MYMODULE)
name: MYMODULE ci-scripts build
# Trigger on pushes and PRs to any branch
on: [push, pull_request]
env:
SETUP_PATH: .ci-local:.ci
SET: test01
CMP: gcc
# For the sequencer on Linux/Windows/MacOS
APT: re2c
CHOCO: re2c
BREW: re2c
jobs:
build-linux:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
# Set environment variables from matrix parameters
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04]
cmp: [gcc, clang]
configuration: [default, static, debug, static-debug]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-macos:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
# Set environment variables from matrix parameters
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [macos-10.15]
cmp: [clang]
# No static builds on MacOS
configuration: [default, debug]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
build-windows:
name: ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
strategy:
fail-fast: false
matrix:
os: [windows-2019, windows-2016]
cmp: [gcc, vs2019, vs2017]
configuration: [default, static, debug, static-debug]
# Available: vs2017/windows-2016 and vs2019/windows-2019
exclude:
- os: windows-2019
cmp: vs2017
- os: windows-2016
cmp: vs2019
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
# Same setup and toolchain as on Travis.
# Needs Base >= 3.15 to compile, EPICS 7 to also run the tests on qemu
build-rtems:
name: RTEMS${{ matrix.rtems }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
RTEMS: ${{ matrix.rtems }}
APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64 qemu-system-x86
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
cmp: [gcc]
configuration: [default, static, debug, static-debug]
rtems: ["4.9", "4.10"]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results
# The WINE cross builds are of somewhat limited use,
# as there are native gcc/MinGW builds available on GitHub Actions
build-wine:
name: WINE${{ matrix.wine }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
WINE: ${{ matrix.wine }}
APT: re2c g++-mingw-w64-i686 g++-mingw-w64-x86-64
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04]
cmp: [gcc]
configuration: [default, static, debug, static-debug]
wine: [32, 64]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results

View File

@@ -0,0 +1,43 @@
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
# (see: https://github.com/epics-base/ci-scripts)
# This is YAML - indentation levels are crucial
# Set the 'name:' properties to values that work for you
name: MYMODULE ci-scripts build
# Trigger on pushes and PRs to any branch
on: [push, pull_request]
env:
SETUP_PATH: .ci-local:.ci
SET: test01
CMP: gcc
jobs:
build-linux:
name: ${{ matrix.base }} / ${{ matrix.cmp }} / ${{ matrix.configuration }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
# Set environment variables from matrix parameters
env:
CMP: ${{ matrix.cmp }}
BCFG: ${{ matrix.configuration }}
BASE: ${{ matrix.base }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, ubuntu-18.04]
cmp: [gcc]
configuration: [default, static]
base: ["7.0", "3.15"]
steps:
- uses: actions/checkout@v2
- name: Prepare and compile dependencies
run: python cue.py prepare
- name: Build main module
run: python cue.py build
- name: Run main module tests
run: python cue.py test
- name: Collect and show test results
run: python cue.py test-results