🎉 Initial commit

This commit is contained in:
BetaHuhn 2021-01-08 21:47:49 +01:00
commit 1694b0cec6
24 changed files with 39556 additions and 0 deletions

1
.eslintrc.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@betahuhn/config').eslint

30
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,30 @@
---
name: 🐛 Bug report
about: Create a report to help us improve
labels: bug
---
**🐞 Describe the bug**
A clear and concise description of what the bug is.
**📚 To Reproduce**
Steps to reproduce the behavior.
**💡 Expected behavior**
A clear and concise description of what you expected to happen.
**🖼️ Screenshots**
If applicable, add screenshots to help explain your problem.
**⚙️ Environment**
- OS: [e.g. Ubuntu 18.04]
- Action version: [e.g. v1.0.0]
**📋 Additional context**
Add any other context about the problem here.

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: 📚 Docs
url: https://github.com/BetaHuhn/action-github-file-sync#-usage
about: Checkout action-github-file-sync's documentation.
- name: 🚀 Feature Request
url: https://github.com/BetaHuhn/action-github-file-sync/discussions/new?category=ideas
about: Share ideas for new features
- name: ❓ Ask a Question
url: https://github.com/BetaHuhn/action-github-file-sync/discussions/new?category=q-a
about: Ask the community for help

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"

12
.github/sync.yml vendored Normal file
View File

@ -0,0 +1,12 @@
BetaHuhn/gh-repo-automation:
- source: .github/workflows/test.yml
dest: .github/workflows/test.yml
replace: true
- source: .github/dependabot.yml
dest: .github/dependabot.yml
replace: true
BetaHuhn/gh-repo-automation:
- source: .github/workflows/test.yml
dest: .github/workflows/test2.yml
replace: true

30
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Build CI
on:
release:
types: [created]
workflow_dispatch:
jobs:
build:
name: Build files
runs-on: ubuntu-18.04
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 14
- name: Cache node modules
uses: c-hive/gha-npm-cache@v1
- name: Install dependencies
run: npm ci
- name: Build files
run: npm run build
- name: Commit build
uses: stefanzweifel/git-auto-commit-action@v4.8.0
with:
commit_message: ":rocket: Rebuild files [skip ci]"
commit_user_name: BetaHuhn Bot
commit_user_email: bot@mxis.ch
commit_author: BetaHuhn Bot <bot@mxis.ch>

26
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: Lint CI
on:
push:
branches-ignore:
- master
pull_request:
branches-ignore:
- master
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 14
- name: Cache node modules
uses: c-hive/gha-npm-cache@v1
- name: Install dependencies
run: npm ci
- name: Run lint command
run: npm run lint

13
.github/workflows/release-scheduler.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Release Scheduler CI
on:
schedule:
- cron: "0 0 * * 1"
workflow_dispatch:
jobs:
releaseScheduler:
runs-on: ubuntu-latest
steps:
- name: Run release-scheduler
uses: koj-co/release-scheduler@master
env:
GH_PAT: ${{ secrets.GH_PAT }}

32
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Release CI
on:
push:
branches:
- master
jobs:
release:
name: Build and release
runs-on: ubuntu-18.04
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 14
- name: Cache node modules
uses: c-hive/gha-npm-cache@v1
- name: Install dependencies
run: npm ci
- name: Build TypeScript
run: npm run build
- name: Release
run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GIT_AUTHOR_NAME: "BetaHuhn Bot"
GIT_AUTHOR_EMAIL: "bot@mxis.ch"
GIT_COMMITTER_NAME: "BetaHuhn Bot"
GIT_COMMITTER_EMAIL: "bot@mxis.ch"

19
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: "Stale Issues CI"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GH_PAT }}
stale-issue-message: "⚠️ This issue has not seen any activity in the past 2 months so I'm marking it as stale. I'll close it if it doesn't see any activity in the coming week."
stale-pr-message: "⚠️ This PR has not seen any activity in the past 2 months so I'm marking it as stale. I'll close it if it doesn't see any activity in the coming week."
days-before-stale: 60
days-before-close: 7
stale-issue-label: "wontfix"
exempt-issue-labels: "wip"
stale-pr-label: "wontfix"
exempt-pr-labels: "wip"

26
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: Test CI
# test
on:
push:
branches-ignore:
- master
pull_request:
branches-ignore:
- master
jobs:
test:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip-build]')"
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 14
- name: Cache node modules
uses: c-hive/gha-npm-cache@v1
- name: Install dependencies
run: npm ci
- name: Run build command
run: npm run build

