diff --git a/NAMESPACE b/NAMESPACE index 79afd7ff7..6631a4576 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -101,9 +101,11 @@ export(use_github_links) export(use_github_release) export(use_gitlab_ci) export(use_gpl3_license) +export(use_jenkins) export(use_lgpl_license) export(use_lifecycle_badge) export(use_logo) +export(use_make) export(use_mit_license) export(use_namespace) export(use_news_md) diff --git a/NEWS.md b/NEWS.md index fe3743ff2..b2035c2df 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # usethis (development version) +* `use_make()` and `use_jenkins()` add a Makefile and Jenkinsfile, respectively + (@ryapric, #501) + # usethis 1.5.0 ## Git, GitHub (and GitLab) diff --git a/R/jenkins.R b/R/jenkins.R new file mode 100644 index 000000000..9282038b6 --- /dev/null +++ b/R/jenkins.R @@ -0,0 +1,19 @@ +#' Create Jenkinsfile for Jenkins CI Pipelines +#' +#' `use_jenkins()` adds a basic Jenkinsfile for R packages to the project root +#' directory. The Jenkinsfile stages take advantage of calls to `make`, and so +#' calling this function will also run `use_make()` if a Makefile does not +#' already exist at the project root. +#' +#' @seealso The [documentation on Jenkins +#' Pipelines](https://jenkins.io/doc/book/pipeline/jenkinsfile). +#' @seealso [use_make()] +#' @export +use_jenkins <- function() { + use_make() + use_template( + "Jenkinsfile", + data = list(name = project_name()) + ) + use_build_ignore("Jenkinsfile") +} diff --git a/R/make.R b/R/make.R new file mode 100644 index 000000000..aad0d02fc --- /dev/null +++ b/R/make.R @@ -0,0 +1,19 @@ +#' Create Makefile +#' +#' `use_make()` adds a basic Makefile to the project root directory. +#' +#' @seealso The [documentation for GNU +#' Make](https://www.gnu.org/software/make/manual/html_node). +#' @export +use_make <- function() { + use_template( + "Makefile", + data = list(name = project_name()) + ) + use_build_ignore("Makefile") +} + +uses_make <- function(base_path = proj_get()) { + makefile_path <- proj_path("Makefile") + file_exists(makefile_path) +} diff --git a/inst/templates/Jenkinsfile b/inst/templates/Jenkinsfile new file mode 100644 index 000000000..77d18ba3f --- /dev/null +++ b/inst/templates/Jenkinsfile @@ -0,0 +1,21 @@ +pipeline { + agent any { + stages { + stage('Build') { + steps { + make build + } + } + stage('Check') { + steps { + make check + } + } + stage('Clean') { + steps { + make clean + } + } + } + } +} diff --git a/inst/templates/Makefile b/inst/templates/Makefile new file mode 100644 index 000000000..d22ee170f --- /dev/null +++ b/inst/templates/Makefile @@ -0,0 +1,26 @@ +# h/t to @jimhester and @yihui for this parse block: +# https://github.com/yihui/knitr/blob/dc5ead7bcfc0ebd2789fe99c527c7d91afb3de4a/Makefile#L1-L4 +# Note the portability change as suggested in the manual: +# https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Writing-portable-packages +PKGNAME = `sed -n "s/Package: *\([^ ]*\)/\1/p" DESCRIPTION` +PKGVERS = `sed -n "s/Version: *\([^ ]*\)/\1/p" DESCRIPTION` + + +all: check + +build: + R CMD build . + +check: build + R CMD check --no-manual $(PKGNAME)_$(PKGVERS).tar.gz + +install_deps: + Rscript \ + -e 'if (!requireNamespace("remotes") install.packages("remotes")' \ + -e 'remotes::install_deps(dependencies = TRUE)' + +install: install_deps build + R CMD INSTALL $(PKGNAME)_$(PKGVERS).tar.gz + +clean: + @rm -rf $(PKGNAME)_$(PKGVERS).tar.gz $(PKGNAME).Rcheck diff --git a/man/use_jenkins.Rd b/man/use_jenkins.Rd new file mode 100644 index 000000000..3d0b33d36 --- /dev/null +++ b/man/use_jenkins.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/jenkins.R +\name{use_jenkins} +\alias{use_jenkins} +\title{Create Jenkinsfile for Jenkins CI Pipelines} +\usage{ +use_jenkins() +} +\description{ +\code{use_jenkins()} adds a basic Jenkinsfile for R packages to the project root +directory. The Jenkinsfile stages take advantage of calls to \code{make}, and so +calling this function will also run \code{use_make()} if a Makefile does not +already exist at the project root. +} +\seealso{ +The \href{https://jenkins.io/doc/book/pipeline/jenkinsfile/}{documentation on Jekins Pipelines}. + +\code{\link[=use_make]{use_make()}} +} diff --git a/man/use_make.Rd b/man/use_make.Rd new file mode 100644 index 000000000..9042eea7e --- /dev/null +++ b/man/use_make.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/make.R +\name{use_make} +\alias{use_make} +\title{Create Makefile} +\usage{ +use_make() +} +\description{ +\code{use_make()} adds a basic Makefile to the project root directory. +} +\seealso{ +The \href{https://www.gnu.org/software/make/manual/html_node}{documentation for GNU Make}. +} diff --git a/tests/testthat/test-use-jenkins.R b/tests/testthat/test-use-jenkins.R new file mode 100644 index 000000000..a0ee78285 --- /dev/null +++ b/tests/testthat/test-use-jenkins.R @@ -0,0 +1,8 @@ +context("use_jenkins") + +test_that("use_jenkins() creates a Makefile AND a Jenkinsfile at project root", { + pkg <- scoped_temporary_package() + use_jenkins() + expect_proj_file("Makefile") + expect_proj_file("Jenkinsfile") +}) diff --git a/tests/testthat/test-use-make.R b/tests/testthat/test-use-make.R new file mode 100644 index 000000000..674661a69 --- /dev/null +++ b/tests/testthat/test-use-make.R @@ -0,0 +1,7 @@ +context("use_makefile") + +test_that("use_make() creates a Makefile at project root", { + pkg <- scoped_temporary_package() + use_make() + expect_proj_file("Makefile") +})