semantic-release / github

:octocat: semantic-release plugin to publish a GitHub release and comment on released Pull Requests/Issues
MIT License
401 stars 125 forks source link

Protected branch with PR requirement prevents release #175

Closed Ninerian closed 5 years ago

Ninerian commented 5 years ago

Hello we integrated semantic release in our tool chain, but as we tried to release to master the first time, the branch protection of master prevented the release.

The error message from travis:

[9:32:50 AM] [semantic-release] › ✖  An error occurred while running semantic-release: { Error: Command failed: git push --tags https://[secure]@github.com/**/service.git HEAD:master
remote: error: GH006: Protected branch update failed for refs/heads/master.        
remote: error: At least 1 approving review is required by reviewers with write access.        
To https://github.com/**/service.git
 ! [remote rejected] HEAD -> master (protected branch hook declined)
error: failed to push some refs to 'https://[secure]@github.com/**/service.git'

How could I keep the PR rule and enable semantic release?

gr2m commented 5 years ago

Hmm that’s odd, I did not run into it myself. Does the configured GITHUB_TOKEN have write access to the repository? Do you have any custom configuration for semantic-release in your setup?

diegopamio commented 5 years ago

We are facing exactly the same issue.

cgadam commented 5 years ago

@gr2m even though you might have write access for protected branches you need to pass all the required checks (like having a PR and having, 2 approvers, etc) in order to be able to merge to master unless you are admin. We don't want our bot to have such privilege so if instead of committing directly to the repo it would be nice if we could create a PR. That should fix this situation.

gr2m commented 5 years ago

semantic-release is not merging or pushing anything by default, it just creates a git tag. I don’t think that is prohibited by the branch protection.

I think what might be possible is that you have configured something which requires the creation of additional commits, hence my question about custom configuration

cgadam commented 5 years ago

@gr2m you are right. The one trying to commit is actually the npm plugin that changes the context the package.json with the new version. There is also another plugin that changes the context of the CHANGELOG.md file. It then needs to push that to the release branch (master in this case)

gr2m commented 5 years ago

I’m not sure if these features are implemented in this plugin or somewhere else? I’m not sure how where the feature would need to be implemented, but if you want to give it a go I can help review it

cgadam commented 5 years ago

@Ninerian, the situation we have which I think it's similar to yours is this one:

You will still get the issue you described before.

[9:32:50 AM] [semantic-release] › ✖  An error occurred while running semantic-release: { Error: Command failed: git push --tags https://[secure]@github.com/**/service.git HEAD:master
remote: error: GH006: Protected branch update failed for refs/heads/master.        
remote: error: At least 1 approving review is required by reviewers with write access.        
To https://github.com/**/service.git
 ! [remote rejected] HEAD -> master (protected branch hook declined)
error: failed to push some refs to 'https://[secure]@github.com/**/service.git'

In the perfect world, we would be able to tell Github, please bypass this type of checking for specific non-admin users (like a bot) but that's something Github doesn't support so far. I have confirmed it with support:

image

The way we workaround this was by assigning the bot as Owner. By doing this it do has the power to bypass the protected branch rules (because it's considered an admin).

The good thing is that the GITHUB_TOKEN we generated for doing this kind of commit doesn't have any crazy permission like deleting repo or such so we should be OK.

image

Hope this is useful to you too and helps u with semantic-release integration on your protected branch.

Ninerian commented 5 years ago

After some research I have to admit that I had the wrong package installed. I used semantic-release/git. after changing to this plugin, the release works flawless.

good-idea commented 4 years ago

In case others come here with the same issue - I was having this problem, but fixed it by un-checking "Include administrators" in the branch protection rule.

hashim-sohail commented 4 years ago

After some research I have to admit that I had the wrong package installed. I used semantic-release/git. after changing to this plugin, the release works flawless.

How were you able to fix this issue?

goloroden commented 4 years ago

@Ninerian Great that you figured out how to solve this 🎉

Can you maybe shed some light on how to combine the @semantic-release/git plugin with branch protection, and on how you solved it?

hashim-sohail commented 4 years ago

@Ninerian Great that you figured out how to solve this 🎉

Can you maybe shed some light on how to combine the @semantic-release/git plugin with branch protection, and on how you solved it?

I was also able to resolve the protection issue using GIT_CREDENTIALS as my environment variable.

Environment Variables

But instead of using my password i used a Personal Access Token of an admin account with push access to the repos

goloroden commented 4 years ago

Hey @hashim-sohail 👋

Thanks for the quick reply!

How do you protect these credentials against malicious PRs who read your environment variables and send them somewhere?

Oh, and have you enabled branch protection? If so, did you setup the token with administrative privileges?

goloroden commented 4 years ago

PS: I'm asking since https://github.com/semantic-release/semantic-release/blob/f645547f2f30eb59179f1d22da13612ba5090f38/docs/recipes/github-actions.md#pushing-packagejson-changes-to-a-master-branch warns not to use personal access tokens. I'm a little bit puzzled here.

On the one hand, the docs advise you to use a personal access token, on the other hand they tell you not to do as it imposes a security risk...

hashim-sohail commented 4 years ago

Hey @hashim-sohail 👋

Thanks for the quick reply! How do you protect these credentials against malicious PRs who read your environment variables and send them somewhere?

We have a different workflow for protected branches, which run only after the PR is merged after review into these branches. The secret is only exposed in these workflows.

Oh, and have you enabled branch protection? If so, did you setup the token with administrative privileges?

Yes, branch protection is active. The token is generated from an admin account. The admin accounts are privileged to push directly to our protected branches.

hashim-sohail commented 4 years ago

PS: I'm asking since https://github.com/semantic-release/semantic-release/blob/f645547f2f30eb59179f1d22da13612ba5090f38/docs/recipes/github-actions.md#pushing-packagejson-changes-to-a-master-branch warns not to use personal access tokens. I'm a little bit puzzled here.

On the one hand, the docs advise you to use a personal access token, on the other hand they tell you not to do as it imposes a security risk...

I went through that link too. But there is no proper workaround right now to implement this. So had to do with a custom workaround, playing with the secrets

goloroden commented 4 years ago

Yes, branch protection is active. The token is generated from an admin account. The admin accounts are privileged to push directly to our protected branches.

Great, thanks 👍

I went through that link too. But there is no proper workaround right now to implement this. So had to do with a custom workaround, playing with the secrets

I did some additional research, too, and GitHub Actions mention that secrets are never given to actions that run as result of a PR of a fork. So, everything should be safe 😊

Thanks for your help 👍

imduchy commented 4 years ago

@cgadam Could you please clarify for me; by adding a bot as an Owner you mean adding him into a Project Team? And are you talking about the @semantic-release-bot ?

cgadam commented 4 years ago

@Duchynko the bot is just an internal github user that authors the commit for semantic-release related modifications.

0xc0d3r commented 4 years ago

I'm still getting this error. This is my release config in package.json.

{

"release": {
    "branches": [
      "staging"
    ],
    "plugins": [
      "@semantic-release/commit-analyzer",
      "@semantic-release/release-notes-generator",
      [
        "@semantic-release/changelog",
        {
          "changelogFile": "docs/CHANGELOG.md"
        }
      ],
      "@semantic-release/github",
      "@semantic-release/npm",
      [
        "@semantic-release/git",
        {
          "assets": [
            "dist/**/*.{js,css}",
            "package.json"
          ],
          "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
        }
      ]
    ]
  }

}

We have a bot user and it is responsible to build and publish. I've assigned the owner role to our bot user. Still getting the below error.

[6:33:47 AM] [semantic-release] › ℹ  Running semantic-release version 17.0.4
2020-03-23T06:33:47.262Z semantic-release:config load config from: /home/runner/work/logger/logger/package.json
2020-03-23T06:33:47.266Z semantic-release:config options values: {
  branches: [ 'staging' ],
  repositoryUrl: 'https://github.com/wingspanHQ/logger',
  tagFormat: 'v${version}',
  plugins: [
    '@semantic-release/commit-analyzer',
    '@semantic-release/release-notes-generator',
    [ '@semantic-release/changelog', [Object] ],
    '@semantic-release/github',
    '@semantic-release/npm',
    [ '@semantic-release/git', [Object] ]
  ],
  _: [],
  debug: true,
  '$0': 'node_modules/.bin/semantic-release'
}
2020-03-23T06:33:47.472Z semantic-release:plugins options for @semantic-release/changelog/verifyConditions: { changelogFile: 'docs/CHANGELOG.md' }
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/changelog"
2020-03-23T06:33:47.473Z semantic-release:plugins options for @semantic-release/github/verifyConditions: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/github"
2020-03-23T06:33:47.473Z semantic-release:plugins options for @semantic-release/npm/verifyConditions: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/npm"
2020-03-23T06:33:47.474Z semantic-release:plugins options for @semantic-release/git/verifyConditions: {
     assets: [ 'dist/**/*.{js,css}', 'package.json' ],
  message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "verifyConditions" from "@semantic-release/git"
}
2020-03-23T06:33:47.474Z semantic-release:plugins options for @semantic-release/commit-analyzer/analyzeCommits: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "analyzeCommits" from "@semantic-release/commit-analyzer"
2020-03-23T06:33:47.475Z semantic-release:plugins options for @semantic-release/release-notes-generator/generateNotes: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "generateNotes" from "@semantic-release/release-notes-generator"
2020-03-23T06:33:47.475Z semantic-release:plugins options for @semantic-release/changelog/prepare: { changelogFile: 'docs/CHANGELOG.md' }
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/changelog"
2020-03-23T06:33:47.475Z semantic-release:plugins options for @semantic-release/npm/prepare: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/npm"
2020-03-23T06:33:47.476Z semantic-release:plugins options for @semantic-release/git/prepare: {
  assets: [ 'dist/**/*.{js,css}', 'package.json' ],
  message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}'
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "prepare" from "@semantic-release/git"
}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/github"
2020-03-23T06:33:47.476Z semantic-release:plugins options for @semantic-release/github/publish: {}
2020-03-23T06:33:47.476Z semantic-release:plugins options for @semantic-release/npm/publish: {}
2020-03-23T06:33:47.476Z semantic-release:plugins options for @semantic-release/github/addChannel: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "publish" from "@semantic-release/npm"
2020-03-23T06:33:47.477Z semantic-release:plugins options for @semantic-release/npm/addChannel: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "addChannel" from "@semantic-release/github"
2020-03-23T06:33:47.477Z semantic-release:plugins options for @semantic-release/github/success: {}
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "addChannel" from "@semantic-release/npm"
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "success" from "@semantic-release/github"
[6:33:47 AM] [semantic-release] › ✔  Loaded plugin "fail" from "@semantic-release/github"
2020-03-23T06:33:49.020Z semantic-release:get-tags found tags for branch staging: [ { gitTag: 'v1.0.0', version: '1.0.0', channels: [ null ] }, { gitTag: 'v1.1.0', version: '1.1.0', channels: [ null ] }, { gitTag: 'v1.1.1', version: '1.1.1', channels: [ null ] }, { gitTag: 'v1.1.2', version: '1.1.2', channels: [ null ] }, { gitTag: 'v1.1.3', version: '1.1.3', channels: [ null ] }, { gitTag: 'v1.1.4', version: '1.1.4', channels: [ null ] }, { gitTag: 'v1.1.5', version: '1.1.5', channels: [ null ] }, { gitTag: 'v1.2.0', version: '1.2.0', channels: [ null ] }, { gitTag: 'v1.3.0', version: '1.3.0', channels: [ null ] }, { gitTag: 'v1.4.0', version: '1.4.0', channels: [ null ] } ]
[6:33:49 AM] [semantic-release] › ✔  Run automated release from branch staging on repository https://github.com/wingspanHQ/logger
[6:33:49 AM] [semantic-release] › ✔  Allowed to push to the Git repository
[6:33:49 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/changelog"
[6:33:49 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/changelog"
[6:33:49 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/github"
[6:33:49 AM] [semantic-release] [@semantic-release/github] › ℹ  Verify GitHub authentication
[6:33:49 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/github"
[6:33:49 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/npm"
[6:33:49 AM] [semantic-release] [@semantic-release/npm] › ℹ  Verify authentication for registry https://npm.pkg.github.com/
[6:33:49 AM] [semantic-release] [@semantic-release/npm] › ℹ  Reading npm config from /home/runner/work/logger/logger/.npmrc
[6:33:49 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/npm"
[6:33:49 AM] [semantic-release] › ℹ  Start step "verifyConditions" of plugin "@semantic-release/git"
[6:33:49 AM] [semantic-release] › ✔  Completed step "verifyConditions" of plugin "@semantic-release/git"
[6:33:49 AM] [semantic-release] › ℹ  Found git tag v1.4.0 associated with version 1.4.0 on branch staging
2020-03-23T06:33:49.498Z semantic-release:get-commits Use from: ddbf4ec9f13a13950fbf62b5651933df626c3aba

[6:33:49 AM] [semantic-release] › ℹ  Found 6 commits since last release
2020-03-23T06:33:49.511Z semantic-release:get-commits Parsed commits: [ { commit: { long: '8e7f8d8e7ec4260eeee43a6ec059d53bd59e5167', short: '8e7f8d8' }, tree: { long: 'dea2d26366d4b4740c3426d1fa596d79540d6d19', short: 'dea2d26' }, author: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T06:32:41.000Z }, committer: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T06:32:41.000Z }, subject: 'chore: add github_token', body: '', hash: '8e7f8d8e7ec4260eeee43a6ec059d53bd59e5167', committerDate: 2020-03-23T06:32:41.000Z, message: 'chore: add github_token', gitTags: '(HEAD -> staging, origin/staging)' }, { commit: { long: 'b30fa59d4aa3b4eba422eacf482571a5aef7fde7', short: 'b30fa59' }, tree: { long: '77cca5a8a2ed033f5bf717606185961a4a4e9929', short: '77cca5a' }, author: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T06:01:53.000Z }, committer: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T06:01:53.000Z }, subject: 'chore: remove git setup in workflow', body: '', hash: 'b30fa59d4aa3b4eba422eacf482571a5aef7fde7', committerDate: 2020-03-23T06:01:53.000Z, message: 'chore: remove git setup in workflow', gitTags: '' }, { commit: { long: '8126ba1448d8f0301430c56d70a21312becb5c77', short: '8126ba1' }, tree: { long: 'b2ebb5d511ec4fba1dc22839614d1f2ee1a9aa99', short: 'b2ebb5d' }, author: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:51:21.000Z }, committer: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:51:21.000Z }, subject: 'chore: add git envs', body: '', hash: '8126ba1448d8f0301430c56d70a21312becb5c77', committerDate: 2020-03-23T05:51:21.000Z, message: 'chore: add git envs', gitTags: '' }, { commit: { long: 'faf6aca9da1ced7c59002d393a1b3efc76faf597', short: 'faf6aca' }, tree: { long: 'e49756af42cbc9c01bc4a18dfe1cdd87240620e4', short: 'e49756a' }, author: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:41:16.000Z }, committer: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:41:16.000Z }, subject: 'chore: remove git_creds env var', body: '', hash: 'faf6aca9da1ced7c59002d393a1b3efc76faf597', committerDate: 2020-03-23T05:41:16.000Z, message: 'chore: remove git_creds env var', gitTags: '' }, { commit: { long: '9dc93f7abd452839091af76daba0d8a89e213196', short: '9dc93f7' }, tree: { long: '13488402daa38d1bedc706be55e8646f8dbebc50', short: '1348840' }, author: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:35:37.000Z }, committer: { name: 'Anesh Parvatha', email: 'anesh.parvatha@gmail.com', date: 2020-03-23T05:35:37.000Z }, subject: 'chore(env): add git_creds env variable to secrets', body: '', hash: '9dc93f7abd452839091af76daba0d8a89e213196', committerDate: 2020-03-23T05:35:37.000Z, message: 'chore(env): add git_creds env variable to secrets', gitTags: '' }, { commit: { long: 'd1104e9a706de5c019cda3ffc48909f7e1406496', short: 'd1104e9' }, tree: { long: '746d43d413b67f0d8b80e724095d5168bc256454', short: '746d43d' }, author: { name: 'Gregory Maglio', email: 'gregm@wingspan.app', date: 2020-03-23T03:50:21.000Z }, committer: { name: 'Gregory Maglio', email: 'gregm@wingspan.app', date: 2020-03-23T03:50:21.000Z }, subject: 'fix: kick!', body: '', hash: 'd1104e9a706de5c019cda3ffc48909f7e1406496', committerDate: 2020-03-23T03:50:21.000Z, message: 'fix: kick!', gitTags: '' } ],message: 'chore(env): add git_creds env variable to secrets', gitTags: '' }, { commit: { long: 'd1104e9a706de5c019cda3ffc48909f7e1406496', short: 'd1104e9' }, tree: { long: '746d43d413b67f0d8b80e724095d5168bc256454', short: '746d43d' }, author: { name: 'Gregory Maglio', email: 'gregm@wingspan.app', date: 2020-03-23T03:50:21.000Z }, committer: { name: 'Gregory Maglio', email: 'gregm@wingspan.app', date: 2020-03-23T03:50:21.000Z }, subject: 'fix: kick!', body: '', hash: 'd1104e9a706de5c019cda3ffc48909f7e1406496', committerDate: 2020-03-23T03:50:21.000Z, message: 'fix: kick!', gitTags: '' } ]
[6:33:49 AM] [semantic-release] › ℹ  Start step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: chore: add github_token
2020-03-23T06:33:49.519Z semantic-release:commit-analyzer Analyzing with default rules
2020-03-23T06:33:49.520Z semantic-release:commit-analyzer Analyzing with default rules
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: chore: remove git setup in workflow
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
2020-03-23T06:33:49.521Z semantic-release:commit-analyzer Analyzing with default rules
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: chore: add git envs
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
2020-03-23T06:33:49.521Z semantic-release:commit-analyzer Analyzing with default rules
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: chore: remove git_creds env var
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
2020-03-23T06:33:49.522Z semantic-release:commit-analyzer Analyzing with default rules
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: chore(env): add git_creds env variable to secrets
2020-03-23T06:33:49.522Z semantic-release:commit-analyzer Analyzing with default rules
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The commit should not trigger a release
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analyzing commit: fix: kick!
2020-03-23T06:33:49.522Z semantic-release:commit-analyzer The rule { type: 'fix', release: 'patch' } match commit with release type 'patch'
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  The release type for the commit is patch
[6:33:49 AM] [semantic-release] [@semantic-release/commit-analyzer] › ℹ  Analysis of 6 commits complete: patch release
[6:33:49 AM] [semantic-release] › ✔  Completed step "analyzeCommits" of plugin "@semantic-release/commit-analyzer"
[6:33:49 AM] [semantic-release] › ℹ  The next release version is 1.4.1
[6:33:49 AM] [semantic-release] › ℹ  Start step "generateNotes" of plugin "@semantic-release/release-notes-generator"
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator version: '1.4.1'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator host: undefined
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator owner: 'wingspanHQ'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator repository: 'logger'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator previousTag: 'v1.4.0'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator currentTag: 'v1.4.1'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator host: 'https://github.com'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator linkReferences: undefined
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator issue: 'issues'
2020-03-23T06:33:49.535Z semantic-release:release-notes-generator commit: 'commit'
[6:33:49 AM] [semantic-release] › ✔  Completed step "generateNotes" of plugin "@semantic-release/release-notes-generator"
[6:33:49 AM] [semantic-release] › ℹ  Start step "prepare" of plugin "@semantic-release/changelog"
[6:33:49 AM] [semantic-release] [@semantic-release/changelog] › ℹ  Create /home/runner/work/logger/logger/docs/CHANGELOG.md
[6:33:49 AM] [semantic-release] › ✔  Completed step "prepare" of plugin "@semantic-release/changelog"
[6:33:49 AM] [semantic-release] › ℹ  Start step "prepare" of plugin "@semantic-release/npm"
[6:33:49 AM] [semantic-release] [@semantic-release/npm] › ℹ  Write version 1.4.1 to package.json in /home/runner/work/logger/logger
v1.4.1
[6:33:49 AM] [semantic-release] › ✔  Completed step "prepare" of plugin "@semantic-release/npm"
[6:33:49 AM] [semantic-release] › ℹ  Start step "prepare" of plugin "@semantic-release/git"
[6:33:50 AM] [semantic-release] [@semantic-release/git] › ℹ  Found 1 file(s) to commit
2020-03-23T06:33:50.029Z semantic-release:git add file to git index {
  command: 'git add --force --ignore-errors package.json',
  exitCode: 0,
  stdout: '',
  stderr: '',
  all: undefined,
  failed: [secure],
  timedOut: [secure],
  isCanceled: [secure],
  killed: [secure]
}
2020-03-23T06:33:50.029Z semantic-release:git commited files: [ 'package.json' ]
[6:33:56 AM] [semantic-release] › ✖  Failed step "prepare" of plugin "@semantic-release/git"
[6:33:56 AM] [semantic-release] › ✖  An error occurred while running semantic-release: Error: Command failed with exit code 1: git push --tags https://github.com/wingspanHQ/logger HEAD:staging
remote: error: GH006: Protected branch update failed for refs/heads/staging.        
remote: error: At least 1 approving review is required by reviewers with write access.        
To https://github.com/wingspanHQ/logger
 ! [remote rejected] HEAD -> staging (protected branch hook declined)
