--- title: "Getting Started with multideploy" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with multideploy} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r} #| include: FALSE knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Introduction 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. ## Setup and Authentication First, load the `{multideploy}` package: ```{r} #| label: setup-vignette #| eval: FALSE library(multideploy) ``` Before using `{multideploy}`, you need to authenticate with GitHub. The package uses the [`gh`](https://github.com/r-lib/gh) package for authentication, which 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 `GITHUB_TOKEN` environment variables. This token can be set directly within the R script via: ```{r} #| label: auth-session-vignette #| eval: FALSE # 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: ```{r} #| label: auth-credentials-vignette #| eval: false gitcreds::gitcreds_set() ``` Your PAT needs appropriate permissions to access and modify repositories. At a minimum, you'll need: - `repo` scope for accessing private repositories - `workflow` scope if you're modifying GitHub Actions workflows ## Managing Repositories ### Listing Repositories The `repos()` function allows you to list repositories for a user or organization: ```{r} #| label: repos-list-vignette #| eval: FALSE # List repositories for a user user_repos <- repos("username") # List repositories for an organization org_repos <- repos("orgname", type = "public") # Filter repositories by name pattern api_repos <- repos("orgname", filter_regex = "^api-") # View the repositories head(api_repos) ``` ### Listing Organizations If you're a member of multiple organizations, you can list them with: ```{r orgs} #| label: orgs-list-vignette #| eval: FALSE my_orgs <- orgs() print(my_orgs) ``` ## Working with Files ### Getting File Content You can retrieve the content of a file from a GitHub repository: ```{r} #| label: file-content-vignette #| eval: FALSE # Get content of a file workflow_file <- file_content("username/repo", ".github/workflows/ci.yml") # View the content cat(workflow_file$content) ``` ### Creating or Updating Files To create or update a file in a repository: ```{r} #| label: file-update-vignette #| eval: FALSE # Update a file result <- file_update( repo = "username/repo", path = ".github/workflows/ci.yml", content = "updated workflow content...", message = "Update CI workflow" ) ``` ## Deploying Files Across Repositories The core functionality of `{multideploy}` is deploying files across multiple repositories. This can be done in two ways: ### Direct File Deployment Deploy a single file to multiple repositories: ```{r} #| label: file-deploy-vignette #| eval: FALSE # 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) ``` ### Creating Pull Requests For changes that require review, you can create pull requests: ```{r} #| label: file-mapping-and-pull-requests-vignette #| eval: FALSE # 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) ``` ## Advanced Use Cases ### Deploying Files with Directory Structure You can deploy all files from a directory while preserving their structure: ```{r} #| label: dir-mapping-vignette #| eval: FALSE # 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 ) ``` ### Dry Run Mode Before making actual changes, you can preview them using dry run mode: ```{r} #| label: dry-run-vignette #| eval: FALSE # Preview file deployment without making changes dry_results <- file_deploy( source_file = "templates/ci.yml", target_path = ".github/workflows/ci.yml", repos = repos, dry_run = TRUE ) # View what would happen print(dry_results) ``` ### Filtering and Targeting Repositories You can combine repository filtering with deployment to target specific subsets of repositories: ```{r targeting} #| label: target-repos-vignette #| eval: FALSE # 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 ) ``` ## Recommendations If you're deploying files across multiple repositories, we recommend taking into consideration the following: 1. **Start with dry runs**: Always use `dry_run = TRUE` first to preview changes. 2. **Use meaningful commit messages**: Include context about why the change is being made. 3. **Consider PR approach for significant changes**: Use `pr_create()` instead of direct commits for changes that might need review. 4. **Store templates in version control**: Keep your template files in their own repository. 5. **Create a deployment script**: For regular deployments, create an R script that can be run repeatedly. ## Deployment Script Example 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: ```{r} #| label: deployment-script-vignette #| eval: FALSE 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: ```{r} #| label: deployment-script-custom-vignette #| eval: FALSE # 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 ) } ``` # Fin 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.