How do I execute a post-receive hook on msysgit on Windows hosted by Apache? - msysgit

I'm setting up a Git server on a Windows host. I have installed the latest Apache, and have it working with msysGit. I'm not using SSH at all; I can push and pull through HTTP.
Now I want to add a post-receive hook to notify my build server, but I can't figure out how to do that. I see the sample hook scripts in the repository on the server, but I'm confused about what to do there. Do I put a Windows batch file there, named post-receive.bat, or do something else?
I'm a bit fuzzy on details of what this is all doing, but Apache is executing c:\Program Files\git\libexec\git-core\git-http-backend.exe when it sees a Git URL. Is git-http-backend.exe going to trigger the post-receive hook?
Update
I'm getting closer. Here's my hook, in hooks/post-receive in my repo:
#!/c/Program Files/Git/bin/sh
curl http://mybuildserver:8080/job/Whazzup/build
I changed the shebang from #!/bin/sh because on Windows I don't have that. Now in the Apache error log I get the message error: cannot spawn hooks/post-receive: No such file or directory
Incidentally, Git bash's chmod does not seem to work. But I was able to get the permission on post-receive to rwxr-xr-x by renaming the sample file.
Update
I changed the shebang line back to #!/bin/sh, but I still get the same error in the Apache error log: error: cannot spawn hooks/post-receive: No such file or directory. As a test I opened a Git bash prompt in the hooks folder, and executed the hook with ./post-receive, and it worked.
Update
Now I'm wondering if I have a different problem. Taking VonC's advice, I tried running Apache httpd from the command line under my own account, instead of as a service under LocalSystem. Still the same thing. Pushing and pulling work fine, but the hook doesn't execute. Then I tried getting Apache out of the equation. From a Git bash prompt on the same computer as the repo, I did a clone (via filesystem), modify, commit, and push. But the hook still didn't execute.
Update
OK, I had a silly problem in my hook script, but now at least it executes when I push to the repo from the same computer (via filesystem). But not when I push through Apache. Apache is now running under a regular account, and the Apache account has full control of the repository. The push works fine, but the post-receive hook doesn't execute.

Apache is executing c:\Program Files\git\libexec\git-core\git-http-backend.exe when it sees a Git URL. Is git-http-backend.exe going to trigger the post-receive hook?
No, it will pass the command (clone, push, pull) to git itself.
The post-receive hook will be executed after the push has been completed, and it is a bash (unix shell) script, as illustrated in " post-receive hook on Windows - GIT_WORK_DIR: no such file or directory ".
See also " git windows post pull " to see where you can create that post-receive script (in the .git/hooks of your repo): it has nothing to do with your http Apache service in front of the repos.
Regarding the error message "cannot spawn hooks/post-receive: No such file or directory", you can refer to " msysgit error with hooks: "git error: cannot spawn .git/hooks/post-commit: No such file or directory" ":
The shebang must be #!/bin/sh
Apache must run as a regular user instead of Local System, in order to benefit from the environment variables defined for said regular user.
<path_to_git>\bin must be in the PATH

Related

Integrating GIT repository with Jenkins

When I am trying to give the Git URL in Jenkins source code management, I am getting this error:
Failed to connect to repository : Error performing command: git.exe ls-remote -h https://github.com/shivnathr/DevOPS1 HEAD
How can I avoid it?
Make sure your Jenkins is running as your account, and not as a service with a technical account.
That way, Jenkins will benefit from the same configuration as your account.
But first, check if you can, with your account, in a simple CMD shell session, execute that same command successfully:
git.exe ls-remote -h https://github.com/shivnathr/DevOPS1 HEAD
When you configure this in Jenkins, it gives this error. But if you ignore this error, does it then work for the build? Have you configured git tools in Jenkins? I am not sure if having git in the path for the user running Jenkins will work (it might), but if you configure a git tool, it should use the first tool in the list to find git. BUT, if the first tool is set to auto-install, then this problem can occur. Make sure the first git tool is just pointing to an installation on the machine. I believe this is a bug. I found this on one of my installations, but I have yet to open an issue for it.