error: failed to push some refs to 'https://github.com/wingspanHQ/logger'
    at makeError (/home/runner/work/logger/logger/node_modules/execa/lib/error.js:58:11)
    at handlePromise (/home/runner/work/logger/logger/node_modules/execa/index.js:114:26)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async push (/home/runner/work/logger/logger/node_modules/@semantic-release/git/lib/git.js:51:3)
    at async module.exports (/home/runner/work/logger/logger/node_modules/@semantic-release/git/lib/prepare.js:69:5)
    at async prepare (/home/runner/work/logger/logger/node_modules/@semantic-release/git/index.js:28:3)
    at async validator (/home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/normalize.js:34:24)
   at async /home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/pipeline.js:37:34
    at async /home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/pipeline.js:31:3
    at async Object.pluginsConf.<computed> [as prepare] (/home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/index.js:80:11) {
  shortMessage: 'Command failed with exit code 1: git push --tags https://github.com/wingspanHQ/logger HEAD:staging',
  command: 'git push --tags https://github.com/wingspanHQ/logger HEAD:staging',
  exitCode: 1,
  signal: undefined,
  signalDescription: undefined,
  stdout: '',
  stderr: 'remote: error: GH006: Protected branch update failed for refs/heads/staging.        \n' +
    'remote: error: At least 1 approving review is required by reviewers with write access.        \n' +
    'To https://github.com/wingspanHQ/logger\n' +
    ' ! [remote rejected] HEAD -> staging (protected branch hook declined)\n' +
    "error: failed to push some refs to 'https://github.com/wingspanHQ/logger'",
  failed: true,
  timedOut: [secure],
  isCanceled: [secure],
  killed: [secure],
  pluginName: '@semantic-release/git'
}
Error: Command failed with exit code 1: git push --tags https://github.com/wingspanHQ/logger HEAD:staging
remote: error: GH006: Protected branch update failed for refs/heads/staging.        
remote: error: At least 1 approving review is required by reviewers with write access.        
To https://github.com/wingspanHQ/logger
 ! [remote rejected] HEAD -> staging (protected branch hook declined)
