Skip to content

.github/workflows/repo-sync.yml #5677

.github/workflows/repo-sync.yml

.github/workflows/repo-sync.yml #5677

Workflow file for this run

# Note this is almost fully copied from
# https://github.com/github/docs/blob/main/.github/workflows/repo-sync.yml
# with the exception of:
# - the `cron` schedule
# - the `if` condition to allow this to run only in `dev-portal-internal`
# - the `source_repo` has been updated to `dev-portal`
# - the PAT credentials are from our `hashibot-web` account. They're managed in
# the `dev-portal-internal` repository secrets.
on:
workflow_dispatch:
schedule:
- cron: '0 */2 * * *' # https://crontab.guru/every-2-hours
permissions:
contents: write
pull-requests: write
jobs:
repo-sync:
if: github.repository == 'hashicorp/dev-portal-internal'
name: Repo Sync
runs-on: ubuntu-latest
steps:
- name: Check out repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Sync repo to branch
uses: repo-sync/github-sync@3832fe8e2be32372e1b3970bbae8e7079edeec88
with:
source_repo: https://${{ secrets.PAT_HASHIBOT_WEB_DEV_PORTAL_INTERNAL_SYNC }}@github.com/hashicorp/dev-portal.git
source_branch: main
destination_branch: repo-sync
github_token: ${{ secrets.PAT_HASHIBOT_WEB_DEV_PORTAL_INTERNAL_SYNC }}
- name: Ship pull request
uses: actions/github-script@e69ef5462fd455e02edcaf4dd7708eda96b9eda0
with:
github-token: ${{ secrets.PAT_HASHIBOT_WEB_DEV_PORTAL_INTERNAL_SYNC }}
result-encoding: string
script: |
const { owner, repo } = context.repo
const head = 'repo-sync'
const base = 'main'
async function closePullRequest(prNumber) {
console.log('Closing pull request', prNumber)
await github.rest.pulls.update({
owner,
repo,
pull_number: prNumber,
state: 'closed'
})
// Error loud here, so no try/catch
console.log('Closed pull request', prNumber)
}
console.log('Closing any existing pull requests')
const { data: existingPulls } = await github.rest.pulls.list({ owner, repo, head, base })
if (existingPulls.length) {
console.log('Found existing pull requests', existingPulls.map(pull => pull.number))
for (const pull of existingPulls) {
await closePullRequest(pull.number)
}
console.log('Closed existing pull requests')
}
try {
const { data } = await github.rest.repos.compareCommits({
owner,
repo,
head,
base,
})
const { files } = data
console.log(`File changes between ${head} and ${base}:`, files)
if (!files.length) {
console.log('No files changed, bailing')
return
}
} catch (err) {
console.error(`Unable to compute the files difference between ${head} and ${base}`, err.message)
}
console.log('Creating a new pull request')
const body = `
This is an automated pull request to sync changes between the public and private repos.
Our bot will merge this pull request automatically.
To preserve continuity across repos, _do not squash_ this pull request.
`
let pull, pull_number
try {
const response = await github.rest.pulls.create({
owner,
repo,
head,
base,
title: 'Repo sync',
body,
})
pull = response.data
pull_number = pull.number
console.log('Created pull request successfully', pull.html_url)
} catch (err) {
// Don't error/alert if there's no commits to sync
// Don't throw if > 100 pulls with same head_sha issue
if (err.message?.includes('No commits') || err.message?.includes('same head_sha')) {
console.log(err.message)
return
}
throw err
}
console.log('Locking conversations to prevent spam')
try {
await github.rest.issues.lock({
...context.repo,
issue_number: pull_number,
lock_reason: 'spam'
})
console.log('Locked the pull request to prevent spam')
} catch (error) {
console.error('Failed to lock the pull request.', error)
// Don't fail the workflow
}
console.log('Counting files changed')
const { data: prFiles } = await github.rest.pulls.listFiles({ owner, repo, pull_number })
if (prFiles.length) {
console.log(prFiles.length, 'files have changed')
} else {
console.log('No files changed, closing')
await closePullRequest(pull_number)
return
}
console.log('Checking for merge conflicts')
if (pull.mergeable_state === 'dirty') {
console.log('Pull request has a conflict', pull.html_url)
throw new Error('Pull request has a conflict, please resolve manually')
}
console.log('No detected merge conflicts')
console.log('Merging the pull request')
// Admin merge pull request to avoid squash
await github.rest.pulls.merge({
owner,
repo,
pull_number,
merge_method: 'merge',
})
// Error loud here, so no try/catch
console.log('Merged the pull request successfully')