Skip to content

Commit 7a87407

Browse files
support for CI/CD
1 parent e9d3637 commit 7a87407

File tree

11 files changed

+261
-3
lines changed

11 files changed

+261
-3
lines changed

API

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ roxygenize_with_cache(key, dirs)
1616
snippet_generate(snippet, open = rstudioapi::isAvailable(), root = here::here())
1717
uninstall_precommit(scope = "repo", ask = "user", root = here::here())
1818
update_precommit()
19-
use_precommit(config_source = getOption("precommit.config_source"), force = FALSE, legacy_hooks = "forbid", open = rstudioapi::isAvailable(), install_hooks = TRUE, root = here::here())
19+
use_ci(ci = getOption("precommit.ci", "native"), open = interactive(), root = here::here())
20+
use_precommit(config_source = getOption("precommit.config_source"), force = FALSE, legacy_hooks = "forbid", open = rstudioapi::isAvailable(), install_hooks = TRUE, ci = getOption("precommit.ci", "native"), root = here::here())
2021
use_precommit_config(config_source = getOption("precommit.config_source"), force = FALSE, open = rstudioapi::isAvailable(), verbose = FALSE, root = here::here())
2122
version_precommit()

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export(roxygenize_with_cache)
1414
export(snippet_generate)
1515
export(uninstall_precommit)
1616
export(update_precommit)
17+
export(use_ci)
1718
export(use_precommit)
1819
export(use_precommit_config)
1920
export(version_precommit)

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ includes switching to R based hook for `readme-rmd-render`, avoiding the
55
{usethis} dependency, integration tests via GitHub Actions, auto-updates for
66
used packages, roxygen snippet generation and more. In addition:
77

8+
* `use_precommit()` gains a `ci` argument, defaulting to `"native"`, which will
9+
guide the user to set up continuous integration of the hooks with either
10+
[pre-commit.ci](https://pre-commit.ci) or
11+
[GitHub Actions](https://github.com/features/actions). New exported
12+
function `use_ci(ci = "native")` can be used to migrate existing repos. The
13+
default behavior for `ci` is governed by the R option `precommit.ci`.
814
* `use_precommit(..., install_hooks = TRUE)` is no longer blocking by default.
915
New option `precommit.block_install_hooks` (defaults to `FALSE`) governs the
1016
behavior (#312).

R/setup.R

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#' This function sets up pre-commit for your git repo.
44
#' @param install_hooks Whether to install environments for all available hooks.
55
#' If `FALSE`, environments are installed with first commit.
6+
#' @inheritParams use_ci
67
#' @param legacy_hooks How to treat hooks already in the repo which are not
78
#' managed by pre-commit. "forbid", the default, will cause `use_precommit()`
89
#' to fail if there are such hooks. "allow" will run these along with
@@ -39,6 +40,7 @@ use_precommit <- function(config_source = getOption("precommit.config_source"),
3940
legacy_hooks = "forbid",
4041
open = rstudioapi::isAvailable(),
4142
install_hooks = TRUE,
43+
ci = getOption("precommit.ci", "native"),
4244
root = here::here()) {
4345
rlang::arg_match(legacy_hooks, c("forbid", "allow", "remove"))
4446
assert_is_installed()
@@ -52,10 +54,61 @@ use_precommit <- function(config_source = getOption("precommit.config_source"),
5254
install_repo(root, install_hooks, legacy_hooks)
5355
if (open) {
5456
open_config(root)
57+
if (ci == "native") {
58+
use_ci(ci)
59+
}
60+
} else {
61+
if (ci == "gha") {
62+
use_ci(ci, force = force, root = root)
63+
}
5564
}
65+
5666
invisible(NULL)
5767
}
5868

69+
70+
#' Use continuous integration with pre-commit
71+
#'
72+
#' Sets up continuous integration, or prompts the user to do it manually.
73+
#'
74+
#' @param ci Specifies which continuous integration service to use. See
75+
#' `vignette("ci", package = "precommit")` for details. Defaults to
76+
#' `getOption("precommit.ci", "native")`, which is set to
77+
#' `"native"` on package loading (if unset). `"native"` sets up
78+
#' [pre-commit.ci](https://pre-commit.ci). Alternatively, `"gha"` can be used
79+
#' to set up [GitHub Actions](https://github.com/features/actions). Set value
80+
#' to `NULL` if you don't want to use a continuous integration.
81+
#' @inheritParams fallback_doc
82+
#' @export
83+
use_ci <- function(ci = getOption("precommit.ci", "native"),
84+
open = interactive(), root = here::here()) {
85+
if (is.na(ci)) {
86+
return()
87+
} else if (ci == "gha") {
88+
dest <- fs::path(root, ".github/workflows/pre-commit.yaml")
89+
fs::dir_create(fs::path_dir(dest))
90+
fs::file_copy(
91+
system.file("pre-commit-gha.yaml", package = "precommit"),
92+
dest,
93+
overwrite = force
94+
)
95+
cli::cli_alert_success(paste0(
96+
"Added GitHub Action template to ",
97+
"{.code .github/workflows/pre-commit.yaml}. Pre-commit hooks will ",
98+
"run on pull requests. If workflow fails, please file an issue in ",
99+
"{.code https://github.com/lorenzwalthert/precommit}."
100+
))
101+
} else if (ci == "native") {
102+
cli::cli_ul("Sign in with GitHub to authenticate {.url https://pre-commit.ci}.")
103+
Sys.sleep(2)
104+
browseURL("https://pre-commit.ci")
105+
} else {
106+
rlang::abort(
107+
'Argument `ci` must be one of `"native"` (default), `"gha"` or `NULL`.'
108+
)
109+
}
110+
}
111+
59112
#' Auto-update your hooks
60113
#'
61114
#' Runs [`pre-commit autoupdate`](https://pre-commit.com/#pre-commit-autoupdate).

R/zzz.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
op <- options()
33
op.precommit <- list(
44
precommit.executable = path_derive_precommit_exec(),
5-
precommit.block_install_hooks = FALSE
5+
precommit.block_install_hooks = FALSE,
6+
precommit.ci = "native"
67
)
78
toset <- !(names(op.precommit) %in% names(op))
89
if (any(toset)) options(op.precommit[toset])

inst/WORDLIST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ getwd
5959
gh
6060
github
6161
gitignore
62+
Gitlab
6263
grDevices
6364
grepl
6465
gsub

inst/pre-commit-gha.yaml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: pre-commit
2+
on:
3+
push:
4+
branches-ignore:
5+
- 'master'
6+
pull_request:
7+
types: [opened, synchronize, reopened, ready_for_review]
8+
9+
jobs:
10+
pre-commit:
11+
runs-on: ubuntu-18.04
12+
if: >-
13+
!contains(github.event.head_commit.message, 'ci skip') &&
14+
(
15+
startsWith(github.ref, 'refs/heads') ||
16+
github.event.pull_request.draft == false
17+
)
18+
steps:
19+
- name: Cancel Previous Runs
20+
uses: styfle/[email protected]
21+
with:
22+
access_token: ${{ github.token }}
23+
- uses: actions/checkout@v2
24+
with:
25+
fetch-depth: 0
26+
27+
- name: Install system dependencies
28+
if: runner.os == 'Linux'
29+
run: |
30+
sudo apt-get update -qq || (sudo rm /etc/apt/sources.list.d/* && sudo apt-get update -yqq)
31+
sudo apt-get install -y libcurl4-openssl-dev
32+
- name: Set up Python
33+
uses: actions/setup-python@v2
34+
with:
35+
python-version: "3.8"
36+
architecture: "x64"
37+
38+
- name: Set up environment
39+
run: |
40+
echo "UBUNTU_VERSION=`grep DISTRIB_RELEASE /etc/lsb-release | sed 's/.*=//g'`" >> $GITHUB_ENV
41+
mkdir -p .local/R/site-packages
42+
echo "R_LIBS_USER=`pwd`/.local/R/site-packages" >> $GITHUB_ENV
43+
- name: Cache R packages
44+
uses: actions/cache@v2
45+
if: startsWith(runner.os, 'Linux')
46+
with:
47+
path: ${{env.R_LIBS_USER}}
48+
key: precommit-${{env.UBUNTU_VERSION}}-renv-${{ hashFiles('.pre-commit.r_requirements.txt') }}-
49+
restore-keys: |
50+
precommit-${{env.UBUNTU_VERSION}}-renv-
51+
- name: Install R packages
52+
run: |
53+
if (!requireNamespace("renv", quietly = TRUE)) install.packages("renv")
54+
renv::restore()
55+
renv::install(scan(".pre-commit.r_requirements.txt", what=character(), sep="\n"))
56+
shell: Rscript {0}
57+
58+
- name: Cache pre-commit
59+
uses: actions/cache@v2
60+
with:
61+
path: ~/.cache/pre-commit
62+
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}-
63+
64+
- name: Run pre-commit
65+
uses: pre-commit/[email protected]
66+
67+
- name: Commit files
68+
if: failure() && startsWith(github.ref, 'refs/heads')
69+
run: |
70+
if [[ `git status --porcelain --untracked-files=no` ]]; then
71+
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
72+
git config --local user.name "github-actions[bot]"
73+
git checkout -- .github/workflows
74+
git commit -m "pre-commit" -a
75+
fi
76+
- name: Push changes
77+
if: failure() && startsWith(github.ref, 'refs/heads')
78+
uses: ad-m/github-push-action@master
79+
with:
80+
github_token: ${{ secrets.GITHUB_TOKEN }}
81+
branch: ${{ github.ref }}

man/use_ci.Rd

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/use_precommit.Rd

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-setup.R

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
test_that("snippet generation works", {
2-
local_test_setup(git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE)
2+
local_test_setup(
3+
git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE
4+
)
35
usethis::use_package("styler")
46
usethis::use_package("R", "Depends", "3.6.0")
57
expect_warning(
@@ -18,3 +20,21 @@ test_that("snippet generation works", {
1820
out, " - id: roxygenize\n.* - styler\n - testthat\n$",
1921
)
2022
})
23+
24+
25+
test_that("GitHub Action CI setup works", {
26+
expect_error(use_ci("stuff"), "must be one of")
27+
local_test_setup(
28+
git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE
29+
)
30+
use_ci("gha", root = getwd())
31+
expect_true(fs::file_exists(".github/workflows/pre-commit.yaml"))
32+
})
33+
34+
test_that("Pre-commit CI setup works", {
35+
local_test_setup(
36+
git = FALSE, use_precommit = FALSE, package = TRUE, install_hooks = FALSE
37+
)
38+
use_ci(root = getwd())
39+
expect_false(fs::file_exists(".github/workflows/pre-commit.yaml"))
40+
})

0 commit comments

Comments
 (0)