61
.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
node_modules/
# Editors
.vscode/
.idea/
*.iml
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Other Dependency directories
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next

0
CHANGELOG.md Normal file
View File

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Maximilian Schiller
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

86
README.md Normal file
View File

@ -0,0 +1,86 @@
# action-github-file-sync
🚧 **UNDER DEVELOPMENT** 🚧
## Usage
Use the `sync.yml` file to specify which files should be synced to which repos.
The top-level key should be used to specify the target repository in the format `username`/`repository-name`@`branch`, after that you can list all the files you want to sync to that individual repository:
```yml
user/repo:
- path/to/file.txt
user/repo2:
- path/to/file2.txt
```
There are multiple ways to specify which files to sync to each individual repository.
### List individual files
```yml
user/repo:
- .github/workflows/build.yml
- LICENSE
- .gitignore
```
### Different destination path/filename
```yml
user/repo:
- source: workflows/build.yml
dest: .github/workflows/build.yml
- source: LICENSE.md
dest: LICENSE
```
### Sync entire directories (coming soon)
```yml
user/repo:
- source: workflows/build.yml
dest: .github/workflows/build.yml
- source: LICENSE.md
dest: LICENSE
```
### Match files with regex pattern (coming soon)
```yml
user/repo:
- pattern: |
^LICENSE$
^.github/workflows/sync-.*
```
### Don't replace existing file
```yml
user/repo:
- source: .github/workflows/lint.yml
replace: false
```
### Don't delete non-existing file (coming soon)
```yml
user/repo:
- source: .github/workflows/lint.yml
delete: false
```
### Sync the same files to multiple repositories
```yml
group:
repos: |
user/repo
user/repo
files:
- source: workflows/build.yml
dest: .github/workflows/build.yml
- source: LICENSE.md
dest: LICENSE
```

52
action.yml Normal file
View File

@ -0,0 +1,52 @@
name: 'GitHub File Sync'
description: 'GitHub Action to Sync Files like Workflows Between Repositories.'
author: 'BetaHuhn'
inputs:
GH_PAT:
description: |
GitHub Personal Access Token to use to get repos and write secrets
required: false
CONFIG_PATH:
description: |
The path for the sync configuration file
required: false
PR_LABELS:
description: |
Labels which will be added to the pull request. Defaults to resync. Set to false to turn off
required: false
ASSIGNEES:
description: |
People to assign to the pull request. Defaults to none
required: false
COMMIT_PREFIX:
description: |
Prefix for commit message and pull request title. Defaults to 🔄
required: false
COMMIT_EACH_FILE:
description: |
Commit each file seperately. Defaults to true
required: false
GIT_EMAIL:
description: |
The e-mail address used to commit the synced files. Defaults to the email of the GitHub PAT
required: false
GIT_USERNAME:
description: |
The username used to commit the synced files. Defaults to the username of the GitHub PAT
required: false
TMP_DIR:
description: |
The working directory where all sync operations will be done. Defaults to `tmp-${Date.now().toString()}`
required: false
DRY_RUN:
description: "Run everything except for nothing will be updated."
required: false
runs:
using: 'node14'
main: 'dist/index.js'
branding:
icon: 'upload-cloud'
color: 'gray-dark'

30896
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

7638
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

37
package.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "action-github-file-sync",
"version": "0.0.1",
"description": "GitHub Action to Sync Files like Workflows Between Repositories.",
"main": "dist/index.js",
"scripts": {
"lint": "eslint ./src",
"build": "ncc build src/index.js -o dist"
},
"repository": {
"type": "git",
"url": "git+https://github.com/betahuhn/action-github-file-sync.git"
},
"keywords": [
"GitHub",
"Actions"
],
"author": "Maximilian Schiller <schiller@mxis.ch>",
"license": "MIT",
"bugs": {
"url": "https://github.com/betahuhn/action-github-file-sync/issues"
},
"homepage": "https://github.com/betahuhn/action-github-file-sync#readme",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/github": "^2.2.0",
"@actions/io": "^1.0.2",
"@putout/git-status-porcelain": "^1.1.0",
"dotenv": "^8.2.0",
"js-yaml": "^4.0.0"
},
"devDependencies": {
"@betahuhn/config": "^1.0.2",
"@vercel/ncc": "^0.26.2",
"eslint": "^7.17.0"
}
}

1
release.config.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('@betahuhn/config').releaseMaster

175
src/config.js Normal file
View File

