Automating the syncing of files between repos with GitHub Actions

Featured image for sharing metadata for article

As I wrote in Checking if files are synced between repos with GitHub Actions, if you're vendoring-and-periodically-updating files, trying to remember to do it is always a pain.

I've now decided to actually write a re-usable action that can be used to perform this work, prompted by a discussion around oapi-codegen, as the official project recommendation is to vendor files. Additionally, this is something that'll be useful at work (and with previous colleagues' setups too) so thought it'd be good to see how it'd be possible.

I've built this as a re-usable action so it's possible to reuse the same definition across multiple files (be they OpenAPI specs, Dependabot configuration or otherwise) as well as define rules around how often to update i.e. on every push, or on a schedule.

For instance, via the docs, we could use this for a multi-purpose Actions job that updates three files like so:

name: "Update OpenAPI specifications and raise PRs if changes needed"
permissions:
  contents: write
  # note that this also requires that GitHub Actions can raise PRs via steps in https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#preventing-github-actions-from-creating-or-approving-pull-requests
  pull-requests: write
on:
  schedule:
  - cron:  '30 5,17 * * *'
  workflow_dispatch: {}
jobs:
  sync-petstore:
    uses: jamietanna/actions/.github/workflows/reusable-sync-file.yml@main
    with:
      identifier: oapi-codegen-petstore
      remote_slug: deepmap/oapi-codegen
      remote_path: examples/petstore-expanded/petstore-expanded.yaml
      local_path: petstore.yaml
    secrets:
      # as this is a public repo, we can sync it easily with the inbuilt token
      cross_repo_github_token: ${{ secrets.GITHUB_TOKEN }}

  # and for a private repo that has two specs in it
  sync-private-admin-api:
    uses: jamietanna/actions/.github/workflows/reusable-sync-file.yml@main
    with:
      identifier: private-admin-api
      remote_slug: jamietanna/example-github-actions-sync-files-private
      remote_path: api/admin-api.yml
      local_path: admin-api.yml
    secrets:
      # this requires a PAT
      cross_repo_github_token: ${{ secrets.PAT }}

  sync-private-another-api:
    uses: jamietanna/actions/.github/workflows/reusable-sync-file.yml@main
    with:
      identifier: private-another-api
      remote_slug: jamietanna/example-github-actions-sync-files-private
      remote_path: api/another-api.yml
      local_path: another-api.yml
    secrets:
      # this requires a PAT
      cross_repo_github_token: ${{ secrets.PAT }}

Notice that we can wire in access tokens, as well as the relevant configuration for where to grab files from and update them in.

To see it in action, see an example PR for the Swagger Petstore API spec and a (fake) specification from a private repository.

When GitHub Actions runs, you can see job summaries i.e. to get the link to the created/updated PRs.

I hope that before long I'll get round to implementing this in Renovate but until then, this is a good solution.

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #github #github-actions.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.