This might be a silly question, but here I am after two days of head banging 😔
I'm currently working on a GitHub Actions job, that would at some point git push to a protected branch (master, actually). However, once it gets to this step, the job fails with a "You're not authorized to push" error message:
error code GH006
In my situation, the first time it happened, it meant that the worker (CLI, bash) is not authorized at all. So I went to log it in a dedicated GitHub account, — and this is where I'm stuck for a couple of days now.
So, how do I login to GitHub account via CLI?
The things I've tried:
Pushing to master manually
This works without errors, since the authorization is OK, — but it is obviously not automated, which is what I'm after.
A couple of details:
I was using Windows 10, whereas the job is set up to run on "ubuntu-18.04";
I've removed all GitHub-related logins from Windows Credential Manager before performing git push, and set them up again via GitHub Login dialog window.
Manually pushing under unauthorized credentials fails, as expected.
git remote set-url origin "https://$username:$token#github.com/my/repo"
This didn't seem to give any effect. I've tried both setting URL of the existing remote and removing-than-adding remotes with different URLs, — both approaches seem to work (not work) the same.
None of the configurations below worked:
steps:
- run: git remote set-url origin "https://$username:$token#github.com/my/repo"
- run: git push origin master
steps:
- run: git remote remove origin
- run: git remote add origin "https://$username:$token#github.com/my/repo"
- run: git fetch origin --all # with and without this step
- run: git push origin master
curl -u "$username:$token" https://api.github.com/user
This is suggested in the docs, and it does succeed, but the login does not persist until git push — even if the pushing happens in the same step. I suspect, there might be a cookie-related solution, but I'm not sure how do they work in a non-browser environment. Also, I believe that this API is designed for different purposes.
Both of these configurations failed:
steps:
# separate processes
- run: curl -u "$username:$token" https://api.github.com/user
- run: git push origin master
steps:
# same process
- run: |
curl -u "$username:$token" https://api.github.com/user
git push origin master
actions/checkout#v2 will now configure and persist authentication when setting the token input. You shouldn't need to configure the origin URL manually.
- uses: actions/checkout#v2
with:
token: ${{ secrets.PAT }}
- name: Create a change
run: echo "test" > test.txt
- name: Commit change
run: |
git config --global user.name 'Your Name'
git config --global user.email 'your-username#users.noreply.github.com'
git add -A
git commit -m "Add test file"
git push
According to this comment on the GitHub forums, the PAT must be created from an admin/org owner account. A collaborator with write access is not enough to push to protected branches.
Related
I have a bash script that pulls and builds some source code. If I am on the master branch, it works as expected, however if I change to a different branch it says it is already up to date even if there are pushed changes. If I do a git pull outside the script from the cmd line, it pulls as expected.
deploy.sh
echo | git branch
echo "git pull ..."
git pull https://tech-dev:password#bitbucket.org/mycompany/pow-wow.git
Output
./deploy.sh
master
* spring3upgrade
git pull ...
From https://bitbucket.org/mycompany/pow-wow
* branch HEAD -> FETCH_HEAD
Already up-to-date.
Question
How do I get it to pull from the branch I am currently on in the bash script?
why it doesn't work
If you are pulling using an explicit URL (as displayed in your question) :
there is no default refspec, so only the remote HEAD (the default branch) is fetched
there is no default "remote branch" configured for your checked out branch, so git pull will merge in whatever that default branch points to (ie: it will try to merge origin/master, not origin/spring3upgrade)
how to fix it
The simplest way is to define a named remote (e.g: origin), let git set up its default configuration, and have named remote tracking branches:
git remote add origin <URL>
git fetch
# for branches that already exist locally:
git switch <branch>
git branch -u origin/branch
# for remote branches not checked out locally:
git switch <branch> # will automatically take 'origin/<branch>' as a base,
# and set it as the upstream branch
If you have a special need which requires to not name the remote: you may provide the refspec you need on the command line, probably:
# pull the branch which has the same name as your local branch:
git pull <repo> "$(git branch --show-current)"
You need to provide specific credentials to access your remote. There are many ways to do that :
a pretty common way is to go through ssh: create an ssh key, configure your central server to accept the public key for a CI (you choose the name ...) dedicated user, and set up your builder agent to access your repo through ssh with that key
or using https, set up a credentials manager (see the link your posted in your comment, or git help credentials), or the many http.* settings in git help config
I'm trying to do the following with Bitbucket Pipelines when i push to my test brand:
- git fetch
- git checkout master
- git pull origin test
- git push origin master
But i get the following message on git fetch: Permission denied (publickey). I was following this tutorial https://confluence.atlassian.com/bitbucket/use-ssh-keys-in-bitbucket-pipelines-847452940.html so i already added an ssh key, but cannot understand what are the next steps that i need for the execution to have permissions to connect to the repository.
If “from same repository” really means that you want to access the repository in which the pipeline runs, the answer is: you don’t need that. When the pipeline runs, it starts the Docker image you defined in your YAML configuration and automatically checks out the commit you pushed. This means that at the moment when when your command (git fetch) is executed, the sources are already waiting for you in path /project.
BitBucket Pipelines automatically checks out the repository upon running. However, if you want to make changes to the repository (e.g. git tag or git push) you will need to add the SSH keys according to the post you have already found (https://confluence.atlassian.com/bitbucket/use-ssh-keys-in-bitbucket-pipelines-847452940.html). That works for our environment.
Can you post the full bitbucket-pipelines.yml file?
With my colleagues, we work on a C++ library that becomes more and more important each day. We already built continuous integration utilities through the gitlab-ci.yml file that let us:
Build & Test in Debug mode
Build & Test in Release mode
Perform safety checks like memory leaks using Valgrind and checking if there is any clear symbol in our library we don't want inside it
Generate documentation
All kind of stuff that made us choose GitLab !
We would like to profile our whole library and push the benchmarks in a separate project. We have already done something like for out documentation using the SSH key method but we would like to avoid this this time.
We tried a script like this:
test_ci_push:
tags:
- linux
- shell
- light
stage: profiling
allow_failure: false
only:
- new-benchmark-stage
script:
- git clone http://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.mycompany.home/developers/benchmarks.git &> /dev/null
- cd benchmarks
- touch test.dat
- echo "This is a test" > test.dat
- git config --global user.name "${GITLAB_USER_NAME}"
- git config --global user.email "${GITLAB_USER_EMAIL}"
- git add --all
- git commit -m "GitLab Runner Push"
- git push http://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.mycompany.home/developers/benchmarks.git HEAD:master
- cd ..
We also tried a basic git push origin master to push our updated files but each time we got the same answer:
remote: You are not allowed to upload code for this project.
fatal: unable to access 'http://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx#gitlab.mycompany.home/developers/benchmarks.git/': The requested URL returned error: 403
Both projects are under the same site and I have the rights to push in both. Where am I doing anything wrong here ?
The gitlab ci token is more like the deploy key in github.com, so it only has read access to the repository. To actually push you will need to generate a personal access token and use that instead.
First you need to generate the token as shown here in the gitlab documentation. Make sure you check both the read user and api scopes. Also this only works in GitLab 8.15 and above. If you are using an older version and do not wish to upgrade there's an alternative method I could show you but it is more complex and less secure.
In the end your gitlab-ci.yml should look something like this:
test_ci_push:
tags:
- linux
- shell
- light
stage: profiling
allow_failure: false
only:
- new-benchmark-stage
script:
- git clone http://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.mycompany.home/developers/benchmarks.git &> /dev/null
- cd benchmarks
- echo "This is a test" > test.dat
- git config --global user.name "${GITLAB_USER_NAME}"
- git config --global user.email "${GITLAB_USER_EMAIL}"
- git add --all
- git commit -m "GitLab Runner Push"
- git push http://${YOUR_USERNAME}:${PERSONAL_ACCESS_TOKEN}#gitlab.mycompany.home/developers/benchmarks.git HEAD:master
- cd ..
While the previous answers are more or less fine, there are some important gotya's.
before_script:
- git config --global user.name "${GITLAB_USER_NAME}"
- git config --global user.email "${GITLAB_USER_EMAIL}"
script:
- <do things>
- git push "https://${GITLAB_USER_LOGIN}:${CI_GIT_TOKEN}#${CI_REPOSITORY_URL#*#}" "HEAD:${CI_COMMIT_TAG}"
For one, we only need to set the username/email to please git.
Secondly having it in the before script, is not super crucial, but allows for easier reuse when doing 'extend'.
Finally, pushing https is 'fine' but since we're not using a stored ssh key, we should avoid anything that can reveal the token. For one, while gitlab won't print the token in this command, git will happily inform us that the new upstream is set to https://username:thetokeninplaintexthere#url
So there's your token in plain text, so don't use -u to set an upstream.
Also, it's not needed, we are only doing a single push.
Further more, when determining the URL, I found that using the exist CI_REPOSITORY_URL to be the most reliable solution (when moving repo's for example or whatnot). So we just replace the username/token in the URL string.
You could also provide user and password (user with write access) as secret variables and use them.
Example:
before_script:
- git remote set-url origin https://$GIT_CI_USER:$GIT_CI_PASS#$CI_SERVER_HOST/$CI_PROJECT_PATH.git
- git config --global user.email 'myuser#mydomain.com'
- git config --global user.name 'MyUser'
You have to define GIT_CI_USER and GIT_CI_PASS as secret variables (you could always create dedicated user for this purpose).
With this configuration you could normally work with git. I'm using this approach to push the tags after the release (with Axion Release Gradle Pluing - http://axion-release-plugin.readthedocs.io/en/latest/index.html)
Example release job:
release:
stage: release
script:
- git branch
- gradle release -Prelease.disableChecks -Prelease.pushTagsOnly
- git push --tags
only:
- master
I'm using the following GitLab job:
repo_pull_sync:
image: danger89/repo_mirror_pull:latest
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
- if: $REMOTE_URL
- if: $REMOTE_BRANCH
- if: $ACCESS_TOKEN
before_script:
- git config --global user.name "${GITLAB_USER_NAME}"
- git config --global user.email "${GITLAB_USER_EMAIL}"
script:
- git checkout $CI_DEFAULT_BRANCH
- git pull
- git remote remove upstream || true
- git remote add upstream $REMOTE_URL
- git fetch upstream
- git merge upstream/$REMOTE_BRANCH
- git push "https://${GITLAB_USER_LOGIN}:${ACCESS_TOKEN}#${CI_REPOSITORY_URL#*#}" "HEAD:${CI_DEFAULT_BRANCH}"
I'm using my own danger89/repo_mirror_pull docker image based on alpine, check this GitHub repository for more info.
This GitLab job pull upstream changes from the predefined remote repository + branch (see variables below), and merge them locally in CI/CD and pushes them in GitLab again.
Basically I created a repository pull mirror (which is officially not available for free on GitLab CE, only a push mirror is supported in GitLab).
Create in GitLab a Project Access Token first in GitLab. Via: Settings->Access Tokens. Check 'api' as the scope.
Create a new schedule, via: CI/CD->Schedules->New schedule. With the following 3 variables:
REMOTE_URL (example: https://github.com/project/repo.git)
REMOTE_BRANCH (example: master)
ACCESS_TOKEN: (see Access Token in the first step! Example: gplat-234hcand9q289rba89dghqa892agbd89arg2854, )
Save pipeline schedule
Again, see also: https://github.com/danger89/repo_pull_sync_docker_image
Regarding the question, see the git push command above, which allows you to push changes back into GitLab using GitLab (project) access token.
Prefacing this with I am very new to git and github.
I set up a repo on github, as user zzz, and it is correctly listed in my local (repo-specific) git config file, which has entries like the following when I do 'git config --local --list':
remote.origin.url=https://github.com/zzz/myrepo.git
user.name=zzz
user.email=yyy#example.com
But when I do do git push origin master, it get 403 denied to user 'xxx'... a user which corresponds to a completely separate github account. How do I fix this? And why is it picking up user 'xxx' when that is not the user i carefully specified in the local config file? I am on windows 7 machine.
Git store credentials in Windows, clear them referring below image:
Run your git push command, it will prompt you to enter credentials again.
Image Courtesy - Remove credentials from Git
So I clone a private repo on my VPS using SSH with Git Shell. Now when I commit changes and try to push it to my VPS it says
"Sync failed: The repository doesn't seem to exist anymore. You may not have access, or it may have been deleted or renamed."
Whenever I go into Git Shell and do "git push origin master", I enter my password and it pushes it succesfully.
Why can't I do this through the Github client?