@ -0,0 +1,175 @@
const core = require('@actions/core')
const yaml = require('js-yaml')
const fs = require('fs')
require('dotenv').config()
const REPLACE_DEFAULT = true
const DELETE_DEFAULT = false
const getVar = ({ key, default: dft, required = false, array = false }) => {
const coreVar = core.getInput(key)
const envVar = process.env[key]
if (required === false && (coreVar === false || envVar === 'false'))
return undefined
if (coreVar !== undefined && coreVar.length >= 1)
return array ? coreVar.split('\n') : coreVar
if (envVar !== undefined && envVar.length >= 1)
return array ? envVar.split(',') : envVar
if (required === true)
return core.setFailed(`Variable ${ key } missing.`)
return dft
}
const context = {
GITHUB_TOKEN: getVar({
key: 'GH_PAT',
required: true
}),
GIT_EMAIL: getVar({
key: 'GIT_EMAIL'
}),
GIT_USERNAME: getVar({
key: 'GIT_USERNAME'
}),
CONFIG_PATH: getVar({
key: 'CONFIG_PATH',
default: '.github/sync.yml'
}),
COMMIT_PREFIX: getVar({
key: 'COMMIT_PREFIX',
default: '🔄'
}),
COMMIT_EACH_FILE: getVar({
key: 'COMMIT_EACH_FILE',
default: true
}),
PR_LABELS: getVar({
key: 'PR_LABELS',
default: [ 'resync' ],
required: false,
array: true
}),
ASSIGNEES: getVar({
key: 'ASSIGNEES',
required: false,
array: true
}),
TMP_DIR: getVar({
key: 'TMP_DIR',
default: `tmp-${ Date.now().toString() }`
}),
DRY_RUN: getVar({
key: 'DRY_RUN',
default: false
}),
GITHUB_REPOSITORY: getVar({
key: 'GITHUB_REPOSITORY',
required: true
})
}
core.setSecret(context.GITHUB_TOKEN)
core.debug(
JSON.stringify(
context,
null,
2
)
)
const parseRepoName = (fullRepo) => {
const user = fullRepo.split('/')[0]
const name = fullRepo.split('/')[1].split('@')[0]
const branch = fullRepo.split('/')[1].split('@')[1] || 'default'
return {
fullName: `${ user }/${ name }`,
user,
name,
branch
}
}
const parseFiles = (files) => {
return files.map((item) => {
if (typeof item === 'string') {
return {
source: item,
dest: item,
replace: REPLACE_DEFAULT,
delete: DELETE_DEFAULT
}
}
if (item.source !== undefined) {
return {
source: item.source,
dest: item.dest !== undefined ? item.dest : item.source,
replace: item.replace !== undefined ? item.replace : REPLACE_DEFAULT,
delete: item.delete !== undefined ? item.delete : DELETE_DEFAULT
}
}
if (item.pattern !== undefined) {
return {
pattern: item.pattern,
dest: item.dest,
replace: item.replace !== undefined ? item.replace : REPLACE_DEFAULT,
delete: item.delete !== undefined ? item.delete : DELETE_DEFAULT
}
}
core.wanr('Warn: No source files specified')
})
}
const parseConfig = async () => {
const fileContent = await fs.promises.readFile(context.CONFIG_PATH)
const configObject = yaml.load(fileContent.toString())
const result = []
Object.keys(configObject).forEach((key) => {
if (key === 'group') {
const object = configObject[key]
const repos = typeof object.repos === 'string' ? object.repos.split('\n').filter((n) => n) : object.repos
repos.forEach((name) => {
const files = parseFiles(object.files)
result.push({
repo: parseRepoName(name),
files
})
})
} else {
const files = parseFiles(configObject[key])
result.push({
repo: parseRepoName(key),
files
})
}
})
return result
}
while (fs.existsSync(context.TMP_DIR)) {
context.TMP_DIR = `tmp-${ Date.now().toString() }`
core.warn(`TEMP_DIR already exists. Using "${ context.TMP_DIR }" now.`)
}
module.exports = {
...context,
parseConfig
}

139
src/git.js Normal file
View File

@ -0,0 +1,139 @@
const { exec } = require('child_process')
const { parse } = require('@putout/git-status-porcelain')
const core = require('@actions/core')
const path = require('path')
const {
GITHUB_TOKEN,
GIT_USERNAME,
GIT_EMAIL,
TMP_DIR,
COMMIT_PREFIX,
GITHUB_REPOSITORY
} = require('./config')
const init = (repo) => {
const localPath = path.join(TMP_DIR, repo.fullName)
const gitUrl = `https://${ GITHUB_TOKEN }@github.com/${ repo.fullName }.git`
const clone = () => {
core.info(`Cloning ${ repo.fullName } into ${ localPath }`)
return execCmd(
`git clone --depth 1 ${ repo.branch !== 'default' ? '--branch "' + repo.branch + '"' : '' } ${ gitUrl } ${ localPath }`
)
}
const setIdentity = async (client) => {
let username = GIT_USERNAME
let email = GIT_EMAIL
if (email === undefined) {
const { data } = await client.users.getAuthenticated()
email = data.email
username = data.login
}
core.info(`Setting git user to email: ${ email }, username: ${ username }`)
return execCmd(
`git config --local user.name "${ username }" && git config --local user.email "${ email }"`,
localPath
)
}
const currentBranch = async () => {
return execCmd(
`git rev-parse --abbrev-ref HEAD`,
localPath
)
}
const createPrBranch = async () => {
return new Promise((resolve, reject) => {
const timestamp = Math.round((new Date()).getTime() / 1000)
const newBranch = `file-sync/${ repo.branch }-${ timestamp }`
core.info(`Creating PR Branch ${ newBranch }`)
execCmd(
`git checkout -b "${ newBranch }"`,
localPath
).catch((err) => {
reject(err)
}).then(() => {
resolve(newBranch)
})
})
}
const add = async (file) => {
return execCmd(
`git add -f ${ file }`,
localPath
)
}
const hasChange = async () => {
const statusOutput = await execCmd(
`git status --porcelain`,
localPath
)
return parse(statusOutput).length !== 0
}
const commit = async (dest, source) => {
const message = dest !== undefined ? `${ COMMIT_PREFIX } Resynced '${ dest }' with '${ GITHUB_REPOSITORY }/${ source }'` : `${ COMMIT_PREFIX } Resynced file(s) with ${ GITHUB_REPOSITORY }`
return execCmd(
`git commit -m "${ message }"`,
localPath
)
}
const status = async () => {
return execCmd(
`git status`,
localPath
)
}
const push = async () => {
return execCmd(
`git push ${ gitUrl }`,
localPath
)
}
return {
localPath,
clone,
setIdentity,
createPrBranch,
add,
hasChange,
commit,
status,
push,
currentBranch
}
}
const execCmd = (command, workingDir) => {
core.debug(`EXEC: "${ command }" IN ${ workingDir }`)
return new Promise((resolve, reject) => {
exec(
command,
{
cwd: workingDir
},
function(error, stdout) {
error ? reject(error) : resolve(stdout.trim())
}
)
})
}
module.exports = {
init
}

39
src/helpers.js Normal file
View File

@ -0,0 +1,39 @@
// From https://github.com/toniov/p-iteration/blob/master/lib/static-methods.js - MIT © Antonio V
const forEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
// eslint-disable-next-line callback-return
await callback(array[index], index, array)
}
}
// From https://github.com/MartinKolarik/dedent-js/blob/master/src/index.ts - Copyright (c) 2015 Martin Kolárik. Released under the MIT license.
const dedent = function(templateStrings, ...values) {
const matches = []
const strings = typeof templateStrings === 'string' ? [ templateStrings ] : templateStrings.slice()
strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, '')
for (let i = 0; i < strings.length; i++) {
let match
// eslint-disable-next-line no-cond-assign
if (match = strings[i].match(/\n[\t ]+/g)) {
matches.push(...match)
}
}
if (matches.length) {
const size = Math.min(...matches.map((value) => value.length - 1))
const pattern = new RegExp(`\n[\t ]{${ size }}`, 'g')
for (let i = 0; i < strings.length; i++) {
strings[i] = strings[i].replace(pattern, '\n')
}
}
strings[0] = strings[0].replace(/^\r?\n/, '')
let string = strings[0]
for (let i = 0; i < values.length; i++) {
string += values[i] + strings[i + 1]
}
return string
}
module.exports = {
forEach,
dedent
}

201
src/index.js Normal file
View File