Change upstream of local (hg-git) clone from (github) original to fork

I discovered an OSS project I've contributed to had moved to github. I installed hg-git and cloned a local repo from the git:// URL; then I made changes.
I then realized I really wanted my own github fork, so I made one; but I haven't been able to figure out quite how to switch my existing local repo. I've changed the local repo settings to use the git:// URL of my fork, and it can pull; but I can't push my changes up. It tells me to use the https:// URL, but when I make that change, I can neither pull nor push -- I get an error 406, "not acceptable."
The work done in the local repo is minimal, so I can redo it, but it'd be simpler if the local repo and my fork could just connect now.
UPDATE
I've installed Github for Windows so I could manage the SSH key. It generated a key (github_rsa) and attached it to my Github account.
I edited the hgrc file and added a [ui]ssh= setting pointing to the local git 'ssh' command (buried down in %APPDATA%\Local\Github).
With this, if I go into a "git-shell" window, which I guess spawns ssh-agent, then I can enter commands such as "hg incoming" and the connection is made. So I've got the remote repo URL right, and within the git-shell ecosystem, I've got the SSH keys set up right.
From a regular CMD.EXE window, the same command yields "Permission denied (publickey)". From TortoiseHg, the same error appears when I try an "incoming" action. I'd prefer to keep using TortoiseHg, but I'm not sure how to get it to use SSH.
FINAL UPDATE
For some reason, TortoisePlink doesn't want to play with github's SSH server, at least not with the Github-for-Windows-generated key. So I still have Github for Windows installed (not necessarily a bad thing, but superfluous to what I wanted to do).
To get hg and TortoiseHg to connect, I had to modify my project settings:
[ui]
ssh = %USERPROFILE%\AppData\Local\GitHub\<salt>\bin\ssh -i %USERPROFILE%\.ssh\github_rsa
That is: point to the SSH command, installed with portable GitHub, and specify the github-generated key on the command line. With this configuration, I don't need ssh-agent to be running.
You need to push via ssh, meaning you need to push via:
hg push git+ssh://git#github.com/<login>/<repo>
Note the usage of git# instead of your login in the first part of the URL. This actually matters; the server will figure out your credentials via the supplied SSH key.
You may also have to add your ssh key to your GitHub account first (per step 4 of this page).
This assumes that you created a fork of the original GitHub repository via the GitHub UI; pushing to an empty repository with hg-git may require additional steps.

github - attempting to push/pull/update (not sure of the terminology) updated code from github to remote server via terminal/ssh mac os

So I have my local computer - where I've updated my (html/js/css) code, github (where I've pushed the updated code already by doing a git add + git commit + git push origin master) and then the server of the actual website which the code is for.
I've connected to the server via the command line terminal. I've already previously cloned the code to the server (by running the command git clone [REPO URL]) while logged in to the server via SSH, so the (un-updated-)files are there.
But now that I've updated the code, and pushed that update to github, how do I now update or push the repo/code/updated-github-code to the server???
I'm currently looking at the terminal with
[~]#
^ showing. I tried to git clone [REPO URL] again, but then I get the msg:
fatal: destination path 'name of my file' already exists and is not an empty directory
Am I missing or overlooking a step? Well obviously I am but I could use some help please. Like I said I'm trying to update the code to the server so the actual website will reflect the changes I made to the code and so everything is in sync (local code, code pushed to github and hopefully/eventually the code on the server/website).
I am just learning this obviously, so go easy on me (I've spent almost the entire day learning to connect to the server via SSH in terminal)...
Also, feel free to correct my terminology...
Pull from github while ssh'd into the server using the link from the github repo "copy to clipboard" button on the web interface. If that doesn't work you could try wiping the repos folder on the server and cloning from scratch. But use that option with caution if downtime is unacceptable for this particular web app.

Can commits/pushes to github be automated?

I've moved a site to a Jekyll / GitHub Pages setup and have an iOS-based markdown editor that syncs to dropbox. Currently I'm investigating ways to bridge the gap and have files created on the go automatically committed and pushed to the GitHub repo but unsure where to start. Is anything like this possible?
(I am not experienced in using Automator on OSX but it seems like it might be an option, though I can't guarantee that a machine will be awake all the time)
Using cron should do the trick. Note that you'll need to have key-based authentication set up for git so you're not prompted a password on push.
(Note that I've used these tools in Linux, but they should work in OS X as well.)
Create your script somewhere
#!/bin/sh
cd /path/to/git/repo
git commit -a -m "Automated commit message." # commit all changes
git push
Make the schript executable
chmod + x script.sh
Run crontab -e to edit your cron file, and add 0 * * * * /path/to/script.sh to execute the script once per hour.
This also assumes that this will be the only committer. If anyone else pushes to the repo from elsewhere, you'll have to merge those changes to this clone before this script will push successfully again.
You could also check out Flashbake!

Jenkins: FTP / SSH deployment, including deletion and moving of files

I was wondering how to get my web-projects deployed using ftp and/or ssh.
We currently have a self-made deployment system which is able to handle this, but I want to switch to Jenkins.
I know there are publishing plugins and they work well when it comes to uploading build artifacts. But they can't delete or move files.
Do you have any hints, tipps or ideas regarding my problem?
The Publish Over SSH plugin enables you to send commands using ssh to the remote server. This works very well, we also perform some moving/deleting files before deploying the new version, and had no problems whatsoever using this approach.
The easiest way to handle deleting and moving items is by deleting everything on the server before you deploy a new release using one of the 'Publish over' extensions. I'd say that really is the only way to know the deployed version is the one you want. If you want more versioning-system style behavior you either need to use a versioning system or maybe rsync that will cover part of it.
If your demands are very specific you could develop your own convention to mark deletions and have them be performed by a separate script (like you would for database changes using Liquibase or something like that).
By the way: I would recommend not automatically updating your live sites after every build using the 'publish over ...' extension. In case we really want to have a live site automatically updated we rely on the Promoted Builds Plugin to keep it nearly fully-automated but add a little safety.
I came up with a simple solution to remove deleted files and upload changes to a remote FTP server as a build action in Jenkins using a simple lftp mirror script. Lftp Manual Page
In Short, you create a config file in your jenkins user directory ~/.netrc and populate it with your FTP credentials.
machine ftp.remote-host.com
login mySuperSweetUsername
password mySuperSweetPassword
Create an lftp script deploy.lftp and drop it in the root of your .git repo
set ftp:list-options -a
set cmd:fail-exit true
open ftp.remote-host.com
mirror --reverse --verbose --delete --exclude .git/ --exclude deploy.lftp --ignore-time --recursion=always
Then add an "Exec Shell" build action to execute lftp on the script.
lftp -f deploy.lftp
The lftp script will
mirror: copy all changed files
reverse: push local files to a remote host. a regular mirror pulls from remote host to local.
verbose: dump all the notes about what files were copied where to the build log
delete: remove remote files no longer present in the git repo
exclude: don't publish .git directory or the deploy.lftp script.
ignore-time: won't publish based on file creation time. If you don't have this, in my case, all files got published since a fresh clone of the git repo updated the file create timestamps. It still works quite well though and even files modified by adding a single space in them were identified as different and uploaded.
recursion: will analyze every file rather than depending on folders to determine if any files in them were possibly modified. This isn't technically necessary since we're ignoring time stamps but I have it in here anyway.
I wrote an article explaining how I keep FTP in sync with Git for a WordPress site I could only access via FTP. The article explains how to sync from FTP to Git then how to use Jenkins to build and deploy back to FTP. This approach isn't perfect but it works. It only uploads changed files and it deletes files off the host that have been removed from the git repo (and vice versa)