diff --git a/.github/workflows/dependabot-changeset-maker.yml b/.github/workflows/dependabot-changeset-maker.yml new file mode 100644 index 0000000000..1387892489 --- /dev/null +++ b/.github/workflows/dependabot-changeset-maker.yml @@ -0,0 +1,72 @@ +name: 'Dependabot changeset maker' +on: + - pull_request_target + +jobs: + generate-changeset: + runs-on: ubuntu-latest + if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 2 + ref: ${{ github.head_ref }} + - name: Configure Git + run: | + git config --global user.email noreply@backstage.io + git config --global user.name 'Github changeset workflow' + - name: Generate changeset + uses: actions/github-script@v5 + with: + script: | + const { promises: fs } = require('fs'); + + // Parses package.json files and returns the package names + async function getPackagesNames(files) { + const names = []; + for (const file of files) { + const data = JSON.parse(await fs.readFile(file, 'utf8')); + names.push(data.name); + } + return names; + } + + async function createChangeset(fileName, commitMessage, packages) { + const pkgs = packages.map(pkg => `'${pkg}': patch`).join('\n'); + const message = commitMessage.replace(/(b|B)ump ([a-z-]+)/, 'Bump `$2`'); + const body = `---\n${pkgs}\n---\n\n${message}`; + await fs.writeFile(fileName, body); + } + + const branch = await exec.getExecOutput('git branch --show-current'); + if (!branch.stdout.startsWith('dependabot/')) { + console.log('Not a dependabot branch, skipping'); + return; + } + + const diffOutput = await exec.getExecOutput('git diff --name-only HEAD~1'); + const diffFiles = diffOutput.stdout.split('\n'); + + if (diffFiles.find(f => f.startsWith('.changeset'))) { + console.log('Changeset already exists, skipping'); + return; + } + + const files = diffFiles + .filter(file => file !== 'package.json') // skip root package.json + .filter(file => file.includes('package.json')); + + if (!files.length) { + console.log('No package.json changes, skipping'); + return; + } + + const packageNames = await getPackagesNames(files); + const { stdout: shortHash } = await exec.getExecOutput('git rev-parse --short HEAD'); + const fileName = `.changeset/dependabot-${shortHash.trim()}.md`; + const { stdout: commitMessage } = await exec.getExecOutput('git show --pretty=format:%s -s HEAD'); + await createChangeset(fileName, commitMessage, packageNames); + await exec.exec('git', ['add', fileName]); + await exec.exec('git commit -C HEAD --amend --no-edit'); + await exec.exec('git push --force');