Add GitHub Actions workflow to test R builds

This commit is contained in:
Greg Lin 2022-08-10 18:54:28 -05:00
commit 4597879d10
5 changed files with 201 additions and 1 deletions

74
.github/workflows/test.yml vendored Normal file
View 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

View file

@ -59,6 +59,9 @@ $(foreach platform,$(PLATFORMS), \
$(eval $(GEN_TARGETS)) \ $(eval $(GEN_TARGETS)) \
) )
print-platforms:
@echo $(PLATFORMS)
# Helper for launching a bash session on a docker image of your choice. Defaults # Helper for launching a bash session on a docker image of your choice. Defaults
# to "ubuntu:xenial". # to "ubuntu:xenial".
TARGET_IMAGE?=ubuntu:xenial TARGET_IMAGE?=ubuntu:xenial
@ -68,4 +71,4 @@ bash:
-w /r-builds \ -w /r-builds \
${TARGET_IMAGE} /bin/bash ${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

View file

@ -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 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 ### 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. 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 ## 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` 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, 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. using a locally built R if present, or otherwise a build from the CDN.

31
test/get_platforms.py Normal file
View 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
View 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()