Skip to content

Instantly share code, notes, and snippets.

@domenic
Last active June 6, 2025 08:01
Show Gist options
  • Save domenic/ec8b0fc8ab45f39403dd to your computer and use it in GitHub Desktop.
Save domenic/ec8b0fc8ab45f39403dd to your computer and use it in GitHub Desktop.

Revisions

  1. domenic revised this gist Nov 25, 2020. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions 0-github-actions.md
    Original file line number Diff line number Diff line change
    @@ -52,3 +52,10 @@ Similarly, if you are using a different branch name than `master`, e.g. if you a
    This relies on third-party code in [`peaceiris/actions-gh-pages`](https://github.com/peaceiris/actions-gh-pages); this code is not maintained by GitHub. In theory, the @peaceiris user could update their action code to extract your `GITHUB_TOKEN`, and update their `v3` tag to point to this new malicious commit. [Read more about this in GitHub's docs](https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions)

    The best security against this, if you are concerned, is to pin to a specific commit, e.g. by replacing `peaceiris/actions-gh-pages@v3` with `peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501` (which is the commit for what is currently tagged as `v3.7.3`). But, this of course means you'll fail to get updates, perhaps even security updates. So on balance, I'm currently recommending using the `v3` tag. Your preferences may vary.

    ## Example project

    A recent project I maintain which uses this approach is [WICG/import-maps](https://github.com/WICG/import-maps). Some features if it you may enjoy perusing:

    - The [`Makefile`](https://github.com/WICG/import-maps/blob/master/Makefile), especially if you're interested in building specifications with [Bikeshed](https://tabatkins.github.io/bikeshed/)
    - The [`.github/workflows/test.yml`](https://github.com/WICG/import-maps/blob/master/.github/workflows/test.yml) file, which shows how to run other build actions alongside the GitHub pages build action in `build.yml`.
  2. domenic revised this gist Nov 25, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 0-github-actions.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@

    This is a set up for projects which want to check in only their source files, but have their gh-pages branch automatically updated with some compiled output every time they push.

    Below are the steps for doing this with Travis CI. However, these days I recommend GitHub Actions, for the following reasons:
    A file below this one contains the steps for doing this with Travis CI. However, these days I recommend GitHub Actions, for the following reasons:

    * It is much easier and requires less steps, because you are already authenticated with GitHub, so you don't need to share secret keys across services like you do when coordinate Travis CI and GitHub.
    * It is free, with no [quotas](https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing).
  3. domenic revised this gist Nov 25, 2020. 1 changed file with 54 additions and 0 deletions.
    54 changes: 54 additions & 0 deletions 0-github-actions.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,54 @@
    # Auto-deploying built products to gh-pages with GitHub Actions

    This is a set up for projects which want to check in only their source files, but have their gh-pages branch automatically updated with some compiled output every time they push.

    Below are the steps for doing this with Travis CI. However, these days I recommend GitHub Actions, for the following reasons:

    * It is much easier and requires less steps, because you are already authenticated with GitHub, so you don't need to share secret keys across services like you do when coordinate Travis CI and GitHub.
    * It is free, with no [quotas](https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing).
    * Anecdotally, builds are much faster with GitHub Actions than with Travis CI, especially in terms of time spent waiting for a builder.

    ## Set up a build script

    Set up your repository with a build script. This could be a checked-in `build.sh`, or a `make` command (I usually use `make ci`), or whatever.

    Ensure that the build script outputs all the results to an `out/` directory. You'll probably want to update `.gitignore` to include `out/`.

    ## The build file

    Add this file to `.github/workflows/build.yml`:

    ```yaml
    name: Build
    on:
    pull_request:
    branches:
    - master
    push:
    branches:
    - master
    jobs:
    build:
    name: Build
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Build
    run: make ci
    - name: Deploy
    if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
    uses: peaceiris/actions-gh-pages@v3
    with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: ./out
    ```
    Here, where it says `run: make ci`, replace it with whatever build script you have, e.g. `run: bash ./build.sh`.

    Similarly, if you are using a different branch name than `master`, e.g. if you are using `main`, then update the three locations which reference `master`.

    ## Security considerations

    This relies on third-party code in [`peaceiris/actions-gh-pages`](https://github.com/peaceiris/actions-gh-pages); this code is not maintained by GitHub. In theory, the @peaceiris user could update their action code to extract your `GITHUB_TOKEN`, and update their `v3` tag to point to this new malicious commit. [Read more about this in GitHub's docs](https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions)

    The best security against this, if you are concerned, is to pin to a specific commit, e.g. by replacing `peaceiris/actions-gh-pages@v3` with `peaceiris/actions-gh-pages@bbdfb200618d235585ad98e965f4aafc39b4c501` (which is the commit for what is currently tagged as `v3.7.3`). But, this of course means you'll fail to get updates, perhaps even security updates. So on balance, I'm currently recommending using the `v3` tag. Your preferences may vary.
  4. domenic revised this gist Jan 30, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ This is a set up for projects which want to check in only their source files, bu

    ## Create a compile script

    You want a script that does a local compile to e.g. an `out/` directory. Let's call this `compile.sh` for our purposes, but for your project it might be `npm build` or `gulp make-docs` or anything similar.
    You want a script that does a local compile to e.g. an `out/` directory. Let's call this `compile.sh` for our purposes, but for your project it might be `npm build` or `gulp make-docs` or `make` or anything similar.

    The `out/` directory should contain everything you want deployed to `gh-pages`. That almost always includes an `index.html`.

  5. domenic revised this gist Jan 30, 2020. 1 changed file with 28 additions and 89 deletions.
    117 changes: 28 additions & 89 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -10,80 +10,9 @@ The `out/` directory should contain everything you want deployed to `gh-pages`.

    Check this script in to your project.

    ## Create a deploy script

    Create a deploy script, call it `deploy.sh`, with the following contents:

    ```bash
    #!/bin/bash
    set -e # Exit with nonzero exit code if anything fails

    SOURCE_BRANCH="master"
    TARGET_BRANCH="gh-pages"

    function doCompile {
    ./compile.sh
    }

    # Pull requests and commits to other branches shouldn't try to deploy, just build to verify
    if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
    echo "Skipping deploy; just doing a build."
    doCompile
    exit 0
    fi

    # Save some useful information
    REPO=`git config remote.origin.url`
    SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
    SHA=`git rev-parse --verify HEAD`

    # Clone the existing gh-pages for this repo into out/
    # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
    # Delete all existing contents except .git (we will re-create them)
    git clone $REPO out
    cd out
    git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
    find -maxdepth 1 ! -name .git ! -name . | xargs rm -rf
    cd ..

    # Run our compile script
    doCompile

    # Now let's go have some fun with the cloned repo
    cd out
    git config user.name "Travis CI"
    git config user.email "$COMMIT_AUTHOR_EMAIL"

    # If there are no changes to the compiled out (e.g. this is a README update) then just bail.
    if git diff --quiet; then
    echo "No changes to the output on this push; exiting."
    exit 0
    fi

    # Commit the "changes", i.e. the new version.
    # The delta will show diffs between new and old versions.
    git add -A .
    git commit -m "Deploy to GitHub Pages: ${SHA}"

    # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
    ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
    ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
    ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
    ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
    openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out ../deploy_key -d
    chmod 600 ../deploy_key
    eval `ssh-agent -s`
    ssh-add ../deploy_key

    # Now that we're all set up, we can push.
    git push $SSH_REPO $TARGET_BRANCH
    ```

    This deploy script depends on an encrypted deploy key file, `deploy_key.enc`, which we will discuss shortly. The basic idea is that Travis stores a couple environment variables for you, not checked in to your repo, which allow the script to decrypt `deploy_key.enc`, which *is* checked in to your repo.

    ## Sign up for Travis and add your project

    Get an account at https://travis-ci.org/. Turn on Travis for your repository in question, using the Travis control panel.
    Get an account at https://travis-ci.com/. Turn on Travis for your repository in question, using the Travis control panel.

    ## Get encrypted credentials

    @@ -105,7 +34,7 @@ storing secure env variables for decryption
    Please add the following to your build script (before_install stage in your .travis.yml, for instance):
    openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in super_secret.txt.enc -out super_secret.txt -d
    openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in deploy_key.enc -out deploy_key -d
    Pro Tip: You can add it automatically by running with --add.
    @@ -114,8 +43,6 @@ Make sure not to add deploy_key to the git repository.
    Commit all changes to your .travis.yml.
    ```

    Make note of that encryption label, here `"0a6446eb3ae3"`. This can be public information; it just says which environment variables to use on the Travis server when decrypting this file.

    You should follow the instructions and commit `deploy_key.enc` to the repository. You should also add `deploy_key` to your `.gitignore`, or delete it. Ignore the bits about `.travis.yml`, however; we're going to do that part all custom-like.

    ## Create your `.travis.yml` file
    @@ -124,15 +51,29 @@ With all this in hand, you can create a `.travis.yml` file. It should look like

    ```yml
    language: generic # don't install any environment
    script:
    - bash ./compile.sh

    script: bash ./deploy.sh
    env:
    global:
    - ENCRYPTION_LABEL: "<.... encryption label from previous step ....>"
    - COMMIT_AUTHOR_EMAIL: "[email protected]"
    ```
    branches:
    only:
    - master

    The `$COMMIT_AUTHOR_EMAIL` variable will be used in the commits to gh-pages that Travis makes on your behalf.
    before_deploy:
    - openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in deploy_key.enc -out deploy_key -d


    deploy:
    provider: pages
    local_dir: out
    deploy_key: deploy_key
    edge:
    branch: master

    notifications:
    email:
    on_success: never
    on_failure: always
    ```
    If your compile script depends on certain environment features, you might want to set up the environment using Travis's built-in abilities, e.g. by changing the language lines like so:
    @@ -146,17 +87,15 @@ node_js:

    ## Finishing up

    At this point you should have 3-4 files checked in to your repo: `compile.sh`, `deploy.sh`, `deploy_key.enc`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!
    At this point you should have 3 files checked in to your repo: `compile.sh` `deploy_key.enc`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!

    ## See it in action

    I use basically this exact setup for https://domenic.github.io/zones/. The relevant files are:

    - https://github.com/domenic/zones/blob/master/.travis.yml
    - https://github.com/domenic/zones/blob/master/deploy.sh
    - https://github.com/domenic/zones/blob/master/deploy_key.enc
    I use basically this exact setup for https://github.com/wicg/origin-policy. The relevant files are:

    (I have inlined the compile script into `deploy.sh`, so there is no separate `compile.sh`.)
    - https://github.com/WICG/origin-policy/blob/master/.travis.yml
    - https://github.com/WICG/origin-policy/blob/master/Makefile (so I could use `make ci` instead of `bash ./compile.sh`)
    - https://github.com/WICG/origin-policy/blob/master/deploy_key.enc

    ## Licensing

  6. domenic revised this gist Jan 10, 2019. 1 changed file with 2 additions and 3 deletions.
    5 changes: 2 additions & 3 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -39,14 +39,13 @@ SHA=`git rev-parse --verify HEAD`

    # Clone the existing gh-pages for this repo into out/
    # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
    # Delete all existing contents except .git (we will re-create them)
    git clone $REPO out
    cd out
    git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
    find -maxdepth 1 ! -name .git ! -name . | xargs rm -rf
    cd ..

    # Clean out existing contents
    rm -rf out/**/* || exit 0

    # Run our compile script
    doCompile

  7. domenic revised this gist Nov 9, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -74,7 +74,7 @@ ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
    openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out ../deploy_key -d
    chmod 600 ../deploy_key
    eval `ssh-agent -s`
    ssh-add deploy_key
    ssh-add ../deploy_key

    # Now that we're all set up, we can push.
    git push $SSH_REPO $TARGET_BRANCH
  8. domenic revised this gist Jun 19, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -92,7 +92,7 @@ The trickiest part of all this is that you want to give Travis the ability to ru

    _NOTE: an earlier version of this guide recommended generating a GitHub personal access token and encrypting that. Although this is simpler, it is not a good idea in general, since it means any of your repository's collaborators would be able to edit the Travis build script to email them your access token, thus giving them access to all your repositories. The repository-specific deploy key approach is safer._

    First, [generate a new SSH key](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/). You should _not_ reuse existing SSH keys, and you should _not_ add the SSH key to your GitHub account.
    First, [generate a new SSH key](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/). You should _not_ reuse existing SSH keys, and you should _not_ add the SSH key to your GitHub account. Also, you must ensure that you do not include a passphrase (i.e., just press enter when asked for one).

    Next, add that deploy key to your repository at `https://github.com/<your name>/<your repo>/settings/keys`.

  9. domenic revised this gist Jan 8, 2018. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -157,4 +157,8 @@ I use basically this exact setup for https://domenic.github.io/zones/. The relev
    - https://github.com/domenic/zones/blob/master/deploy.sh
    - https://github.com/domenic/zones/blob/master/deploy_key.enc

    (I have inlined the compile script into `deploy.sh`, so there is no separate `compile.sh`.)
    (I have inlined the compile script into `deploy.sh`, so there is no separate `compile.sh`.)

    ## Licensing

    All code in the above post is licensed under the MIT License.
  10. domenic revised this gist May 1, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -63,7 +63,7 @@ fi

    # Commit the "changes", i.e. the new version.
    # The delta will show diffs between new and old versions.
    git add .
    git add -A .
    git commit -m "Deploy to GitHub Pages: ${SHA}"

    # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
  11. domenic revised this gist May 1, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -56,7 +56,7 @@ git config user.name "Travis CI"
    git config user.email "$COMMIT_AUTHOR_EMAIL"

    # If there are no changes to the compiled out (e.g. this is a README update) then just bail.
    if [ -z `git diff --exit-code` ]; then
    if git diff --quiet; then
    echo "No changes to the output on this push; exiting."
    exit 0
    fi
    @@ -71,8 +71,8 @@ ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
    ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
    ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
    ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
    openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy_key.enc -out deploy_key -d
    chmod 600 deploy_key
    openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../deploy_key.enc -out ../deploy_key -d
    chmod 600 ../deploy_key
    eval `ssh-agent -s`
    ssh-add deploy_key

  12. domenic revised this gist Jun 3, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -94,7 +94,7 @@ _NOTE: an earlier version of this guide recommended generating a GitHub personal

    First, [generate a new SSH key](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/). You should _not_ reuse existing SSH keys, and you should _not_ add the SSH key to your GitHub account.

    Next, add that deploy key to your repository at https://github.com/<your name>/<your repo>/settings/keys.
    Next, add that deploy key to your repository at `https://github.com/<your name>/<your repo>/settings/keys`.

    Now use the Travis client to encrypt the generated deploy key. The result should look something like this:

  13. domenic revised this gist Apr 27, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -117,7 +117,7 @@ Commit all changes to your .travis.yml.

    Make note of that encryption label, here `"0a6446eb3ae3"`. This can be public information; it just says which environment variables to use on the Travis server when decrypting this file.

    You should follow the instructions and commit `deploy_key.enc` to the repository. You should also add `deploy_key` to your `.gitignore`, or delete it.
    You should follow the instructions and commit `deploy_key.enc` to the repository. You should also add `deploy_key` to your `.gitignore`, or delete it. Ignore the bits about `.travis.yml`, however; we're going to do that part all custom-like.

    ## Create your `.travis.yml` file

  14. domenic revised this gist Apr 27, 2016. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -20,7 +20,6 @@ set -e # Exit with nonzero exit code if anything fails

    SOURCE_BRANCH="master"
    TARGET_BRANCH="gh-pages"
    EMAIL_TO_NOTIFY="[email protected]"

    function doCompile {
    ./compile.sh
    @@ -54,7 +53,7 @@ doCompile
    # Now let's go have some fun with the cloned repo
    cd out
    git config user.name "Travis CI"
    git config user.email "$EMAIL_TO_NOTIFY"
    git config user.email "$COMMIT_AUTHOR_EMAIL"

    # If there are no changes to the compiled out (e.g. this is a README update) then just bail.
    if [ -z `git diff --exit-code` ]; then
    @@ -131,8 +130,11 @@ script: bash ./deploy.sh
    env:
    global:
    - ENCRYPTION_LABEL: "<.... encryption label from previous step ....>"
    - COMMIT_AUTHOR_EMAIL: "[email protected]"
    ```
    The `$COMMIT_AUTHOR_EMAIL` variable will be used in the commits to gh-pages that Travis makes on your behalf.

    If your compile script depends on certain environment features, you might want to set up the environment using Travis's built-in abilities, e.g. by changing the language lines like so:

    ```yml
  15. domenic revised this gist Apr 27, 2016. 1 changed file with 90 additions and 47 deletions.
    137 changes: 90 additions & 47 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -16,100 +16,143 @@ Create a deploy script, call it `deploy.sh`, with the following contents:

    ```bash
    #!/bin/bash
    set -e # exit with nonzero exit code if anything fails
    set -e # Exit with nonzero exit code if anything fails

    SOURCE_BRANCH="master"
    TARGET_BRANCH="gh-pages"
    EMAIL_TO_NOTIFY="[email protected]"

    function doCompile {
    ./compile.sh
    }

    # Pull requests and commits to other branches shouldn't try to deploy, just build to verify
    if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
    echo "Skipping deploy; just doing a build."
    doCompile
    exit 0
    fi

    # Save some useful information
    REPO=`git config remote.origin.url`
    SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
    SHA=`git rev-parse --verify HEAD`

    # Clone the existing gh-pages for this repo into out/
    # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
    git clone $REPO out
    cd out
    git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
    cd ..

    # clear and re-create the out directory
    rm -rf out || exit 0;
    mkdir out;
    # Clean out existing contents
    rm -rf out/**/* || exit 0

    # run our compile script, discussed above
    ./compile.sh
    # Run our compile script
    doCompile

    # go to the out directory and create a *new* Git repo
    # Now let's go have some fun with the cloned repo
    cd out
    git init

    # inside this git repo we'll pretend to be a new user
    git config user.name "Travis CI"
    git config user.email "<you>@<your-email>"

    # The first and only commit to this new Git repo contains all the
    # files present with the commit message "Deploy to GitHub Pages".
    git add .
    git commit -m "Deploy to GitHub Pages"
    git config user.email "$EMAIL_TO_NOTIFY"

    # Force push from the current repo's master branch to the remote
    # repo's gh-pages branch. (All previous history on the gh-pages branch
    # will be lost, since we are overwriting it.) We redirect any output to
    # /dev/null to hide any sensitive credential data that might otherwise be exposed.
    git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1
    ```

    You can run this deploy script locally if you like, with
    # If there are no changes to the compiled out (e.g. this is a README update) then just bail.
    if [ -z `git diff --exit-code` ]; then
    echo "No changes to the output on this push; exiting."
    exit 0
    fi

    ```
    GH_TOKEN=<your password> GH_REF=github.com/<your name>/<your repo>.git ./deploy.sh
    # Commit the "changes", i.e. the new version.
    # The delta will show diffs between new and old versions.
    git add .
    git commit -m "Deploy to GitHub Pages: ${SHA}"

    # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc
    ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
    ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
    ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
    ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
    openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy_key.enc -out deploy_key -d
    chmod 600 deploy_key
    eval `ssh-agent -s`
    ssh-add deploy_key

    # Now that we're all set up, we can push.
    git push $SSH_REPO $TARGET_BRANCH
    ```

    But that's no fun. We want this to happen automatically every time you push. To do that, we'll use Travis CI.
    This deploy script depends on an encrypted deploy key file, `deploy_key.enc`, which we will discuss shortly. The basic idea is that Travis stores a couple environment variables for you, not checked in to your repo, which allow the script to decrypt `deploy_key.enc`, which *is* checked in to your repo.

    ## Sign up for Travis and add your project

    Get an account at https://travis-ci.org/. Turn on Travis for your repository in question, using the Travis control panel.

    ## Get encrypted credentials

    The trickiest part of all this is that you want to give Travis the ability to run your deploy script and push changes to gh-pages, without checking in the necessary credentials to your repo. The solution for this is to use Travis's [encryption support](http://docs.travis-ci.com/user/encryption-keys/).
    The trickiest part of all this is that you want to give Travis the ability to run your deploy script and push changes to gh-pages, without checking in the necessary credentials to your repo. The solution for this is to use Travis's [encrypted file support](https://docs.travis-ci.com/user/encrypting-files/).

    We'll generate a GitHub personal access token (essentially an application-specific password) and encrypt it, then put the encrypted version in our `.travis.yml` file. Then we can check in the `.travis.yml` file with no issues.
    _NOTE: an earlier version of this guide recommended generating a GitHub personal access token and encrypting that. Although this is simpler, it is not a good idea in general, since it means any of your repository's collaborators would be able to edit the Travis build script to email them your access token, thus giving them access to all your repositories. The repository-specific deploy key approach is safer._

    First, generate a token at https://github.com/settings/applications
    First, [generate a new SSH key](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/). You should _not_ reuse existing SSH keys, and you should _not_ add the SSH key to your GitHub account.

    Then, install the Travis client and do
    Next, add that deploy key to your repository at https://github.com/<your name>/<your repo>/settings/keys.

    Now use the Travis client to encrypt the generated deploy key. The result should look something like this:

    ```
    travis encrypt GH_TOKEN=<secret token here>
    ```
    $ travis encrypt-file deploy_key
    encrypting deploy_key for domenic/travis-encrypt-file-example
    storing result as deploy_key.enc
    storing secure env variables for decryption
    This will give you a very long line like
    Please add the following to your build script (before_install stage in your .travis.yml, for instance):
    openssl aes-256-cbc -K $encrypted_0a6446eb3ae3_key -iv $encrypted_0a6446eb3ae3_key -in super_secret.txt.enc -out super_secret.txt -d
    Pro Tip: You can add it automatically by running with --add.
    Make sure to add deploy_key.enc to the git repository.
    Make sure not to add deploy_key to the git repository.
    Commit all changes to your .travis.yml.
    ```
    secure: "<.... encrypted data ....>"
    ```

    If you don't want to install Ruby/RubyGems and such, there are reports that the [travis-encrypt](http://npmjs.org/travis-encrypt) npm package works just as well.
    Make note of that encryption label, here `"0a6446eb3ae3"`. This can be public information; it just says which environment variables to use on the Travis server when decrypting this file.

    You should follow the instructions and commit `deploy_key.enc` to the repository. You should also add `deploy_key` to your `.gitignore`, or delete it.

    ## Create your `.travis.yml` file

    With all this in hand, you can create a `.travis.yml` file. It should look like this:

    ```yml
    language: generic # don't install any environment

    script: bash ./deploy.sh
    env:
    global:
    - GH_REF: github.com/<your name>/<your repo>.git
    - secure: "<.... encrypted data from above ....>"
    - ENCRYPTION_LABEL: "<.... encryption label from previous step ....>"
    ```
    If your compile script depends on certain environment features, you might want to set up the environment using Travis's built-in abilities, e.g. by adding lines like these:
    If your compile script depends on certain environment features, you might want to set up the environment using Travis's built-in abilities, e.g. by changing the language lines like so:
    ```yml
    language: node_js
    node_js:
    - "0.10"
    - stable
    ```
    (In this case, [by default](http://docs.travis-ci.com/user/languages/javascript-with-nodejs/) Travis will install Node.js 0.10, then run `npm install`.)
    (In this case, [by default](http://docs.travis-ci.com/user/languages/javascript-with-nodejs/) Travis will install the latest stable Node.js, then run `npm install`.)

    ## Finishing up

    At this point you should have 2-3 files checked in to your repo: `compile.sh`, `deploy.sh`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!
    At this point you should have 3-4 files checked in to your repo: `compile.sh`, `deploy.sh`, `deploy_key.enc`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!

    ## See it in action

    I use basically this exact setup for http://www.w3.org/2001/tag/doc/promises-guide (which is hosted on gh-pages; the w3.org URL is a proxy to that). The relevant files are:
    I use basically this exact setup for https://domenic.github.io/zones/. The relevant files are:

    - https://github.com/w3ctag/promises-guide/blob/master/.travis.yml
    - https://github.com/w3ctag/promises-guide/blob/master/deploy-gh-pages.sh
    - https://github.com/domenic/zones/blob/master/.travis.yml
    - https://github.com/domenic/zones/blob/master/deploy.sh
    - https://github.com/domenic/zones/blob/master/deploy_key.enc

    (I have inlined the compile script into the latter, so there is no separate `compile.sh`.)
    (I have inlined the compile script into `deploy.sh`, so there is no separate `compile.sh`.)
  16. domenic revised this gist Jan 16, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -77,6 +77,8 @@ This will give you a very long line like
    secure: "<.... encrypted data ....>"
    ```

    If you don't want to install Ruby/RubyGems and such, there are reports that the [travis-encrypt](http://npmjs.org/travis-encrypt) npm package works just as well.

    ## Create your `.travis.yml` file

    With all this in hand, you can create a `.travis.yml` file. It should look like this:
  17. domenic revised this gist Jan 16, 2015. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -89,6 +89,16 @@ env:
    - secure: "<.... encrypted data from above ....>"
    ```
    If your compile script depends on certain environment features, you might want to set up the environment using Travis's built-in abilities, e.g. by adding lines like these:
    ```yml
    language: node_js
    node_js:
    - "0.10"
    ```
    (In this case, [by default](http://docs.travis-ci.com/user/languages/javascript-with-nodejs/) Travis will install Node.js 0.10, then run `npm install`.)

    ## Finishing up

    At this point you should have 2-3 files checked in to your repo: `compile.sh`, `deploy.sh`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!
  18. domenic revised this gist Jan 16, 2015. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -33,13 +33,15 @@ git init
    git config user.name "Travis CI"
    git config user.email "<you>@<your-email>"

    # the first and only commit to this new Git repo contains all the files present with the commit message "Deploy to GitHub Pages"
    # The first and only commit to this new Git repo contains all the
    # files present with the commit message "Deploy to GitHub Pages".
    git add .
    git commit -m "Deploy to GitHub Pages"

    # force push from the current repo's master branch to the remote repo's gh-pages branch
    # (all previous history on the gh-pages branch will be lost, since we are overwriting it)
    # redirect any output to /dev/null to hide any sensitive credential data that might be exposed
    # Force push from the current repo's master branch to the remote
    # repo's gh-pages branch. (All previous history on the gh-pages branch
    # will be lost, since we are overwriting it.) We redirect any output to
    # /dev/null to hide any sensitive credential data that might otherwise be exposed.
    git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1
    ```

  19. domenic revised this gist Jan 16, 2015. 1 changed file with 14 additions and 2 deletions.
    16 changes: 14 additions & 2 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -16,18 +16,30 @@ Create a deploy script, call it `deploy.sh`, with the following contents:

    ```bash
    #!/bin/bash
    set -e
    set -e # exit with nonzero exit code if anything fails

    # clear and re-create the out directory
    rm -rf out || exit 0;
    mkdir out;

    # run our compile script, discussed above
    ./compile.sh

    # go to the out directory and create a *new* Git repo
    cd out
    git init
    git config user.name "Travis-CI"

    # inside this git repo we'll pretend to be a new user
    git config user.name "Travis CI"
    git config user.email "<you>@<your-email>"

    # the first and only commit to this new Git repo contains all the files present with the commit message "Deploy to GitHub Pages"
    git add .
    git commit -m "Deploy to GitHub Pages"

    # force push from the current repo's master branch to the remote repo's gh-pages branch
    # (all previous history on the gh-pages branch will be lost, since we are overwriting it)
    # redirect any output to /dev/null to hide any sensitive credential data that might be exposed
    git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1
    ```

  20. domenic revised this gist Jan 16, 2015. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,9 @@ This is a set up for projects which want to check in only their source files, bu

    You want a script that does a local compile to e.g. an `out/` directory. Let's call this `compile.sh` for our purposes, but for your project it might be `npm build` or `gulp make-docs` or anything similar.

    Check this in to your project.
    The `out/` directory should contain everything you want deployed to `gh-pages`. That almost always includes an `index.html`.

    Check this script in to your project.

    ## Create a deploy script

  21. domenic revised this gist Jan 16, 2015. 1 changed file with 4 additions and 2 deletions.
    6 changes: 4 additions & 2 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -81,5 +81,7 @@ At this point you should have 2-3 files checked in to your repo: `compile.sh`, `

    I use basically this exact setup for http://www.w3.org/2001/tag/doc/promises-guide (which is hosted on gh-pages; the w3.org URL is a proxy to that). The relevant files are:

    https://github.com/w3ctag/promises-guide/blob/master/.travis.yml
    https://github.com/w3ctag/promises-guide/blob/master/deploy-gh-pages.sh
    - https://github.com/w3ctag/promises-guide/blob/master/.travis.yml
    - https://github.com/w3ctag/promises-guide/blob/master/deploy-gh-pages.sh

    (I have inlined the compile script into the latter, so there is no separate `compile.sh`.)
  22. domenic revised this gist Jan 16, 2015. 1 changed file with 9 additions and 2 deletions.
    11 changes: 9 additions & 2 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -66,7 +66,7 @@ secure: "<.... encrypted data ....>"
    With all this in hand, you can create a `.travis.yml` file. It should look like this:

    ```yml
    script: bash ./deploy-gh-pages.sh
    script: bash ./deploy.sh
    env:
    global:
    - GH_REF: github.com/<your name>/<your repo>.git
    @@ -75,4 +75,11 @@ env:
    ## Finishing up
    At this point you should have 2-3 files checked in to your repo: `compile.sh`, `deploy.sh`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!
    At this point you should have 2-3 files checked in to your repo: `compile.sh`, `deploy.sh`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!

    ## See it in action

    I use basically this exact setup for http://www.w3.org/2001/tag/doc/promises-guide (which is hosted on gh-pages; the w3.org URL is a proxy to that). The relevant files are:

    https://github.com/w3ctag/promises-guide/blob/master/.travis.yml
    https://github.com/w3ctag/promises-guide/blob/master/deploy-gh-pages.sh
  23. domenic created this gist Jan 16, 2015.
    78 changes: 78 additions & 0 deletions auto-deploy.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    # Auto-deploying built products to gh-pages with Travis

    This is a set up for projects which want to check in only their source files, but have their gh-pages branch automatically updated with some compiled output every time they push.

    ## Create a compile script

    You want a script that does a local compile to e.g. an `out/` directory. Let's call this `compile.sh` for our purposes, but for your project it might be `npm build` or `gulp make-docs` or anything similar.

    Check this in to your project.

    ## Create a deploy script

    Create a deploy script, call it `deploy.sh`, with the following contents:

    ```bash
    #!/bin/bash
    set -e

    rm -rf out || exit 0;
    mkdir out;
    ./compile.sh

    cd out
    git init
    git config user.name "Travis-CI"
    git config user.email "<you>@<your-email>"
    git add .
    git commit -m "Deploy to GitHub Pages"
    git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages > /dev/null 2>&1
    ```

    You can run this deploy script locally if you like, with

    ```
    GH_TOKEN=<your password> GH_REF=github.com/<your name>/<your repo>.git ./deploy.sh
    ```

    But that's no fun. We want this to happen automatically every time you push. To do that, we'll use Travis CI.

    ## Sign up for Travis and add your project

    Get an account at https://travis-ci.org/. Turn on Travis for your repository in question, using the Travis control panel.

    ## Get encrypted credentials

    The trickiest part of all this is that you want to give Travis the ability to run your deploy script and push changes to gh-pages, without checking in the necessary credentials to your repo. The solution for this is to use Travis's [encryption support](http://docs.travis-ci.com/user/encryption-keys/).

    We'll generate a GitHub personal access token (essentially an application-specific password) and encrypt it, then put the encrypted version in our `.travis.yml` file. Then we can check in the `.travis.yml` file with no issues.

    First, generate a token at https://github.com/settings/applications

    Then, install the Travis client and do

    ```
    travis encrypt GH_TOKEN=<secret token here>
    ```

    This will give you a very long line like

    ```
    secure: "<.... encrypted data ....>"
    ```

    ## Create your `.travis.yml` file

    With all this in hand, you can create a `.travis.yml` file. It should look like this:

    ```yml
    script: bash ./deploy-gh-pages.sh
    env:
    global:
    - GH_REF: github.com/<your name>/<your repo>.git
    - secure: "<.... encrypted data from above ....>"
    ```
    ## Finishing up
    At this point you should have 2-3 files checked in to your repo: `compile.sh`, `deploy.sh`, and `.travis.yml`. If you've also told Travis about your repo, then the first time you push to GitHub with these changes, it will automatically compile and deploy your source!