The {multideploy}
package provides a streamlined way to
deploy file changes across multiple GitHub repositories. Whether you’re
managing standardized CI/CD configurations, common utility scripts, code
style definitions, or any other files that should be consistent across
repositories, {multideploy}
helps automate this
process.
This vignette will guide you through the main functionality of the package with practical examples.
First, load the {multideploy}
package:
Before using {multideploy}
, you need to authenticate
with GitHub. The package uses the gh
package for
authentication, which looks for a GitHub
Personal Access Token (PAT) in the GITHUB_PAT
or
GITHUB_TOKEN
environment variables. This token can be set
directly within the R script via:
# Set GitHub PAT (or better, use .Renviron)
Sys.setenv(GITHUB_PAT = askpass::askpass("What is your GitHub Personal Access Token (PAT) ?"))
For regular use, it’s recommended to add your PAT to the git
credential system through the gitcreds
package:
Your PAT needs appropriate permissions to access and modify repositories. At a minimum, you’ll need:
repo
scope for accessing private repositoriesworkflow
scope if you’re modifying GitHub Actions
workflowsThe repos()
function allows you to list repositories for
a user or organization:
You can retrieve the content of a file from a GitHub repository:
The core functionality of {multideploy}
is deploying
files across multiple repositories. This can be done in two ways:
Deploy a single file to multiple repositories:
# Get repositories
repos <- repos("orgname", filter_regex = "^api-")
# Deploy a file to all repositories
results <- file_deploy(
source_file = "templates/ci.yml",
target_path = ".github/workflows/ci.yml",
repos = repos,
commit_message = "Standardize CI workflow"
)
# View deployment results
print(results)
For changes that require review, you can create pull requests:
# Create a mapping of files to deploy
mapping <- file_mapping(
"templates/ci.yml" = ".github/workflows/ci.yml",
"templates/lint.R" = ".lintr",
"templates/codeowners" = ".github/CODEOWNERS"
)
# Create pull requests with these changes
pr_results <- pr_create(
repos = repos,
branch_name = "feature/standardize-configs",
title = "Standardize repository configurations",
body = "This PR updates CI workflows, linting settings, and CODEOWNERS file to match organization standards.",
file_mapping = mapping
)
# View PR creation results
print(pr_results)
You can deploy all files from a directory while preserving their structure:
# Create mapping from a directory
workflow_mapping <- file_mapping(
dir = "templates/workflows",
pattern = "\\.ya?ml$",
target_prefix = ".github/workflows/",
preserve_structure = TRUE
)
# Use this mapping to create PRs
pr_create(
repos = repos,
branch_name = "feature/update-workflows",
title = "Update all workflow files",
body = "Standardize all GitHub Actions workflow files",
file_mapping = workflow_mapping
)
Before making actual changes, you can preview them using dry run mode:
You can combine repository filtering with deployment to target specific subsets of repositories:
# Get all organization repositories
all_repos <- repos("orgname")
# Filter to only Java repositories
r_repos <- all_repos[grepl("r", all_repos$name), ]
# Deploy R-specific configuration
file_deploy(
source_file = "templates/R/.Rbuildignore",
target_path = ".Rbuildignore",
repos = r_repos
)
# Filter to only Python repositories
python_repos <- all_repos[grepl("python", all_repos$name), ]
# Deploy Python-specific configuration
file_deploy(
source_file = "templates/python/pylintrc",
target_path = ".pylintrc",
repos = python_repos
)
If you’re deploying files across multiple repositories, we recommend taking into consideration the following:
Start with dry runs: Always use
dry_run = TRUE
first to preview changes.
Use meaningful commit messages: Include context about why the change is being made.
Consider PR approach for significant changes:
Use pr_create()
instead of direct commits for changes that
might need review.
Store templates in version control: Keep your template files in their own repository.
Create a deployment script: For regular deployments, create an R script that can be run repeatedly.
Regarding the last recommendation, you can create a deployment script that automates the process of updating files across multiple repositories. Here’s an example script that updates CI/CD workflows and deploys configuration files to all repositories in an organization:
library(multideploy)
# Get repositories
api_repos <- repos("my-organization", filter_regex = "^api-")
service_repos <- repos("my-organization", filter_regex = "^service-")
all_repos <- rbind(api_repos, service_repos)
# Create file mappings
workflow_mapping <- file_mapping(
dir = "templates/workflows",
pattern = "\\.ya?ml$",
target_prefix = ".github/workflows/",
preserve_structure = TRUE
)
config_mapping <- file_mapping(
"templates/.lintr" = ".lintr",
"templates/.editorconfig" = ".editorconfig",
"templates/CONTRIBUTING.md" = "CONTRIBUTING.md"
)
# Create PRs for workflow changes
pr_create(
repos = all_repos,
branch_name = "chore/update-workflows",
title = "Update CI/CD workflows",
body = "Update workflows to organization standards",
file_mapping = workflow_mapping,
dry_run = FALSE
)
If you want to deploy the files directly without creating pull requests, you can use the following snippet to directly deploy the configuration files:
# Directly deploy config files
for (local_file in names(config_mapping)) {
target_path <- config_mapping[[local_file]]
file_deploy(
source_file = local_file,
target_path = target_path,
repos = all_repos,
commit_message = paste("Update", basename(target_path), "to organization standards"),
dry_run = FALSE
)
}
The {multideploy}
package streamlines the process of
maintaining consistent files across multiple GitHub repositories. By
automating deployment, you can ensure standardization while saving
significant time and effort.