@ -0,0 +1,201 @@
const core = require('@actions/core')
const github = require('@actions/github')
const io = require('@actions/io')
const fs = require('fs')
const Git = require('./git')
const { forEach, dedent } = require('./helpers')
const {
parseConfig,
GITHUB_TOKEN,
COMMIT_EACH_FILE,
GITHUB_REPOSITORY,
COMMIT_PREFIX,
PR_LABELS,
ASSIGNEES,
DRY_RUN
} = require('./config')
const run = async () => {
const client = new github.GitHub(GITHUB_TOKEN)
const repos = await parseConfig()
await forEach(repos, async (item) => {
core.info(`Repository Info`)
core.info(`Slug : ${ item.repo.name }`)
core.info(`Owner : ${ item.repo.user }`)
core.info(`Https Url : https://github.com/${ item.repo.fullName }`)
core.info(`Branch : ${ item.repo.branch }`)
core.info(' ')
try {
const git = Git.init(item.repo)
await git.clone()
await git.setIdentity(client)
const currentBranch = await git.currentBranch()
const prBranch = await git.createPrBranch()
const modified = []
await forEach(item.files, async (file) => {
if (file.pattern !== undefined) {
core.warning('Pattern not supported yet')
return
}
const fileExists = fs.existsSync(file.source)
if (fileExists === false) {
core.warning(`Source file ${ file.source } not found`)
return
}
const stat = await fs.promises.lstat(file.source)
const isFile = stat.isFile()
if (isFile === false) {
core.warning(`Directory as source not supported yet`)
// io.cp(file.source, dest, { recursive: false, force: false })
return
}
const dest = `${ git.localPath }/${ file.dest }`
const destExists = fs.existsSync(dest)
if (destExists === true && file.replace === false) {
core.warning(`File already exists in destination and 'replace' option is set to false`)
return
}
core.info(`Copying ${ file.source } to ${ dest }`)
await io.cp(file.source, dest, { recursive: false, force: true }).catch((err) => {
core.error(`Unable to copy file.`)
core.error(err)
}).then(async () => {
await git.add(file.dest)
if (COMMIT_EACH_FILE === true) {
const hasChange = await git.hasChange()
if (hasChange === false) {
core.info('File already up to date')
return
}
core.info(`Creating commit for file ${ file.dest }`)
await git.commit(file.dest, file.source)
modified.push({
dest: file.dest,
source: file.source
})
}
})
})
if (DRY_RUN) {
core.warning('Dry run, no changes will be pushed')
core.info('Git Status')
core.info(await git.status())
return
}
const hasChange = await git.hasChange()
if (hasChange === false && COMMIT_EACH_FILE === false) {
core.info('File(s) already up to date')
return
}
if (hasChange === true) {
core.info(`Creating commit for remaining files`)
await git.commit()
modified.push({
dest: git.localPath
})
}
if (modified.length < 1) {
core.info('Nothing to push')
return
}
core.info(`Pushing changes to remote`)
await git.push()
let changedFiles = ''
let list = ``
if (COMMIT_EACH_FILE === true) {
modified.forEach((file) => {
list += `<li><code>${ file.dest }</code> with <code>${ file.source }</code></li>`
})
changedFiles = dedent(`
<details>
<summary>Synced files</summary>
<ul>
${ list }
</ul>
</details>
`)
}
core.info(`Creating new PR`)
const { data } = await client.pulls.create({
owner: item.repo.user,
repo: item.repo.name,
title: `${ COMMIT_PREFIX } Resynced file(s) with ${ GITHUB_REPOSITORY }`,
body: dedent(`
Resynced file(s) with [${ GITHUB_REPOSITORY }](https://github.com/${ GITHUB_REPOSITORY }).
${ changedFiles }
---
This PR was created automatically by the [action-github-file-sync](https://github.com/BetaHuhn/action-github-file-sync) workflow run [#${ process.env.GITHUB_RUN_NUMBER || 0 }](https://github.com/${ GITHUB_REPOSITORY }/actions/runs/${ process.env.GITHUB_RUN_NUMBER || 0 })
`),
head: prBranch,
base: currentBranch
})
core.info(`Pull Request Created: #${ data.number }`)
core.info(`${ data.html_url }`)
core.setOutput('pull_request_number', data.number)
core.setOutput('pull_request_url', data.html_url)
if (PR_LABELS !== undefined && PR_LABELS.length > 0) {
core.info(`Adding label(s) "${ PR_LABELS.join(', ') }" to PR`)
await client.issues.addLabels({
owner: item.repo.user,
repo: item.repo.name,
issue_number: data.number,
labels: PR_LABELS
})
}
if (ASSIGNEES !== undefined && ASSIGNEES.length > 0) {
core.info(`Adding assignee(s) "${ ASSIGNEES.join(', ') }" to PR`)
await client.issues.addAssignees({
owner: item.repo.user,
repo: item.repo.name,
issue_number: data.number,
assignees: ASSIGNEES
})
}
core.info(' ')
} catch (err) {
core.error(err.message)
core.error(err)
}
})
core.info('DONE')
}
run()
.then(() => {})
.catch((err) => {
console.error('ERROR', err)
core.setFailed(err.message)
})