From 528300b3002211ba90f5d278742127b1dc940b45 Mon Sep 17 00:00:00 2001 From: sorinvoicu <61691256+sorinvoicu@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:42:31 +0000 Subject: [PATCH] init --- .Rbuildignore | 9 ++++ .github/workflows/check.yml | 57 ++++++++++++++++++++++++ .github/workflows/gitleaks.yml | 60 +++++++++++++++++++++++++ .github/workflows/links.yml | 44 +++++++++++++++++++ .github/workflows/lintr.yml | 43 ++++++++++++++++++ .github/workflows/pkgdown.yml | 49 +++++++++++++++++++++ .github/workflows/roxygen.yml | 55 +++++++++++++++++++++++ .github/workflows/shared_ci.yml | 32 ++++++++++++++ .gitignore | 3 ++ DESCRIPTION | 21 +++++++++ LICENSE | 13 ++++++ NAMESPACE | 4 ++ R/hello.R | 40 +++++++++++++++++ README.md | 16 +++++++ _pkgdown.yml | 9 ++++ dependencies.yml | 6 +++ inst/repo-logo.svg | 60 +++++++++++++++++++++++++ man/hello.Rd | 20 +++++++++ man/run_app.Rd | 15 +++++++ tests/testthat.R | 3 ++ tests/testthat/shiny-app/app.R | 6 +++ tests/testthat/test-hello.R | 5 +++ tests/testthat/test-shiny.R | 10 +++++ workflows.md | 78 +++++++++++++++++++++++++++++++++ 24 files changed, 658 insertions(+) create mode 100644 .Rbuildignore create mode 100644 .github/workflows/check.yml create mode 100644 .github/workflows/gitleaks.yml create mode 100644 .github/workflows/links.yml create mode 100644 .github/workflows/lintr.yml create mode 100644 .github/workflows/pkgdown.yml create mode 100644 .github/workflows/roxygen.yml create mode 100644 .github/workflows/shared_ci.yml create mode 100644 .gitignore create mode 100644 DESCRIPTION create mode 100644 LICENSE create mode 100644 NAMESPACE create mode 100644 R/hello.R create mode 100644 README.md create mode 100644 _pkgdown.yml create mode 100644 dependencies.yml create mode 100644 inst/repo-logo.svg create mode 100644 man/hello.Rd create mode 100644 man/run_app.Rd create mode 100644 tests/testthat.R create mode 100644 tests/testthat/shiny-app/app.R create mode 100644 tests/testthat/test-hello.R create mode 100644 tests/testthat/test-shiny.R create mode 100644 workflows.md diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..fe64037 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,9 @@ +^dv.templates\.Rproj$ +^\.Rproj\.user$ +^.*\.Rproj$ +^LICENSE\.md$ +^LICENSE$ +^\.github +_pkgdown.yml +workflows.md +dependencies.yml diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..07c50a0 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,57 @@ +--- +name: Check ๐Ÿ“ฆ + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + +concurrency: + group: check-test-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + check-test: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + container: + image: ${{ vars.CI_IMAGE }} + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + + - name: Install package dependencies ๐Ÿ“„ + run: | + if (file.exists("dependencies.yml")) { + repos <- yaml::yaml.load(readLines("dependencies.yml"))$dependencies |> + sapply(function(x) x$repo) + if(repos |> length() > 0) { + repos |> + pak::pak(dependencies = TRUE, ask = FALSE, upgrade = FALSE) + } + } + shell: Rscript {0} + + - name: Check ๐Ÿ“ฆ + run: | + options(crayon.enabled = TRUE) + devtools::check(error_on="error", args=c("--no-tests")) + shell: Rscript {0} + + - name: Test ๐Ÿงช + if: > + !contains(github.event.commits[0].message, '[skip tests]') && github.event.pull_request.draft == false + run: | + options(crayon.enabled = TRUE) + devtools::test() + shell: Rscript {0} diff --git a/.github/workflows/gitleaks.yml b/.github/workflows/gitleaks.yml new file mode 100644 index 0000000..d9a2680 --- /dev/null +++ b/.github/workflows/gitleaks.yml @@ -0,0 +1,60 @@ +--- +name: Gitleaks ๐ŸŒง๏ธ + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + inputs: + gitleaks-version: + description: Gitleaks executable version. + required: false + type: string + default: "8.18.2" + +concurrency: + group: gitleaks-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + gitleaks: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + container: + image: ${{ vars.CI_IMAGE }} + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + + - name: Normalize inputs ๐Ÿ“ + shell: bash + run: | + gitleaks_version_input="${{ inputs.gitleaks-version }}" + echo "GITLEAKS_VERSION=${gitleaks_version_input:-8.18.2}" >> $GITHUB_ENV + + - name: Install gitleaks ๐Ÿ’ง + run: | + cd /tmp + wget -q \ + "https://github.com/zricethezav/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \ + -O gitleaks.tar.gz || \ + (echo "Error downloading gitleaks ${GITLEAKS_VERSION} tarball" && exit 1) + tar -xvzf gitleaks.tar.gz || \ + (echo "Error unarchiving gitleaks ${GITLEAKS_VERSION} tarball" && exit 1) + mv gitleaks /usr/bin/. || \ + (echo "Error moving gitleaks for /usr/bin" && exit 1) + shell: bash + + - name: Run gitleaks ๐ŸŒง๏ธ + run: gitleaks -v detect --no-git --source . + shell: bash diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 0000000..11165ca --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,44 @@ +--- +name: Check URLs ๐ŸŒ + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + +concurrency: + group: links-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + links: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + + - name: Check URLs ๐ŸŒ + uses: lycheeverse/lychee-action@v1 + with: + fail: true + args: >- + --verbose + --no-progress + --exclude "https://github.com.*.tar.gz" + **/*.md + **/*.Rmd + **/*.html + **/*.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lintr.yml b/.github/workflows/lintr.yml new file mode 100644 index 0000000..34b0c92 --- /dev/null +++ b/.github/workflows/lintr.yml @@ -0,0 +1,43 @@ +--- +name: Lintr ๐Ÿ” + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + inputs: + lintr-error-on-lint: + description: Raise lintr error when lints found. + required: false + default: true + type: boolean + +concurrency: + group: lint-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + lintr: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + container: + image: ${{ vars.CI_IMAGE }} + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + + - name: Lintr ๐Ÿ” + run: lintr::lint_package() + shell: Rscript {0} + env: + LINTR_ERROR_ON_LINT: ${{ inputs.lintr-error-on-lint }} diff --git a/.github/workflows/pkgdown.yml b/.github/workflows/pkgdown.yml new file mode 100644 index 0000000..0ce2d9d --- /dev/null +++ b/.github/workflows/pkgdown.yml @@ -0,0 +1,49 @@ +--- +name: Pkgdown ๐Ÿ“– + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + +concurrency: + group: pkgdown-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + pkgdown: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + container: + image: ${{ vars.CI_IMAGE }} + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + + - name: Build site ๐Ÿ”ง + run: pkgdown::build_site() + shell: Rscript {0} + + - name: Checkout gh-pages branch โฌ‡๏ธ + uses: actions/checkout@v4 + with: + path: gh-pages + ref: gh-pages + + - name: Deploy to GitHub pages ๐Ÿ“ฐ + if: (github.event_name == 'push') && (github.ref_name == 'main') + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + clean: true + branch: gh-pages + folder: docs diff --git a/.github/workflows/roxygen.yml b/.github/workflows/roxygen.yml new file mode 100644 index 0000000..281b467 --- /dev/null +++ b/.github/workflows/roxygen.yml @@ -0,0 +1,55 @@ +--- +name: Roxygen ๐Ÿ“„ + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_call: + +concurrency: + group: roxygen-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + roxygen: + name: ${{ vars.CI_IMAGE }} + runs-on: ubuntu-latest + container: + image: ${{ vars.CI_IMAGE }} + + steps: + - name: Checkout project โฌ‡๏ธ + uses: actions/checkout@v4 + with: + path: ${{ github.event.repository.name }} + + - name: Generate man pages ๐Ÿ“„ + run: | + Rscript -e 'roxygen2::roxygenize()' + if [[ -n $(git status -s | grep -E "man|DESCRIPTION") ]] + then + ROXYGEN_VERSION="$(Rscript -e 'packageVersion("roxygen2")' | awk '{print $NF}')" + echo "โš ๏ธ Manuals are not up-to-date with roxygen comments!" + echo "Here are the differences:" + git diff man/* DESCRIPTION + echo -e "\n Please rerun the following command on your workstation and push your changes" + echo "--------------------------------------------------------------------" + echo "roxygen2::roxygenize('.')" + echo "--------------------------------------------------------------------" + echo "โ„น๏ธ roxygen2 version that was used in this workflow: $ROXYGEN_VERSION" + echo "Please ensure that the 'RoxygenNote' field in the DESCRIPTION file matches this version" + exit 1 + else + echo "๐Ÿ‘ Manuals are up-to-date with roxygen comments" + fi + shell: bash + working-directory: ${{ github.event.repository.name }} diff --git a/.github/workflows/shared_ci.yml b/.github/workflows/shared_ci.yml new file mode 100644 index 0000000..98848d7 --- /dev/null +++ b/.github/workflows/shared_ci.yml @@ -0,0 +1,32 @@ +--- +name: Checks ๐Ÿงฉ + +on: + workflow_call: + +jobs: + check-test: + name: Check ๐Ÿ“ฆ + uses: boehringer-ingelheim/dv.templates/.github/workflows/check.yml@main + + lintr: + name: Lintr ๐Ÿ” + uses: boehringer-ingelheim/dv.templates/.github/workflows/lintr.yml@main + with: + lintr-error-on-lint: true + + gitleaks: + name: Gitleaks ๐ŸŒง๏ธ + uses: boehringer-ingelheim/dv.templates/.github/workflows/gitleaks.yml@main + + roxygen: + name: Roxygen ๐Ÿ“„ + uses: boehringer-ingelheim/dv.templates/.github/workflows/roxygen.yml@main + + pkgdown: + name: Pkgdown ๐Ÿ“– + uses: boehringer-ingelheim/dv.templates/.github/workflows/pkgdown.yml@main + + links: + name: Check URLs ๐ŸŒ + uses: boehringer-ingelheim/dv.templates/.github/workflows/links.yml@main diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8420283 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.Rproj.user +_snaps/ +docs/ \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..8d0d644 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,21 @@ +Package: dv.templates +Title: Provides reusable functionality for R and CI/CD +Version: 0.0.0.9100 +Authors@R: c( + person("Boehringer-Ingelheim Pharma GmbH & Co.KG", role = c("cph", "fnd")), + person("Sorin", "Voicu", , "first.last@example.com", role = c("aut", "cre")) + ) +Description: Provides reusable functionality for R and CI/CD. +License: Apache License 2.0 +Encoding: UTF-8 +Roxygen: list(markdown = TRUE) +Imports: + shiny, + stringr +Suggests: + knitr, + testthat (>= 2.0), + shinytest2 +VignetteBuilder: + knitr +RoxygenNote: 7.3.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8df72c1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2024 Boehringer-Ingelheim Pharma GmbH & Co.KG + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..c4e3ed8 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,4 @@ +# Generated by roxygen2: do not edit by hand + +export(hello) +export(run_app) diff --git a/R/hello.R b/R/hello.R new file mode 100644 index 0000000..bd68aa7 --- /dev/null +++ b/R/hello.R @@ -0,0 +1,40 @@ +#' Personal greeting +#' +#' @description Greet a person and appropriately capitalize their name. +#' +#' @param name Your name (character string; e.g. "john doe"). +#' +#' @return A character string, capitalized to title case. +#' @export +#' +#' @examples +#' hello("james bond") +hello <- function(name = "your name") { + name <- stringr::str_to_title(name) + print(paste("Hello,", name)) +} + +#' Personal greeting as a Shiny app +#' +#' @description Greet a person and appropriately capitalize their name +#' as a Shiny app. +#' +#' @return Shiny app showcasing the personal greeting feature. +#' @export +#' +run_app <- function() { + ui <- shiny::fluidPage( + shiny::textInput("name", "What is your name?"), + shiny::actionButton("greet", "Greet"), + shiny::textOutput("greeting") + ) + + server <- function(input, output, session) { + output$greeting <- shiny::renderText({ + shiny::req(input$greet) + hello(shiny::isolate(input$name)) + }) + } + + shiny::shinyApp(ui, server) +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..70baf94 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# dv.templates + +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/check.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/check.yml?query=workflow) +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/gitleaks.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/gitleaks.yml?query=workflow) +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/lintr.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/lintr.yml?query=workflow) +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/pkgdown.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/pkgdown.yml?query=workflow) +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/roxygen.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/roxygen.yml?query=workflow) +[![Build status](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/links.yml/badge.svg)](https://github.com/boehringer-ingelheim/dv.templates/actions/workflows/links.yml?query=workflow) + +An R package template with built-in GitHub Actions-based CI/CD workflows. + +### Usage + +All CI/CD jobs are defined in the [.github/workflows](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows) directory in the form of GitHub Action workflows. These can be modified per your requirements, but are designed and implemented to follow best practices and to ensure the highest quality standards for your package. + +๐Ÿ‘‰ For more information on workflows, please refer to the [Workflows documentation](./workflows.md). diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 0000000..5d31487 --- /dev/null +++ b/_pkgdown.yml @@ -0,0 +1,9 @@ +url: https://boehringer-ingelheim.github.io/dv.templates/ + +template: + bootstrap: 5 + +navbar: + right: + - icon: fa-github + href: https://github.com/boehringer-ingelheim/dv.templates diff --git a/dependencies.yml b/dependencies.yml new file mode 100644 index 0000000..16b3fb4 --- /dev/null +++ b/dependencies.yml @@ -0,0 +1,6 @@ +# use pak source reference to define fluid dependencies +# https://pak.r-lib.org/reference/pak_package_sources.html + +# dependencies: +# dv.loader: +# repo: github::boehringer-ingelheim/dv.loader@main diff --git a/inst/repo-logo.svg b/inst/repo-logo.svg new file mode 100644 index 0000000..d184624 --- /dev/null +++ b/inst/repo-logo.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/man/hello.Rd b/man/hello.Rd new file mode 100644 index 0000000..e7eb880 --- /dev/null +++ b/man/hello.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hello.R +\name{hello} +\alias{hello} +\title{Personal greeting} +\usage{ +hello(name = "your name") +} +\arguments{ +\item{name}{Your name (character string; e.g. "john doe").} +} +\value{ +A character string, capitalized to title case. +} +\description{ +Greet a person and appropriately capitalize their name. +} +\examples{ +hello("james bond") +} diff --git a/man/run_app.Rd b/man/run_app.Rd new file mode 100644 index 0000000..5739dee --- /dev/null +++ b/man/run_app.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/hello.R +\name{run_app} +\alias{run_app} +\title{Personal greeting as a Shiny app} +\usage{ +run_app() +} +\value{ +Shiny app showcasing the personal greeting feature. +} +\description{ +Greet a person and appropriately capitalize their name +as a Shiny app. +} diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..ae73b47 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,3 @@ +pkg_name <- "dv.templates" +library(pkg_name, character.only = TRUE) +testthat::test_check(pkg_name) diff --git a/tests/testthat/shiny-app/app.R b/tests/testthat/shiny-app/app.R new file mode 100644 index 0000000..1b5835f --- /dev/null +++ b/tests/testthat/shiny-app/app.R @@ -0,0 +1,6 @@ +if (Sys.getenv("CI") == "true") { + pkgload::load_all(Sys.getenv("GITHUB_WORKSPACE")) +} else { + pkgload::load_all() +} +run_app() diff --git a/tests/testthat/test-hello.R b/tests/testthat/test-hello.R new file mode 100644 index 0000000..4dccc45 --- /dev/null +++ b/tests/testthat/test-hello.R @@ -0,0 +1,5 @@ +test_that("hello greets the entity", { + result <- hello("foo") + expected <- "Hello, Foo" + expect_identical(result, expected) +}) diff --git a/tests/testthat/test-shiny.R b/tests/testthat/test-shiny.R new file mode 100644 index 0000000..ed05572 --- /dev/null +++ b/tests/testthat/test-shiny.R @@ -0,0 +1,10 @@ +test_that("the greeter app updates user's name on clicking the button", { + app <- shinytest2::AppDriver$new(app_dir = "./shiny-app", name = "greeting_app") + + # WHEN: the user enters their name and clicks the "Greet" button + app$set_inputs(name = "Hello Bar") + app$click("greet") + + # THEN: a greeting is printed to the screen + values <- app$expect_values(output = "greeting", screenshot_args = FALSE) +}) diff --git a/workflows.md b/workflows.md new file mode 100644 index 0000000..3022bdb --- /dev/null +++ b/workflows.md @@ -0,0 +1,78 @@ +# What these workflows do? + +### [`check.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/check.yml) + +Runs devtools::check() and devtools::test() on the R package inside the checked out repository. + +### [`gitleaks.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/gitleaks.yml) + +Runs [`gitleaks`](https://github.com/zricethezav/gitleaks) on the repo to discover any secrets that might have been hardcoded. + +### [`lintr.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/lintr.yml) + +Runs lintr on the repo with the linting settings specified in the container image. + +### [`pkgdown.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/pkgdown.yml) + +Generates a [`pkgdown`](https://pkgdown.r-lib.org/) website and uploads it to Github Pages. + +### [`roxygen.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/roxygen.yml) + +Uses [`roxygen`](https://roxygen2.r-lib.org/) to generate `.Rd` files in the +`man/` directory. It also checks if manuals are up-to-date with roxygen comments in the code. + +### [`links.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/links.yml) + +Checks for broken links inside the repository. + +### [`shared_ci.yml`](https://github.com/boehringer-ingelheim/dv.templates/blob/main/.github/workflows/shared_ci.yml) + +Builds a reusable workflow to be called from other repositories. + +Example configuration for `main` branch: + +```yaml +--- +name: Checks ๐Ÿงฉ + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - ready_for_review + branches: + - main + push: + branches: + - main + workflow_dispatch: + +jobs: + check-test: + name: Check ๐Ÿ“ฆ + uses: boehringer-ingelheim/dv.templates/.github/workflows/check.yml@main + + lintr: + name: Lintr ๐Ÿ” + uses: boehringer-ingelheim/dv.templates/.github/workflows/lintr.yml@main + with: + lintr-error-on-lint: true + + gitleaks: + name: Gitleaks ๐ŸŒง๏ธ + uses: boehringer-ingelheim/dv.templates/.github/workflows/gitleaks.yml@main + + roxygen: + name: Roxygen ๐Ÿ“„ + uses: boehringer-ingelheim/dv.templates/.github/workflows/roxygen.yml@main + + pkgdown: + name: Pkgdown ๐Ÿ“– + uses: boehringer-ingelheim/dv.templates/.github/workflows/pkgdown.yml@main + + links: + name: Check URLs ๐ŸŒ + uses: boehringer-ingelheim/dv.templates/.github/workflows/links.yml@main +```