error: failed to push some refs to 'https://github.com/wingspanHQ/logger'
    at makeError (/home/runner/work/logger/logger/node_modules/execa/lib/error.js:58:11)
    at handlePromise (/home/runner/work/logger/logger/node_modules/execa/index.js:114:26)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async push (/home/runner/work/logger/logger/node_modules/@semantic-release/git/lib/git.js:51:3)
    at async module.exports (/home/runner/work/logger/logger/node_modules/@semantic-release/git/lib/prepare.js:69:5)
    at async prepare (/home/runner/work/logger/logger/node_modules/@semantic-release/git/index.js:28:3)
    at async validator (/home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/normalize.js:34:24)
    at async /home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/pipeline.js:37:34
    at async /home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/pipeline.js:31:3
    at async Object.pluginsConf.<computed> [as prepare] (/home/runner/work/logger/logger/node_modules/semantic-release/lib/plugins/index.js:80:11) {
  shortMessage: 'Command failed with exit code 1: git push --tags https://github.com/wingspanHQ/logger HEAD:staging',
  command: 'git push --tags https://github.com/wingspanHQ/logger HEAD:staging',
  exitCode: 1,
  signal: undefined,
  signalDescription: undefined,
  stdout: '',
  stderr: 'remote: error: GH006: Protected branch update failed for refs/heads/staging.        \n' +
    'remote: error: At least 1 approving review is required by reviewers with write access.        \n' +
    'To https://github.com/wingspanHQ/logger\n' +
    ' ! [remote rejected] HEAD -> staging (protected branch hook declined)\n' +
    "error: failed to push some refs to 'https://github.com/wingspanHQ/logger'",
  failed: true,
  timedOut: [secure],
  isCanceled: [secure],
    killed: [secure],
  pluginName: '@semantic-release/git'
}error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
##[error]Process completed with exit code 1.

