Skip to content

fix: use_github_copilot() corrupts ${{ }} GitHub Actions expressions #44

@jonthegeek

Description

@jonthegeek

Summary

As a package developer, in order to install working GitHub Actions workflows, I would like use_github_copilot() to write workflow files without corrupting ${{ }} expressions.

Details

The templates in inst/templates/workflows/ contain GitHub Actions expressions such as ${{ secrets.GITHUB_TOKEN }} and ${{ inputs.r-version }}. Because .use_template() delegates to usethis::use_template(), which renders templates via the whisker engine, the {{ }} delimiters are interpreted as template variables. Since these workflows have no package-specific data, whisker silently strips the variable content, producing broken YAML (e.g., $ instead of ${{ secrets.GITHUB_TOKEN }}).

The fix has two parts:

  1. Add a .use_template_as_is() internal helper that reads the raw template bytes from inst/templates/ and writes them verbatim using usethis::write_over(), then calls usethis::edit_file() when open = TRUE. This is the same observable behavior as usethis::use_template(), but skips the render_template() / whisker step entirely. Check the code of usethis::use_template for the general idea of what's needed, but we should also handle overwrite in our helper.
  2. Update use_github_copilot() to call .use_template_as_is() instead of .use_template() for both workflow files.

Escaping {{ / }} in the templates is an alternative but requires ongoing maintenance every time a template is edited, and the escape syntax is not obvious to future contributors.

Behavior

Current (broken):

  • use_github_copilot() produces a copilot-setup-steps.yml and install/action.yml in which ${{ ... }} expressions are partially or fully stripped, rendering the workflows invalid.

Expected:

  • Both installed files are byte-for-byte identical to their templates (no whisker interpolation).
  • use_github_copilot() tests verify that the installed files contain ${{ literally (e.g., ${{ secrets.GITHUB_TOKEN }} in copilot-setup-steps.yml, ${{ inputs.r-version }} in install/action.yml).

Behavior of .use_template_as_is(template, save_as, open = FALSE):

  • Reads the template from system.file("templates", template, package = "pkgskills").
  • Processes overwrite arg as in (or with) .path_proj_save_as and ultimately .check_path_writable(). We may want to refactor .use_template() to likewise move the .path_proj_save_as() step "inside" the helper, if that makes sense and doesn't break tests.
  • Writes the content verbatim to usethis::proj_path(save_as) via usethis::write_over().
  • Calls usethis::edit_file(usethis::proj_path(save_as)) when open = TRUE.

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions