Add GitHub Actions workflow to test R builds
This commit is contained in:
parent
83dfc554f2
commit
4597879d10
5 changed files with 201 additions and 1 deletions
74
.github/workflows/test.yml
vendored
Normal file
74
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
name: R builds
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'builder/**'
|
||||
- 'test/**'
|
||||
- 'Makefile'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
platforms:
|
||||
description: |
|
||||
Comma-separated list of platforms. Specify "all" to use all platforms (the default).
|
||||
required: false
|
||||
default: 'all'
|
||||
type: string
|
||||
r_versions:
|
||||
description: |
|
||||
Comma-separated list of R versions. Specify "last-N" to use the
|
||||
last N minor R versions, or "all" to use all minor R versions since R 3.1.
|
||||
Defaults to "last-5".
|
||||
required: false
|
||||
default: 'last-5'
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
setup-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
platforms: ${{ steps.setup-matrix.outputs.platforms }}
|
||||
r_versions: ${{ steps.setup-matrix.outputs.r_versions }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up matrix of platforms and R versions
|
||||
id: setup-matrix
|
||||
run: |
|
||||
platforms=$(python test/get_platforms.py ${{ github.event.inputs.platforms }})
|
||||
echo "::set-output name=platforms::$platforms"
|
||||
r_versions=$(python test/get_r_versions.py ${{ github.event.inputs.r_versions }})
|
||||
echo "::set-output name=r_versions::$r_versions"
|
||||
|
||||
test:
|
||||
needs: setup-matrix
|
||||
strategy:
|
||||
matrix:
|
||||
platform: ${{ fromJson(needs.setup-matrix.outputs.platforms) }}
|
||||
env:
|
||||
R_VERSIONS: ${{ join(fromJson(needs.setup-matrix.outputs.r_versions), ' ') }}
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.platform }} (R ${{ join(fromJson(needs.setup-matrix.outputs.r_versions), ', ') }})
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver: docker
|
||||
install: true
|
||||
|
||||
- name: Build R
|
||||
run: |
|
||||
for version in ${{ env.R_VERSIONS }}; do
|
||||
R_VERSION=$version make build-r-${{ matrix.platform }}
|
||||
done
|
||||
|
||||
- name: Test R
|
||||
run: |
|
||||
for version in ${{ env.R_VERSIONS }}; do
|
||||
R_VERSION=$version make test-r-${{ matrix.platform }}
|
||||
done
|
||||
5
Makefile
5
Makefile
|
|
@ -59,6 +59,9 @@ $(foreach platform,$(PLATFORMS), \
|
|||
$(eval $(GEN_TARGETS)) \
|
||||
)
|
||||
|
||||
print-platforms:
|
||||
@echo $(PLATFORMS)
|
||||
|
||||
# Helper for launching a bash session on a docker image of your choice. Defaults
|
||||
# to "ubuntu:xenial".
|
||||
TARGET_IMAGE?=ubuntu:xenial
|
||||
|
|
@ -68,4 +71,4 @@ bash:
|
|||
-w /r-builds \
|
||||
${TARGET_IMAGE} /bin/bash
|
||||
|
||||
.PHONY: deps docker-build docker-push docker-down docker-build-package docker-shell-package-env ecr-login fetch-serverless-custom-file serverless-deploy
|
||||
.PHONY: deps docker-build docker-push docker-down docker-build-package docker-shell-package-env ecr-login fetch-serverless-custom-file print-platforms serverless-deploy
|
||||
|
|
|
|||
25
README.md
25
README.md
|
|
@ -226,6 +226,21 @@ environment:
|
|||
|
||||
In order for the makefile to push these new platforms to ECR, add them to the PLATFORMS variable near the top of the Makefile
|
||||
|
||||
### test/docker-compose.yml
|
||||
|
||||
A new service in the `test/docker-compose.yml` file named according to the `platform-version` and containing the proper entries:
|
||||
|
||||
```yaml
|
||||
ubuntu-2204:
|
||||
image: ubuntu:jammy
|
||||
command: /r-builds/test/test-apt.sh
|
||||
environment:
|
||||
- OS_IDENTIFIER=ubuntu-2204
|
||||
- R_VERSION=${R_VERSION}
|
||||
volumes:
|
||||
- ../:/r-builds
|
||||
```
|
||||
|
||||
### Submit a Pull Request
|
||||
|
||||
Once you've followed the steps above, submit a pull request. On successful merge, builds for this platform will begin to be available from the CDN.
|
||||
|
|
@ -244,6 +259,16 @@ serverless invoke stepf -n rBuilds -d '{"force": true, "versions": ["3.6.3", "4.
|
|||
|
||||
## Testing
|
||||
|
||||
Tests are automatically run on each push that changes a file in `builder/`, `test/`, or the `Makefile`.
|
||||
These tests validate that R was correctly configured, built, and packaged. By default, the tests run
|
||||
for the last 5 minor R versions on each platform.
|
||||
|
||||
To run the tests manually, you can navigate to the [GitHub Actions workflow page](https://github.com/rstudio/r-builds/actions/workflows/test.yml)
|
||||
and use "Run workflow" to run the tests from a custom branch, list of platforms, and list of R versions.
|
||||
|
||||
To skip the tests, add `[skip ci]` to your commit message. See [Skipping workflow runs](https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs)
|
||||
for more information.
|
||||
|
||||
To test the R builds locally, you can use the `build-r-$PLATFORM` and `test-r-$PLATFORM`
|
||||
targets to build R and run the tests. The tests use the quick install script to install R,
|
||||
using a locally built R if present, or otherwise a build from the CDN.
|
||||
|
|
|
|||
31
test/get_platforms.py
Normal file
31
test/get_platforms.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Print R-builds platforms as JSON.")
|
||||
parser.add_argument(
|
||||
'platforms',
|
||||
type=str,
|
||||
nargs='?',
|
||||
default='all',
|
||||
help='Comma-separated list of platforms. Specify "all" to use all platforms (the default).'
|
||||
)
|
||||
args = parser.parse_args()
|
||||
platforms = _get_platforms(which=args.platforms)
|
||||
print(json.dumps(platforms))
|
||||
|
||||
|
||||
def _get_platforms(which='all'):
|
||||
supported_platforms = subprocess.check_output(['make', 'print-platforms'], text=True)
|
||||
supported_platforms = supported_platforms.split()
|
||||
if which == 'all':
|
||||
return supported_platforms
|
||||
platforms = which.split(',')
|
||||
platforms = [p for p in platforms if p in supported_platforms]
|
||||
return platforms
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
67
test/get_r_versions.py
Normal file
67
test/get_r_versions.py
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import argparse
|
||||
import json
|
||||
import re
|
||||
import urllib.request
|
||||
|
||||
VERSIONS_URL = 'https://cdn.rstudio.com/r/versions.json'
|
||||
|
||||
# Minimum R version for "all"
|
||||
MIN_ALL_VERSION = '3.1.0'
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Print R-builds R versions as JSON.")
|
||||
parser.add_argument(
|
||||
'versions',
|
||||
type=str,
|
||||
nargs='?',
|
||||
default='last-5',
|
||||
help="""Comma-separated list of R versions. Specify "last-N" to use the
|
||||
last N minor R versions, or "all" to use all minor R versions since R 3.1.
|
||||
Defaults to "last-5".
|
||||
"""
|
||||
)
|
||||
args = parser.parse_args()
|
||||
versions = _get_versions(which=args.versions)
|
||||
print(json.dumps(versions))
|
||||
|
||||
|
||||
def _get_versions(which='all'):
|
||||
supported_versions = sorted(_get_supported_versions(), reverse=True)
|
||||
|
||||
last_n_versions = None
|
||||
if which.startswith('last-'):
|
||||
last_n_versions = int(which.replace('last-', ''))
|
||||
elif which != 'all':
|
||||
versions = which.split(',')
|
||||
versions = [v for v in versions if v in supported_versions]
|
||||
return versions
|
||||
|
||||
versions = {}
|
||||
for ver in supported_versions:
|
||||
# Skip unreleased versions (e.g., devel, next)
|
||||
if not re.match(r'[\d.]', ver):
|
||||
continue
|
||||
if ver < MIN_ALL_VERSION:
|
||||
continue
|
||||
minor_ver = tuple(ver.split('.')[0:2])
|
||||
if minor_ver not in versions:
|
||||
versions[minor_ver] = ver
|
||||
versions = sorted(list(versions.values()), reverse=True)
|
||||
|
||||
if last_n_versions:
|
||||
return versions[0:last_n_versions]
|
||||
|
||||
return versions
|
||||
|
||||
|
||||
def _get_supported_versions():
|
||||
request = urllib.request.Request(VERSIONS_URL)
|
||||
response = urllib.request.urlopen(request)
|
||||
data = response.read()
|
||||
result = json.loads(data)
|
||||
return result['r_versions']
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Reference in a new issue