Skip to content

Git push rule Commit message blocking semantic release

Summary

We have setup a push rule on several repositories to enforce a commit message based on the Semantic Release commit message analyser.

^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\([a-z]+\)){0,1}:\s.+

However since upgrading to v16+ the above commit message rule is blocking the git notes push, but we are unable to figure out why.

Orignally opened with semantic release: https://github.com/semantic-release/semantic-release/issues/1446

Steps to reproduce

(How one can reproduce the issue - this is very important)

  1. Setup a new project with semantic release
    • package.json (see below)
    • .release.rc (see below)
    • .gitlab.ci (see below)
  2. Setup a push rule on the project
    • Commit Message: ^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\([a-z]+\)){0,1}:\s.+
  3. Setup CI Variables
    • GIT_AUTHOR_EMAIL
    • GIT_COMMITTER_EMAIL
    • SSH_PRIVATE_KEY (For deploy key)
  4. Setup a deploy key
  5. Create a new commit with message "feat: testing release"
  6. Monitor pipeline

package.json

{
  "dependencies": {
    "@semantic-release/gitlab": "4.1.0",
    "@semantic-release/release-notes-generator": "7.3.5",
    "semantic-release": "16.0.4"
  },
  "name": "test-project"
}

.releaserc.yaml

---
plugins:
  - "@semantic-release/commit-analyzer"
  - "@semantic-release/release-notes-generator"
preset: angular
tagFormat: "${version}"

.gitlab-ci.yml

default: 
  image: alpine:latest

stages:
  - release

before_script:
  - apk update
  - apk add git
  - apk add openssh-client
  - apk add nodejs npm
  - git config --global user.email "${GIT_AUTHOR_EMAIL}"
  - git config --global user.name "Gitlab CI" 
  - mkdir -p ~/.ssh
  - cp $SSH_PRIVATE_KEY ~/.ssh/id_rsa
  - chmod 700 ~/.ssh
  - chmod 400 ~/.ssh/id_rsa
  - eval `ssh-agent`
  - ssh-add ~/.ssh/id_rsa
  - ssh-keyscan -t rsa ${CI_SERVER_HOST} >> ~/.ssh/known_hosts
  - git remote set-url origin git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git
  - chmod 644 ~/.ssh/known_hosts


release:
  only:
    refs:
      - master
  stage: release
  script:
    - npm install
    - npx semantic-release

Example Project

We are using a on prem EE version of GitLab (GitLab Enterprise Edition 12.6.7-ee) but here is a GitLab.com attempt (although I annot use push rules on the free level)

https://gitlab.com/robinmoss.uk/issue-207807

What is the current bug behavior?

The release pipeline fails with the following error:

[1:49:13 PM] [semantic-release] › ✖  An error occurred while running semantic-release: { Error: Command failed with exit code 1: git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release

What is the expected correct behavior?

The push should succeed.

Relevant logs and/or screenshots

177 [1:49:11 PM] [semantic-release] › ✔  Completed step "generateNotes" of plugin "@semantic-release/exec"
178 [1:49:13 PM] [semantic-release] › ✖  An error occurred while running semantic-release: { Error: Command failed with exit code 1: git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release
179 remote: GitLab: Commit message does not follow the pattern '^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\([a-z]+\)){0,1}:\s.+'        
180 To https://gitlab/project.git
181  ! [remote rejected] refs/notes/semantic-release -> refs/notes/semantic-release (pre-receive hook declined)
182 error: failed to push some refs to 'https://gitlab-ci-token:[secure]@gitlab/project.git'
183     at makeError (/builds/rainbow/release-notes-generator/node_modules/execa/lib/error.js:58:11)
184     at handlePromise (/builds/rainbow/release-notes-generator/node_modules/execa/index.js:114:26)
185     at process._tickCallback (internal/process/next_tick.js:68:7)
186   shortMessage:
187    'Command failed with exit code 1: git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release',
188   command:
189    'git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release',
190   exitCode: 1,
191   signal: undefined,
192   signalDescription: undefined,
193   stdout: '',
194   stderr:
195    'remote: GitLab: Commit message does not follow the pattern \'^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\\([a-z]+\\)){0,1}:\\s.+\'        \nTo https://gitlab/project.git\n ! [remote rejected] refs/notes/semantic-release -> refs/notes/semantic-release (pre-receive hook declined)\nerror: failed to push some refs to \'https://gitlab-ci-token:[secure]@gitlab/project.git\'',
196   failed: true,
197   timedOut: false,
198   isCanceled: false,
199   killed: false }
200 { Error: Command failed with exit code 1: git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release
201 remote: GitLab: Commit message does not follow the pattern '^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\([a-z]+\)){0,1}:\s.+'        
202 To https://gitlab/project.git
203  ! [remote rejected] refs/notes/semantic-release -> refs/notes/semantic-release (pre-receive hook declined)
204 error: failed to push some refs to 'https://gitlab-ci-token:[secure]@gitlab/project.git'
205     at makeError (/builds/rainbow/release-notes-generator/node_modules/execa/lib/error.js:58:11)
206     at handlePromise (/builds/rainbow/release-notes-generator/node_modules/execa/index.js:114:26)
207     at process._tickCallback (internal/process/next_tick.js:68:7)
208   shortMessage:
209    'Command failed with exit code 1: git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release',
210   command:
211    'git push https://gitlab-ci-token:[secure]@gitlab/project.git refs/notes/semantic-release',
212   exitCode: 1,
213   signal: undefined,
214   signalDescription: undefined,
215   stdout: '',
216   stderr:
217    'remote: GitLab: Commit message does not follow the pattern \'^(build|ci|docs|feat|fix|perf|refactor|style|test|chore)(\\([a-z]+\\)){0,1}:\\s.+\'        \nTo https://gitlab/project.git\n ! [remote rejected] refs/notes/semantic-release -> refs/notes/semantic-release (pre-receive hook declined)\nerror: failed to push some refs to \'https://gitlab-ci-token:[secure]@gitlab/project.git\'',
218   failed: true,
219   timedOut: false,
220   isCanceled: false,
221   killed: false }
225 ERROR: Job failed: exit code 1

Output of checks

(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)

Results of GitLab environment info

Expand for output related to GitLab environment info

(For installations with omnibus-gitlab package run and paste the output of: sudo gitlab-rake gitlab:env:info)

(For installations from source run and paste the output of: sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production)

Results of GitLab application Check

Expand for output related to the GitLab application check

(For installations with omnibus-gitlab package run and paste the output of: sudo gitlab-rake gitlab:check SANITIZE=true)

(For installations from source run and paste the output of: sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true)

(we will only investigate if the tests are passing)

Proposal

I believe that we verify all commits to match push rules. git notes add creates a new reference refs/notes/* that we identify as a regular commit and apply the push rule validation to it.

As a possible solution, we can either exclude refs/notes/* or verify only refs/heads and refs/tags from push rules validation flow (note: the code responsible for the error message)

Edited by Vasilii Iakliushin