Skip to content

Commit f0fc039

Browse files
committed
Add vignette
1 parent 15d0b08 commit f0fc039

File tree

2 files changed

+359
-0
lines changed

2 files changed

+359
-0
lines changed

vignettes/.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.html
2+
*.R

vignettes/multideploy.Rmd

+357
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
---
2+
title: "Getting Started with multideploy"
3+
output: rmarkdown::html_vignette
4+
vignette: >
5+
%\VignetteIndexEntry{Getting Started with multideploy}
6+
%\VignetteEngine{knitr::rmarkdown}
7+
%\VignetteEncoding{UTF-8}
8+
---
9+
10+
```{r}
11+
#| include: FALSE
12+
knitr::opts_chunk$set(
13+
collapse = TRUE,
14+
comment = "#>"
15+
)
16+
```
17+
18+
## Introduction
19+
20+
The `multideploy` package provides a streamlined way to deploy file changes
21+
across multiple GitHub repositories. Whether you're managing standardized CI/CD
22+
configurations, common utility scripts, code style definitions, or any other
23+
files that should be consistent across repositories, `multideploy` helps
24+
automate this process.
25+
26+
This vignette will guide you through the main functionality of the package with
27+
practical examples.
28+
29+
## Setup and Authentication
30+
31+
First, load the multideploy package:
32+
33+
```{r}
34+
#| label: setup
35+
#| eval: FALSE
36+
library(multideploy)
37+
```
38+
39+
Before using `multideploy`, you need to authenticate with GitHub. The package
40+
uses the [`gh`](https://github.com/r-lib/gh) package for authentication, which
41+
looks for a [GitHub Personal Access Token (PAT)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) in the `GITHUB_PAT` or
42+
`GITHUB_TOKEN` environment variables. This token can be set directly within the
43+
R script via:
44+
45+
```{r}
46+
#| label: auth
47+
#| eval: FALSE
48+
# Set GitHub PAT (or better, use .Renviron)
49+
Sys.setenv(GITHUB_PAT = askpass::askpass("What is your GitHub Personal Access Token (PAT) ?"))
50+
```
51+
52+
For regular use, it's recommended to add your PAT to the git credential system
53+
through the `gitcreds` package:
54+
55+
```r
56+
gitcreds::gitcreds_set()
57+
```
58+
59+
Alternatively, you can set the PAT directly in your `.Renviron` file by running:
60+
61+
```r
62+
file.edit("~/.Renviron")
63+
```
64+
65+
Then, type:
66+
67+
```bash
68+
GITHUB_PAT=your_github_pat_here
69+
```
70+
71+
Your PAT needs appropriate permissions to access and modify repositories.
72+
At a minimum, you'll need:
73+
74+
- `repo` scope for accessing private repositories
75+
- `workflow` scope if you're modifying GitHub Actions workflows
76+
77+
## Managing Repositories
78+
79+
### Listing Repositories
80+
81+
The `repos()` function allows you to list repositories for a user or organization:
82+
83+
```{r}
84+
#| label: repos
85+
#| eval: FALSE
86+
# List repositories for a user
87+
user_repos <- repos("username")
88+
89+
# List repositories for an organization
90+
org_repos <- repos("orgname", type = "public")
91+
92+
# Filter repositories by name pattern
93+
api_repos <- repos("orgname", filter_regex = "^api-")
94+
95+
# View the repositories
96+
head(api_repos)
97+
```
98+
99+
### Listing Organizations
100+
101+
If you're a member of multiple organizations, you can list them with:
102+
103+
```{r orgs}
104+
#| label: orgs
105+
#| eval: FALSE
106+
my_orgs <- orgs()
107+
print(my_orgs)
108+
```
109+
110+
## Working with Files
111+
112+
### Getting File Content
113+
114+
You can retrieve the content of a file from a GitHub repository:
115+
116+
```{r}
117+
#| label: file-content
118+
#| eval: FALSE
119+
# Get content of a file
120+
workflow_file <- file_content("username/repo", ".github/workflows/ci.yml")
121+
122+
# View the content
123+
cat(workflow_file$content)
124+
```
125+
126+
### Creating or Updating Files
127+
128+
To create or update a file in a repository:
129+
130+
```{r}
131+
#| label: file-update
132+
#| eval: FALSE
133+
# Update a file
134+
result <- file_update(
135+
repo = "username/repo",
136+
path = ".github/workflows/ci.yml",
137+
content = "updated workflow content...",
138+
message = "Update CI workflow"
139+
)
140+
```
141+
142+
## Deploying Files Across Repositories
143+
144+
The core functionality of `multideploy` is deploying files across multiple repositories. This can be done in two ways:
145+
146+
### Direct File Deployment
147+
148+
Deploy a single file to multiple repositories:
149+
150+
```{r}
151+
#| label: file-deploy
152+
#| eval: FALSE
153+
# Get repositories
154+
repos <- repos("orgname", filter_regex = "^api-")
155+
156+
# Deploy a file to all repositories
157+
results <- file_deploy(
158+
source_file = "templates/ci.yml",
159+
target_path = ".github/workflows/ci.yml",
160+
repos = repos,
161+
commit_message = "Standardize CI workflow"
162+
)
163+
164+
# View deployment results
165+
print(results)
166+
```
167+
168+
### Creating Pull Requests
169+
170+
For changes that require review, you can create pull requests:
171+
172+
```{r}
173+
#| label: file-mapping-and-pull-requests
174+
#| eval: FALSE
175+
# Create a mapping of files to deploy
176+
mapping <- file_mapping(
177+
"templates/ci.yml" = ".github/workflows/ci.yml",
178+
"templates/lint.R" = ".lintr",
179+
"templates/codeowners" = ".github/CODEOWNERS"
180+
)
181+
182+
# Create pull requests with these changes
183+
pr_results <- pr_create(
184+
repos = repos,
185+
branch_name = "feature/standardize-configs",
186+
title = "Standardize repository configurations",
187+
body = "This PR updates CI workflows, linting settings, and CODEOWNERS file to match organization standards.",
188+
file_mapping = mapping
189+
)
190+
191+
# View PR creation results
192+
print(pr_results)
193+
```
194+
195+
## Advanced Use Cases
196+
197+
### Deploying Files with Directory Structure
198+
199+
You can deploy all files from a directory while preserving their structure:
200+
201+
```{r}
202+
#| label: dir-mapping
203+
#| eval: FALSE
204+
# Create mapping from a directory
205+
workflow_mapping <- file_mapping(
206+
dir = "templates/workflows",
207+
pattern = "\\.ya?ml$",
208+
target_prefix = ".github/workflows/",
209+
preserve_structure = TRUE
210+
)
211+
212+
# Use this mapping to create PRs
213+
pr_create(
214+
repos = repos,
215+
branch_name = "feature/update-workflows",
216+
title = "Update all workflow files",
217+
body = "Standardize all GitHub Actions workflow files",
218+
file_mapping = workflow_mapping
219+
)
220+
```
221+
222+
### Dry Run Mode
223+
224+
Before making actual changes, you can preview them using dry run mode:
225+
226+
```{r}
227+
#| label: dry-run
228+
#| eval: FALSE
229+
# Preview file deployment without making changes
230+
dry_results <- file_deploy(
231+
source_file = "templates/ci.yml",
232+
target_path = ".github/workflows/ci.yml",
233+
repos = repos,
234+
dry_run = TRUE
235+
)
236+
237+
# View what would happen
238+
print(dry_results)
239+
```
240+
241+
### Filtering and Targeting Repositories
242+
243+
You can combine repository filtering with deployment to target specific subsets of repositories:
244+
245+
```{r targeting}
246+
#| label: target-repos
247+
#| eval: FALSE
248+
# Get all organization repositories
249+
all_repos <- repos("orgname")
250+
251+
# Filter to only Java repositories
252+
r_repos <- all_repos[grepl("r", all_repos$name), ]
253+
254+
# Deploy R-specific configuration
255+
file_deploy(
256+
source_file = "templates/R/.Rbuildignore",
257+
target_path = ".Rbuildignore",
258+
repos = r_repos
259+
)
260+
261+
# Filter to only Python repositories
262+
python_repos <- all_repos[grepl("python", all_repos$name), ]
263+
264+
# Deploy Python-specific configuration
265+
file_deploy(
266+
source_file = "templates/python/pylintrc",
267+
target_path = ".pylintrc",
268+
repos = python_repos
269+
)
270+
```
271+
272+
## Recommendations
273+
274+
If you're deploying files across multiple repositories, we recommend taking
275+
into consideration the following:
276+
277+
1. **Start with dry runs**: Always use `dry_run = TRUE` first to preview changes.
278+
279+
2. **Use meaningful commit messages**: Include context about why the change is
280+
being made.
281+
282+
3. **Consider PR approach for significant changes**: Use `pr_create()` instead
283+
of direct commits for changes that might need review.
284+
285+
4. **Store templates in version control**: Keep your template files in their own
286+
repository.
287+
288+
5. **Create a deployment script**: For regular deployments, create an R script
289+
that can be run repeatedly.
290+
291+
## Deployment Script Example
292+
293+
Regarding the last recommendation, you can create a deployment script that
294+
automates the process of updating files across multiple repositories. Here's an
295+
example script that updates CI/CD workflows and deploys configuration files to
296+
all repositories in an organization:
297+
298+
```{r}
299+
#| label: deployment-script
300+
#| eval: FALSE
301+
library(multideploy)
302+
303+
# Get repositories
304+
api_repos <- repos("my-organization", filter_regex = "^api-")
305+
service_repos <- repos("my-organization", filter_regex = "^service-")
306+
all_repos <- rbind(api_repos, service_repos)
307+
308+
# Create file mappings
309+
workflow_mapping <- file_mapping(
310+
dir = "templates/workflows",
311+
pattern = "\\.ya?ml$",
312+
target_prefix = ".github/workflows/",
313+
preserve_structure = TRUE
314+
)
315+
316+
config_mapping <- file_mapping(
317+
"templates/.lintr" = ".lintr",
318+
"templates/.editorconfig" = ".editorconfig",
319+
"templates/CONTRIBUTING.md" = "CONTRIBUTING.md"
320+
)
321+
322+
# Create PRs for workflow changes
323+
pr_create(
324+
repos = all_repos,
325+
branch_name = "chore/update-workflows",
326+
title = "Update CI/CD workflows",
327+
body = "Update workflows to organization standards",
328+
file_mapping = workflow_mapping,
329+
dry_run = FALSE
330+
)
331+
```
332+
333+
If you want to deploy the files directly without creating pull requests, you can
334+
use the following snippet to directly deploy the configuration files:
335+
336+
```{r}
337+
#| label: deployment-script-custom
338+
#| eval: FALSE
339+
# Directly deploy config files
340+
for (local_file in names(config_mapping)) {
341+
target_path <- config_mapping[[local_file]]
342+
343+
file_deploy(
344+
source_file = local_file,
345+
target_path = target_path,
346+
repos = all_repos,
347+
commit_message = paste("Update", basename(target_path), "to organization standards"),
348+
dry_run = FALSE
349+
)
350+
}
351+
```
352+
353+
# Fin
354+
355+
The `multideploy` package streamlines the process of maintaining consistent
356+
files across multiple GitHub repositories. By automating deployment, you can
357+
ensure standardization while saving significant time and effort.

0 commit comments

Comments
 (0)