@pvdlg @cgadam Am I missing something?

0xc0d3r commented 4 years ago
export GH_TOKEN=<gh_token_generated_by_semantic-release-cli>
export NPM_TOKEN=<github_personal_access_token> // We are using GPR
export GIT_CREDENTIALS=<url_encoded_username>:<url_encoded_password>
export GIT_AUTHOR_NAME=<author_username>
export GIT_AUTHOR_EMAIL=<author_email>
export GIT_COMMITTER_NAME=<commiter_username>
export GIT_COMMITTER_EMAIL=<committer_email>

CI=true yarn semantic-release --debug

I ran this script locally on my machine and I am able to release the next version and bump the package version automatically using @semantic-release/git plugin.

Why the same configuration is not working on CI? Check my config release config and logs here

release.yml

name: Release
on:
  push:
    branches:
      - staging
      - next
      - beta
      - '*.x' # maintenance releases

jobs:
  release:
    name: release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Setup node
        uses: actions/setup-node@v1
        with:
          always-auth: true
          node-version: 12
      - name: Install npm packages
        run: yarn install
      - name: Build
        run: yarn build
      - name: Semantic Release
        run: yarn semantic-release --debug
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.NPM_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}
          GIT_AUTHOR_NAME: ${{ secrets. GIT_AUTHOR_NAME }}
          GIT_AUTHOR_EMAIL: ${{ secrets. GIT_AUTHOR_EMAIL }}
          GIT_COMMITTER_NAME: ${{ secrets. GIT_COMMITTER_NAME }}
          GIT_COMMITTER_EMAIL: ${{ secrets. GIT_COMMITTER_EMAIL }}

One more thing I observed is that in my tokens page, the generated token has never used and after I ran the above script locally, it has changed to Last used within last week.

@gr2m @pvdlg Can you support me with this?

carrmelo commented 4 years ago

The way we workaround this was by assigning the bot as Owner. By doing this it do has the power to bypass the protected branch rules (because it's considered an admin). The good thing is that the GITHUB_TOKEN we generated for doing this kind of commit doesn't have any crazy permission like deleting repo or such so we should be OK.

hey @cgadam, how did you assign the bot as an owner? I have created a token but then the release is done under my name, that is not ideal since our team would like to keep the action done in the github-action[bot] name.

I have tried the plugin and configuration as minimal as the example in the @semantic-release/git but keep on getting the error because of the 2 approval needed... (inlcude administrators options in unticked)

thanks in advance for any help!

travi commented 4 years ago

a "bot" user in this case is simply another github user account that your team uses only for automated tasks like this one. you can then create a token for that account instead of your own. that user account then just needs to have a permission level that is allowed to push to the protected branch.

0xc0d3r commented 4 years ago

@travi We did the same as you said but still we are getting the error.

travi commented 4 years ago

that user account then just needs to have a permission level that is allowed to push

@0xc0d3r the above detail is key. do you allow admins to push, even though the branch is restricted. the "include administrators" option would need to be unchecked and the bot user would need to have admin or higher permissions.

0xc0d3r commented 4 years ago

@travi We made our bot user as Owner.

travi commented 4 years ago

have you contacted github support about this? it sounds to me like more of a github permissions issue than related specifically to semantic-release.

personally, i do not protect pushes to master, so i have not had to solve this problem directly.

carrmelo commented 4 years ago

Thanks for the answer @travi ! I get that now :)

So can you confirm that this is the workaround for protected branches? github-actions[bot] can never publish as an administrator and bypass the 2 approvals?

travi commented 4 years ago

i don't personally use github actions, so i can't fully confirm anything. however, i know that the default token available to the action is limited on permissions and providing a different token is the way around that. with the appropriate permissions granted to the personal access token, interactions that require higher permissions should be enabled.

JoepKockelkorn commented 3 years ago

This might be related: https://github.com/semantic-release/git/issues/196 The git checkout action persists the automatic token, which you do not want in the case of running semantic-release.

janhesters commented 3 years ago

I managed to solve this by:

  1. Follow these docs to create a personal access token. You need to check the "repo" box when creating it.
  2. Add the token as a secret for the repo under the name GH_TOKEN.

This is my release.yml. (Notice how it has the auto generated GITHUB_TOKEN and the manually cerated GH_TOKEN.)

name: Release
on:
  push:
    branches:
      - main

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Build
        run: yarn build
      - name: Release
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

This is my .releaserc.

