Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to combine version & publish commands together for protected branches #936

Open
ghost opened this issue Sep 4, 2022 · 9 comments

Comments

@ghost
Copy link

ghost commented Sep 4, 2022

Problem

Hello there
In monorepos with main branch protected with pull request necessity, I think it is better to only add changesets to the pull request (summary & bump types can be reviewed by contributors also) & finally by merging to the main branch, changesets github action would "version & publish" to the registry itself.
Right now, as I inspected the whole doc and API, after merging to the main branch, again another PR is created by the action & by merging the subsequent PR, publishing would happen. I think the PR creation by the action in this scenario is redundant completely.

It would be great if we could config the action in a way so that "version & publish" commands are run one after another.

@jamsinclair
Copy link

jamsinclair commented Sep 7, 2022

I've seen a number of issues that I think relate to your vision, like changesets/action#77. I'll try follow up and collate them all.

The issue with having "version & publish" happening in the same step is the need for the bump commit (package versions being updated) by Changesets. That's why the default flow has the PR creation step. To support a workflow without making a commit, we'd need to add an option and logic to only track the Package versions by git tags only. Package versions in package.json files would not be updated.

Edit: I'll try to make an RFC issue for this 🤓 or perhaps this could be a stretch goal for Changesets v3

@Andarist
Copy link
Member

Andarist commented Sep 7, 2022

Yeah, the main problem here is that you need to bump versions and remove the changeset files from git - both of those usually require an additional commit to be created. If that would happen whenever you merge something to your base branch then it would become quite cumbersome to work with and more prone to race conditions as people are able to branch off your base at any point in time. However, I think that I've seen people using such custom workflows with Changesets - so it's definitely possible.

While for some projects that extra PR might be redundant - for other projects it's quite nice as "batching" multiple PRs into one is desirable. Imagine that you'd have two concurrent PRs introducing major changesets for package A. Your intention is probably to release a single major version of your package and not two.

@ghost
Copy link
Author

ghost commented Sep 10, 2022

@Andarist
I don't think race condition might happen in my use case, because "versioning & publishing" is a kind of task that is tracked by one person at a time, and it is done rarely in a month.
But the problem of additional commit is rational. I think that it would be more clear if I summarize my own workflow in my CI:

1- In my repository, direct push to the main branch is impossible. The branch is protected with pull request necessity.
2- Every time we create a PR, and push to it, some validation checks run (tests, type checking, yarn dedupe check).
3- At the end of a PR, if we want to also make a publish, we create changesets and let the bump type & summary become reviewed by other developers.
4- When review is completed, the PR developer should call version command on changeset so that package.json & CHANGELOGS are updated.
5- At this moment, after merging to the main branch is done, a telegram message is sent via a bot with info about releases (The info is not available right now!).

I changed my mind and think that the version command should be manually run by the developer, but it would be great that the bot had some config to not let PRs with changesets merge to the main branch, so that the developer doesn't forget to run the version command.

About step 5, I wanted to suggest that a release object in publishedPackages output of the action containing the summary & bump type would come in handy. I would rather take the PR if possible.

@ghost
Copy link
Author

ghost commented Sep 10, 2022

The idea of making temporary markdown files (so-called changesets) for saving bump types and summaries before versioning is also great, and in my use case makes commenting and reviewing easier.
But in my opinion, these md files are temporary and I don't like them to be present in my commit history. (Especially when they have random:) names)

That's why I want the config mentioned above for the bot to avoid PRs with changesets to be merged to the main branch.

@Andarist
Copy link
Member

I changed my mind and think that the version command should be manually run by the developer, but it would be great that the bot had some config to not let PRs with changesets merge to the main branch, so that the developer doesn't forget to run the version command.

This probably would be doable. However, I also wonder - could we automate running changeset version as some kind of pre-merge hook? Does GitHub support executing git hooks when landing PRs using their UI/API?

About step 5, I wanted to suggest that a release object in publishedPackages output of the action containing the summary & bump type would come in handy. I would rather take the PR if possible.

I don't think that including the summary would be OK here - there are certainly character limits when it comes to action outputs and this would risk exceeding those limits. The bump type probably could be added though.

The idea of making temporary markdown files (so-called changesets) for saving bump types and summaries before versioning is also great, and in my use case makes commenting and reviewing easier.

Yeah, this is IMHO one of the main appeals of Changesets.

@danawoodman
Copy link

My vote would simply be a flag in the changeset config that auto merges the PR (say automerge: true). This way you still have the PR with the needed changes and removal of changeset file without the developer having to manually click approve.

@jamsinclair
Copy link

you need to bump versions and remove the changeset files from git - both of those usually require an additional commit to be created

Thinking a little more abstract, do the changesets need to be cleaned up?

We could use git tags and commit history to determine newer changesets since the last release. This would also remove the need for any commits. Devs could periodically clean up old changeset files for hygiene, but not strictly necessary 🤔

@danawoodman
Copy link

danawoodman commented Sep 21, 2022

Whew, took far too long to figure this out, but I have a solution for those who want to auto-merge their Changset "Version Packages" PRs like our team does:

.github/workflows/auto-merge.yml:

name: Auto Merge

on:
  workflow_run:
    workflows: ["Release"] # the name of your release action
    types:
      - completed

jobs:
  release:
    # prevents this action from running on forks
    if: github.repository == 'your-org/your-repo'
    name: Release
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - name: "Merge pull request"
        uses: "actions/github-script@v6"
        with:
          script: |
            const owner = "your-org";
            const repo = "your-repo";
            const head = "changeset-release/main";
            await new Promise(r => setTimeout(r, 2000));
            const { data } = await github.rest.pulls.list({ owner, repo, head, per_page: 1 });
            if (data.length) {
              const pull_number = data[0].number;
              await github.rest.pulls.merge({ owner, repo, pull_number, merge_method: "squash"});
            }

This will immediately merge your changset PR so you can do one-push publishing of packages.

It's a bit of a hack, but until this is natively supported it should help.

@danawoodman
Copy link

Ok, I've finally managed to get this working. It's a bit hacky but seems reliable:

name: Release

on:
  push:
    branches: main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    # prevents this action from running on forks
    if: github.repository == 'your-org/your-repo'
    name: Release
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3
        with:
          # This makes Actions fetch all Git history so that Changesets can generate
          # changelogs with the correct commits
          fetch-depth: 0
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 17.x
          cache: "npm"
      - name: Install dependencies
        run: npm install --frozen-lockfile
      - name: Build
        run: npm run build
      - name: Create release pull request
        id: changesets
        uses: changesets/action@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - name: Merge pull request
        if: steps.changesets.outputs.pullRequestNumber > 0
        uses: actions/github-script@v6
        with:
          script: |
            const owner = "your-org";
            const repo = "your-repo";
            const head = "changeset-release/main";
            const pull_number = "${{ steps.changesets.outputs.pullRequestNumber }}"
            await github.rest.pulls.merge({ owner, repo, pull_number, merge_method: "squash"});
      - name: Publish to npm
        if: steps.changesets.outputs.pullRequestNumber > 0
        uses: changesets/action@v1
        with:
          publish: npm run release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants