On Mar 28, 2013 Dan Allen explained how to deploy to github-pages automatically. Many other GitHub users like Steve Klabnik and Domenic Denicola followed with the same approach:
Use an OAuth token with public_repo
or repo
permission to access the Github account over HTTPS inside a virtual build environment.
The same applies to Travis CI's built-in abilities, and there are more restrictions as deploying GitHub Releases works only for tags, not for branches.
The token grants write access for all of your (public) repositories and organizations!
This probably doesn't matter for dedicated accounts.
Use a deploy key specific to a particular repository:
To deploy to a custom or unsupported provider, use the after-success build stage or script provider.
This work is inspired by Tommy Chen's article about Hexo in the first place.
By the way: There exist lots of different Static Site Generators, probably in your favoured programming language!
placeholder | description |
---|---|
GH_USER |
GitHub account to use |
GH_REPO |
Repositories in GH_USER |
GH_TOKEN |
Personal access token |
GIT_NAME |
Identity used for deployed commits |
GIT_EMAIL |
- |
ssh_pass |
Passphrase for the encrypted SSH key |
First of all set up Travis CI!
placeholder | repo | branch |
---|---|---|
GH_REPO_IN |
site | master |
GH_REPO_OUT |
GH_USER .github.io |
master |
There's a Hexo installation (example) inside GH_REPO_IN
.
The following shell-commands will be executed in GH_REPO_IN
's directory.
placeholder | repo | branch |
---|---|---|
GH_REPO_IN |
GH_USER .github.io |
src2 3 |
GH_REPO_OUT |
GH_USER .github.io |
master |
GH_REPO_IN |
blog | master |
GH_REPO_OUT |
blog | gh-pages 1 2 |
If both IN
and OUT
are in the same repository, it's less secure since you're able to access all branches in it with the same deploy key.
- 1:
_config.yml
:branch: gh-pages
underdeploy:
- 2:
git checkout --orphan
(branch with its own history) - 3:
.travis.yml
: Modfiybranch
underdeploy:
andbranches
Make sure your GitHub token has the scopes required by Travis CI.
- http://docs.travis-ci.com/api/?shell#external-apis
- http://docs.travis-ci.com/user/github-oauth-scopes/
- https://help.github.com/articles/creating-an-access-token-for-command-line-use/
travis — read:org, repo:status, repo_deployment, user:email, write:repo_hook
gem install travis -v 1.8.0 --no-rdoc --no-ri
If you have a GitHub token, you can use the GitHub authentication endpoint to exchange it for an access token. The Travis API server will not store the token or use it for anything else then verifying the user account.
travis help login
travis login --org --user 'GH_USER' --github-token 'GH_TOKEN'
unset HISTFILE #Quit shell without saving history
travis settings maximum_number_of_builds --set 1
travis settings
# Settings for GH_USER/GH_REPO_IN:
# [+] builds_only_with_travis_yml Only run builds with a .travis.yml
# [+] build_pushes Build pushes
# [-] build_pull_requests Build pull requests
# 1 maximum_number_of_builds Maximum number of concurrent builds
ssh-keygen -t rsa -b 4096 -C "GIT_EMAIL" -f "ssh_key" -q -N "ssh_pass"
unset HISTFILE
Make sure not to add the private
ssh_key
to the git repository. You should ignore it regarding the worst case.
printf "\n%s\n%s\n\n" ssh_key{,.pub} >> .gitignore
Attention: Do it after
hexo init
!
Copy the contents of the ssh_key.pub
file to your clipboard ..
xclip -sel clip < ssh_key.pub
.. and paste it into
travis encrypt-file ssh_key
The ouput contains a line which begins with openssl ...
and must be added to .travis/deploy.sh
(modify -in
and -out
options)
Save GitHub's public SSH key and verify with fingerprint
ssh-keyscan -t rsa github.com > ssh_known_hosts
wget -q -O - https://help.github.com/articles/what-are-github-s-ssh-key-fingerprints/ \
| { grep -q "$(ssh-keygen -l -f ssh_known_hosts | cut -d' ' -f2)" \
&& echo "Public key was successfully verified by fingerprint"; }
Host github.com
User git
StrictHostKeyChecking yes
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
travis encrypt GIT_NAME=<Your input>
travis encrypt GIT_EMAIL=<Your input>
travis encrypt ssh_pass=<Your input>
The output has to be pasted into your .travis.yml
under env: global:
- http://docs.travis-ci.com/user/deployment/script/
- http://docs.travis-ci.com/user/deployment/custom/#Git
language: node_js
sudo: false
node_js:
# Version depends on your Hexo
- "0.12"
cache:
apt: true
directories:
- node_modules
# Optional
addons:
apt:
packages:
# used by deploy.sh
- expect
# used by gulpfile.js
# - graphicsmagick
env:
global:
- secure: "<encrypted string for GIT_NAME>"
- secure: "<encrypted string for GIT_EMAIL>"
- secure: "<encrypted string for ssh_pass>"
branches:
only:
- master
install:
# package.json
- npm install --no-optional
before_script:
# Clone the repository
- git clone https://github.com/GH_USER/GH_REPO_OUT .deploy_git
script:
# package.json
- npm run build
before_deploy:
# Make the deploy-script executable
- chmod u+x .travis/deploy.sh
deploy:
provider: script
script: .travis/deploy.sh
on:
branch: master
# Prevents from automatically hard resetting to the latest git version
skip_cleanup: true
- Exploring Expect by Don Libes: Handling End Of File (eof)
#!/bin/bash
# stop executing if any errors occur
# stop executing if an unset variable is encountered
set -o errexit -o nounset
# Decrypt the private key
openssl aes-256-cbc -K $encrypted_***_key -iv $encrypted_***_iv -in .travis/ssh_key.enc -out ~/.ssh/id_rsa -d
# Set the permission of the key
chmod 600 ~/.ssh/id_rsa
# Start SSH agent in the background
eval "$(ssh-agent -s)"
# Add the private key to the ssh-agent
# Enter passphrase automatically
expect >/dev/null 2>&1 << EOF
set timeout 10
spawn ssh-add "${HOME}/.ssh/id_rsa"
expect {
"Enter passphrase for" {
send "$ssh_pass\r"
}
}
expect {
timeout { exit 1 }
"denied" { exit 1 }
eof { exit 0 }
}
EOF
# Copy SSH config and known_hosts
cp .travis/ssh_config ~/.ssh/config
cp .travis/ssh_known_hosts ~/.ssh/known_hosts
# Set Git config
git config --global user.name "${GIT_NAME}"
git config --global user.email "${GIT_EMAIL}"
# Deploy with Hexo
# Hide any sensitive credential data that might otherwise be exposed
# In case of debugging you should remove those redirections to /dev/null
expect >/dev/null 2>&1 << EOF
set timeout 600
spawn hexo deploy
expect {
"Enter passphrase for" {
send "$ssh_pass\r"
}
}
expect {
timeout { exit 1 }
"denied" { exit 1 }
eof { exit 0 }
}
EOF
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"hexo": {
"version": ""
},
"scripts": {
"build": "hexo generate && gulp"
},
"dependencies": {
"hexo": "^3.1.1",
"hexo-deployer-git": "0.0.4",
...
},
"devDependencies": {
"gulp": "^3.8.11",
...
},
"optionalDependencies": {
...
}
}
...
# Deployment
## Docs: http://hexo.io/docs/deployment.html
deploy:
type: git
repo: [email protected]:GH_USER/GH_REPO_OUT
branch: master
This work by m3t (96bd6c8bb869fe632b3650fb7156c797ef8c2a055d31dde634565f3edda485ba) <mlt [at] posteo [dot] de> is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.