{
  "branches": [
    "main"
  ],
  "plugins": [
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    [
      "@semantic-release/git",
      {
        "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ],
    "@semantic-release/github"
  ]
}

Hope this helps others to resolve the issue.

jthegedus commented 3 years ago

Has anyone tried creating a PR for the changes created by semantic-release?

  1. Run npx semantic-release without the @semantic-release/git plugin
  2. Create new branch during the next step
  3. Git add and commit
  4. Create PR from new branch (using something like https://github.com/peter-evans/create-pull-request)
  5. Use a separate GitHub Action to auto-approve :thinking:

Sorry for digging up this thread.


Update: Turns out this is what release-please does!

nickofthyme commented 3 years ago

@janhesters that worked for me! Not sure if it was the persist-credentials: false, the token changes or both but it works great. Thanks!

goldy1992 commented 3 years ago

After some research I have to admit that I had the wrong package installed. I used semantic-release/git. after changing to this plugin, the release works flawless.

After following the advice from @janhesters I managed to get this to work however I would like to highlight this comment as I believe it to be quite misleading without the complete context (which wasn't given in the first comment of the issue)....

You CANNOT change from @semantic-release/git to @semantic-release/github and vice versa and the same results as they do completely different things.

mrlubos commented 3 years ago

I managed to solve this by:

  1. Follow these docs to create a personal access token. You need to check the "repo" box when creating it.
  2. Add the token as a secret for the repo under the name GH_TOKEN.

This is my release.yml. (Notice how it has the auto generated GITHUB_TOKEN and the manually cerated GH_TOKEN.)

name: Release
on:
  push:
    branches:
      - main

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Build
        run: yarn build
      - name: Release
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

This is my .releaserc.

{
  "branches": [
    "main"
  ],
  "plugins": [
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    [
      "@semantic-release/git",
      {
        "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ],
    "@semantic-release/github"
  ]
}

Hope this helps others to resolve the issue.

THANK YOU. The only thing that helped. I am not sure if it was because of the persist-credentials flag or that I passed a different secret to GH_TOKEN (i.e. GH_TOKEN: ${{ secrets.MY_CUSTOM_SECRET }}, but after changing both to your guide it works.

mynkow commented 3 years ago

I managed to solve this by:

  1. Follow these docs to create a personal access token. You need to check the "repo" box when creating it.
  2. Add the token as a secret for the repo under the name GH_TOKEN.

This is my release.yml. (Notice how it has the auto generated GITHUB_TOKEN and the manually cerated GH_TOKEN.)

name: Release
on:
  push:
    branches:
      - main

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
          persist-credentials: false
      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Build
        run: yarn build
      - name: Release
        env:
          GH_TOKEN: ${{ secrets.GH_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

This is my .releaserc.

{
  "branches": [
    "main"
  ],
  "plugins": [
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    [
      "@semantic-release/git",
      {
        "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
      }
    ],
    "@semantic-release/github"
  ]
}

Hope this helps others to resolve the issue.

THANK YOU. The only thing that helped. I am not sure if it was because of the persist-credentials flag or that I passed a different secret to GH_TOKEN (i.e. GH_TOKEN: ${{ secrets.MY_CUSTOM_SECRET }}, but after changing both to your guide it works.

For me it was the flag persist-credentials=false ;)

deepal commented 3 years ago

Regardless of any of the mentioned workarounds, it will still fail if you have "Include Administrators" checkbox checked in branch protection rules. Even though your token has all the permissions (including any admin permissions), it prevents pushing to the protected branch because the branch protection rules are applied to the administrators as well. The only way I got this to work is by unchecking *Include Administrators**, which is only a workaround. Not a solution.

If anyone finds out a solution to get this to work while having "Include Administrators" checked in branch protection rules, I would be thrilled to try out.

travi commented 3 years ago

If anyone finds out a solution to get this to work while having "Include Administrators" checked in branch protection rules, I would be thrilled to try out.

semantic-release can only work within the limitations of how github authorization works. if you have protection enabled that is enforced for admins, things are working as designed if it prevents a token with admin privileges from doing the thing that branch protection is protecting against.

which is only a workaround. Not a solution.

semantic-release can only work on behalf of a user that has appropriate permissions. it does not have special privileges beyond what github can allow to a user. it sounds like you are wanting more flexibility in the github auth model. there is nothing semantic-release can do about that. your best bet would be to reach out to github support and communicate your need that is not being met by the current model.

hellhoundsx commented 3 years ago

Just leaving here a note that if you are not using github actions(I use Jenkins job) and had this issue, it might be how you clone your project as stated in https://github.com/semantic-release/git/issues/196. persist-credentials works for github actions as it seems to remove the native credentials which forces semantic to use the token instead.

Even though I tried multiple ways of cloning the project, it seemed that semantic never used my token... but after some snooping around you can run the following command which will force the use of the token when pushing to the repo (this if you are using git type like git@github.com:XXXX.git)

git config url."https://${GH_TOKEN}@github.com/".insteadOf git@github.com:

npx semantic-release
kettanaito commented 2 years ago

For anybody using GitHub Actions, you need to set the token option of the actions/checkout action so that GitHub would authorize local Git with the necessary push permissions.

- name: Checkout
  uses: actions/checkout@v3
  with:
    fetch-depth: 0
    token: ${{ secrets.CI_GITHUB_TOKEN }}

Your CI_GITHUB_TOKEN secret should equal your GitHub Personal Access Token with the repo permissions scope. That scope would authorize pushes to protected branches, given you don't have "Include administrators" set in the protected branch's settings.

ming-rga commented 1 year ago

For those who bump into this with GH branch protection with external CI (ie. jenkins), you can also by pass the branch protection rule (ie. code approval) via the option Allow specified actors to bypass required pull requests.

In the field, specify the user of the GITHUB_TOKEN used for semantic-release.

natarajsahoo commented 1 year ago

I also faced the same issue & in my case, the problem was that I had enabled the "Do not allow bypassing the above settings" flag under branch protection rules. After disabling the above flag it worked for me.

twang817 commented 1 year ago

I finally pieced this all together as well, and it was a chore. Let me save the next guy some time:

If you are absolutely allergic to using a PAT for this, we created an org-level Github App specifically for dealing with the limitations of GITHUB_TOKEN. Follow this documentation to create a Github App. Let's call our Github App MyBot

Once you have your GIthub App, configure its permissions. We gave ours a repository-level permissions -- for the purposes of this use-case, I believe Content is what you need.

Next create a Private Key. This will download a PEM file -- don't lose it. Also take note of your App's App ID.

Now install it to your organization. We chose to install it to just the repo that I'm working with, but I see no reason you couldn't install it org-wide if you're okay with the security implications.

Now that we have that set up, we can go to our repo and set up some secrets. I added a MYBOT_APP_ID and MYBOT_PRIVATE KEY. Dump the contents of your App ID and Private Key into those secrets.

Next, we go to branch protection rules. I'm assuming if you're reading this, you're going to have Require a pull request before merging ticked, as well as Require approvals. You may have others (I didn't). Under Allow specified actors to bypass required pull requests, you can now type MyBot and add him to the list of actors that can bypass the rules. Make sure Do not allow bypassing the above settings is not checked below.

We can finally write our workflow

name: Semantic Release

on:
  push:
    branches:
      - master

jobs:
  release:
    runs-on: ubuntu-latest
    concurrency: release

    steps:
      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@v1
        with:
          app_id: ${{ secrets.MYBOT_APP_ID }}
          private_key: ${{ secrets.MYBOT_PRIVATE_KEY }}

      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          token: ${{ steps.generate_token.outputs.token }}

      - name: Semantic Release
        uses: codfish/semantic-release-action@v2
        with:
          additional_packages: |
            [
              'conventional-changelog-conventionalcommits',
              '@semantic-release/changelog',
              '@google/semantic-release-replace-plugin',
              '@semantic-release/git',
              'semantic-release-slack-bot'
            ]
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
          SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

And, for completeness, my .releaserc (I use the YAML format):

branches: master
plugins:
  - '@semantic-release/commit-analyzer'
  - '@semantic-release/release-notes-generator'
  - '@semantic-release/github'

  # generate changelog CHANGELOG.md
  - '@semantic-release/changelog'

  # update pyproject.toml with newest version
  - - '@google/semantic-release-replace-plugin'
    - replacements:
      - files: [pyproject.toml]
        from: "version = \".*\""
        to: "version = \"${nextRelease.version}\""
        results:
          - file: pyproject.toml
            hasChanged: true
            numMatches: 1
            numReplacements: 1
        countMatches: true

  # commit CHANGELOG.md and pyproject.toml
  - - '@semantic-release/git'
    - assets:
      - CHANGELOG.md
      - pyproject.toml

  # notify slack, using SLACK_TOKEN from environment
  - - 'semantic-release-slack-bot'
    - packageName: csm-terraform-modules
      notifyOnSuccess: true
      notifyOnFail: true
      slackChannel: "#my-slack-channel"
      markdownReleaseNotes: true

preset: conventionalcommits

Hope this saves the next guy about 8hrs of time. 🤦🏼

lukeduda commented 1 year ago

I finally pieced this all together as well, and it was a chore. Let me save the next guy some time:

If you are absolutely allergic to using a PAT for this, we created an org-level Github App specifically for dealing with the limitations of GITHUB_TOKEN. Follow this documentation to create a Github App. Let's call our Github App MyBot

Once you have your GIthub App, configure its permissions. We gave ours a repository-level permissions -- for the purposes of this use-case, I believe Content is what you need.

Next create a Private Key. This will download a PEM file -- don't lose it. Also take note of your App's App ID.

Now install it to your organization. We chose to install it to just the repo that I'm working with, but I see no reason you couldn't install it org-wide if you're okay with the security implications.

Now that we have that set up, we can go to our repo and set up some secrets. I added a MYBOT_APP_ID and MYBOT_PRIVATE KEY. Dump the contents of your App ID and Private Key into those secrets.

Next, we go to branch protection rules. I'm assuming if you're reading this, you're going to have Require a pull request before merging ticked, as well as Require approvals. You may have others (I didn't). Under Allow specified actors to bypass required pull requests, you can now type MyBot and add him to the list of actors that can bypass the rules. Make sure Do not allow bypassing the above settings is not checked below.

We can finally write our workflow

name: Semantic Release

on:
  push:
    branches:
      - master

jobs:
  release:
    runs-on: ubuntu-latest
    concurrency: release

    steps:
      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@v1
        with:
          app_id: ${{ secrets.MYBOT_APP_ID }}
          private_key: ${{ secrets.MYBOT_PRIVATE_KEY }}

      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          token: ${{ steps.generate_token.outputs.token }}

      - name: Semantic Release
        uses: codfish/semantic-release-action@v2
        with:
          additional_packages: |
            [
              'conventional-changelog-conventionalcommits',
              '@semantic-release/changelog',
              '@google/semantic-release-replace-plugin',
              '@semantic-release/git',
              'semantic-release-slack-bot'
            ]
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
          SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

And, for completeness, my .releaserc (I use the YAML format):

branches: master
plugins:
  - '@semantic-release/commit-analyzer'
  - '@semantic-release/release-notes-generator'
  - '@semantic-release/github'

  # generate changelog CHANGELOG.md
  - '@semantic-release/changelog'

  # update pyproject.toml with newest version
  - - '@google/semantic-release-replace-plugin'
    - replacements:
      - files: [pyproject.toml]
        from: "version = \".*\""
        to: "version = \"${nextRelease.version}\""
        results:
          - file: pyproject.toml
            hasChanged: true
            numMatches: 1
            numReplacements: 1
        countMatches: true

  # commit CHANGELOG.md and pyproject.toml
  - - '@semantic-release/git'
    - assets:
      - CHANGELOG.md
      - pyproject.toml

  # notify slack, using SLACK_TOKEN from environment
  - - 'semantic-release-slack-bot'
    - packageName: csm-terraform-modules
      notifyOnSuccess: true
      notifyOnFail: true
      slackChannel: "#my-slack-channel"
      markdownReleaseNotes: true

preset: conventionalcommits

Hope this saves the next guy about 8hrs of time. 🤦🏼

That's the best answer in this thread! Works like a charm!!! :muscle:

berkon commented 11 months ago

For anybody using GitHub Actions, you need to set the token option of the actions/checkout action so that GitHub would authorize local Git with the necessary push permissions.

This is a very important and not really obvious information! Its a pity that this is not written down somewhere in the semantic-release docs. Apart from that I additionally had to add my admin account on GitHub to the list of the actors allowed to bypass the branch protection. I don't really understand why, because in that box there is a small hint, telling that admin accounts are always allowed to bypass the pull request requirement. Thus I think it should not be necessary to add the account to that list.

dvictory commented 10 months ago

I finally pieced this all together as well, and it was a chore. Let me save the next guy some time:

If you are absolutely allergic to using a PAT for this, we created an org-level Github App specifically for dealing with the limitations of GITHUB_TOKEN. Follow this documentation to create a Github App. Let's call our Github App MyBot

Once you have your GIthub App, configure its permissions. We gave ours a repository-level permissions -- for the purposes of this use-case, I believe Content is what you need.

Next create a Private Key. This will download a PEM file -- don't lose it. Also take note of your App's App ID.

Now install it to your organization. We chose to install it to just the repo that I'm working with, but I see no reason you couldn't install it org-wide if you're okay with the security implications.

Now that we have that set up, we can go to our repo and set up some secrets. I added a MYBOT_APP_ID and MYBOT_PRIVATE KEY. Dump the contents of your App ID and Private Key into those secrets.

Next, we go to branch protection rules. I'm assuming if you're reading this, you're going to have Require a pull request before merging ticked, as well as Require approvals. You may have others (I didn't). Under Allow specified actors to bypass required pull requests, you can now type MyBot and add him to the list of actors that can bypass the rules. Make sure Do not allow bypassing the above settings is not checked below.

We can finally write our workflow

name: Semantic Release

on:
  push:
    branches:
      - master

jobs:
  release:
    runs-on: ubuntu-latest
    concurrency: release

    steps:
      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@v1
        with:
          app_id: ${{ secrets.MYBOT_APP_ID }}
          private_key: ${{ secrets.MYBOT_PRIVATE_KEY }}

      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
          token: ${{ steps.generate_token.outputs.token }}

      - name: Semantic Release
        uses: codfish/semantic-release-action@v2
        with:
          additional_packages: |
            [
              'conventional-changelog-conventionalcommits',
              '@semantic-release/changelog',
              '@google/semantic-release-replace-plugin',
              '@semantic-release/git',
              'semantic-release-slack-bot'
            ]
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
          SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}

And, for completeness, my .releaserc (I use the YAML format):

branches: master
plugins:
  - '@semantic-release/commit-analyzer'
  - '@semantic-release/release-notes-generator'
  - '@semantic-release/github'

  # generate changelog CHANGELOG.md
  - '@semantic-release/changelog'

  # update pyproject.toml with newest version
  - - '@google/semantic-release-replace-plugin'
    - replacements:
      - files: [pyproject.toml]
        from: "version = \".*\""
        to: "version = \"${nextRelease.version}\""
        results:
          - file: pyproject.toml
            hasChanged: true
            numMatches: 1
            numReplacements: 1
        countMatches: true

  # commit CHANGELOG.md and pyproject.toml
  - - '@semantic-release/git'
    - assets:
      - CHANGELOG.md
      - pyproject.toml

  # notify slack, using SLACK_TOKEN from environment
  - - 'semantic-release-slack-bot'
    - packageName: csm-terraform-modules
      notifyOnSuccess: true
      notifyOnFail: true
      slackChannel: "#my-slack-channel"
      markdownReleaseNotes: true

preset: conventionalcommits

Hope this saves the next guy about 8hrs of time. 🤦🏼

I had to add the Issues permission for my app, otherwise the @semantic-release/github plugin fails to search issues. Hope this helps others.

amrsmind commented 8 months ago

You can use the @semantic-release/exec plugin in combination with GitHub CLI.

Note that my answer is missing the part about getting GitHub CLI to be installed and configured (with a GitHub token) in your CI environment.

  1. Install the exec plugin:

    npm install --save-dev @semantic-release/exec
  2. Update your semantic-release configuration: Add the exec plugin in your release.config.js to run a custom script that handles PR creation.

    module.exports = {
     // ... other config ...
     plugins: [
       // ... other plugins ...
       [
         '@semantic-release/exec',
         {
           prepareCmd: './create-release-pr.sh ${nextRelease.version} "${nextRelease.notes}"'
         }
       ]
     ],
    };
  3. Create a script for PR creation (create-release-pr.sh): Write a script that checks out a new branch, commits changes like package.json and CHANGELOG.md, and then uses gh to create a PR.

    #!/bin/bash
    VERSION=$1
    NOTES=$2
    
    git checkout -b release/$VERSION
    git add package.json CHANGELOG.md
    git commit -m "chore(release): $VERSION [skip ci]"
    git push origin release/$VERSION
    
    gh pr create --base main --head release/$VERSION --title "Release $VERSION" --body "$NOTES"
boxrick commented 8 months ago

So one issue I find is I want to do this more widely with basically all repos generated from templates in the 'init' stage. This obviously creates some issues since we have a CODEOWNERS which only allows a certain team to commit back to the repo.

So I thought why don't I just add it to the TEAM on repo creation but this isn't easy to due Github having a lack of fine grained permissions on a user on all repos and also

So my solution / workaround for this is to use a PAT token, but this PAT token can be owned against an org rather than a user. Then give it the following set of permissions to enable it to both add it to the TEAM and modify the permissions on the repo:

Screenshot 2023-12-19 at 16 32 07
travi commented 8 months ago

I would start by asking if you truly need to make a commit as part of your release process. If you choose not to make a commit, the need to push a commit no longer exists. There is a reason we do not include the git plugin in core.

mrlubos commented 8 months ago

@travi Is the recommended approach to create a commit as a part of pull request before being merged?