Deploy Ghost GitHub Action

Hi everyone,

I’m trying to setup a github deploy ghost action following the documentation on the githubpage:

But either I’m blind or github changed their interface, but I cannot find the Settings -> Secrets left hand side menu option where I should setup the API keys.

Repository is private (theme is commercial so I didn’t want to make the code public), but this shouldn’t be an issue, as I’ve checked other public repositories of mine and I cannot find this option there.

Any hints how I can proceed? I managed to sync the theme (update + customizations) in the repo and now I only need to push it to live.


@dsecareanu I don’t think it’s fully available yet. I think you can sign up to the beta here or you can join GitHub’s developer program to get automatic access to things like this


Oh, my shattered hopes and dreams! :slight_smile:

Okies, will try the developer beta to see if this shows up in my account and download my repo and upload it manually meanwhile.

Thanks @Kevin!

Oh no! I didn’t realise that. If the repository is private you should be able to store your Ghost API keys in the repo rather than in a secret, fwiw?

No worries, all good. I’ve applied for Actions beta and got atomatically accepted so now I also have the Secrets option and can follow the standard documentation. But might be good to add a note in the docs for others as well.

Thanks! :slight_smile:

I’ve managed to complete the deployment process, but I got an error and not sure how to debug.


Node run failed with exit code 1

The details of the error:

Error [ThemeValidationError]: Theme is not compatible or contains errors.

155 at /home/runner/work/_actions/TryGhost/action-deploy-theme/v1.2.0/dist/index.js:6882:33

156 at processTicksAndRejections (internal/process/task_queues.js:89:5)

157 at async main (/home/runner/work/_actions/TryGhost/action-deploy-theme/v1.2.0/dist/index.js:1225:9) {

158 name: ‘ThemeValidationError’,

159 context: null,

160 type: ‘ThemeValidationError’,

161 details: {

162 checkedVersion: ‘3.x’,

163 name: ‘nubia’,

164 path: ‘/tmp/010e1476-8af7-4409-a443-3f51eb0326a7’,

165 version: ‘1.3.6’,

166 errors: [ [Object] ]

167 },

168 property: null,

169 help: null,

170 code: null,

171 id: ‘412dba80-f660-11e9-9206-dff5dc3ad8e3’


173##[error]Node run failed with exit code 1

Should I try to gscan it I guess?


I think I found the culprit:

Oops! You seemed to have used invalid Handlebars syntax. This mostly happens, when you use a helper that is not supported.
See the full list of available helpers here.

Affected files:

  • default.hbs: Parse error on line 32: …
-------------------^ Expecting ‘OPEN_INVERSE_CHAIN’, ‘INVERSE’, ‘OPEN_ENDBLOCK’, got ‘EOF’

But unsure what needs to change there. :slight_smile:

This is the line from default.hbs

<script src='{{ asset 'js/app.min.js' }}'></script>

Sounds like you might be missing a closing helper - can you share the full template?

Trying to debug it as the default.hbs file is identical with the theme original file (and the original theme passes the gscan test 100%, so it doesn’t give errors).

There should be something in other linked files (partials or assets maybe) as the process I went through when I implemented this was:

  • git init in the live theme (which was customized) directory
  • unpack the updated theme locally and git inited it as well
  • pushed the live theme into github repo
  • updated local theme with the changes from the live (configs, so had to manually solve some merging conflicts and I might have deleted something somewhere that wasn’t supposed to)
  • pushed the updated local to the github repo

Now the sync is failing, but the actual theme works fine.

But anyways, this is the full default.hbs file:

<!doctype html>
<html lang='{{ @site.lang }}'>
  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>

  <title>{{ meta_title }}</title>
  <meta name='viewport' content='width=device-width, initial-scale=1.0'>

  {{> compiled/inline-css }}

    var site_url                            = '{{@site.url}}',
        pagination_next_page_number         = '{{ }}',
        pagination_available_pages_number   = '{{ pagination.pages }}',
        pagination_loading_text             = '{{t "Loading" }}',
        pagination_more_posts_text          = '{{t "More Posts" }}',
        clipboard_copied_text               = '{{t "Link copied to clipboard" }}';

  {{ ghost_head }}
<body class='{{ body_class }}'>

  <div class='js-off-canvas-container c-off-canvas-container'>
    {{> header }}

    {{{ body }}}

    {{> footer}}

  <script src='{{ asset 'js/app.min.js' }}'></script>
  {{!-- Load instagram.js only in single post --}}
  {{#is 'post'}}<script src='{{ asset 'js/instagram.js' }}'></script>{{/is}}

  {{ ghost_foot }}

Found the culprit, the partials/social-icons.hbs file was messed up with double site.facebook entries and other minor errors (that’s why the references to lists in the error). :slight_smile: Now the flow worked. Thanks!

Excellent! I was just looking into this and I couldn’t see the same error on the gscan CLI, so I’ve pushed a little fix to gscan that makes sure that full detail is output on errors on the cli.

So if you do npm i -g gscan@latest and then gscan . --verbose inside your repo on your computer, you should see the error output the same as what appeared in the failing build.

I don’t use a local ghost development environment so this might work on the actual server in the theme folder, I guess. Yes, it works directly on server and result is:

$ gscan . --verbose
Checking theme compatibility...
✓ Your theme is compatible with Ghost 3.x
Get more help at
You can also check theme compatibility at

You can still run gscan locally without having a full local dev environment (as long as you have node & npm), by installing gscan on your machine:

npm install -g gscan@latest

And then running gscan in the folder where your theme files are:

gscan --fatal --verbose .

The --fatal flag only outputs errors that will stop Ghost accepting the theme, rather than general errors or warnings, and the --verbose flag outputs help info as well as the error.

Alterntively, it is possible to run gscan as part of your github action. There are 2 methods, that depend a bit on your ideal local setup and workflow.

Option 1 - using gscan as npm test

In the Casper repository, we have npm test configured to run gscan.

You can do this, by:

  1. adding gscan as a dev dependency to your theme npm install gscan --save-dev
  2. adding a test script to package.json, e.g.
"scripts": {
   "test": "gscan ."
  1. Configure the gscan command to work how you want, e.g. gscan --fatal . if you only want fatal errors.

Once this is setup, you can then add steps to your github action workflow .yml file to run npm test on every build, which will then fail before attempting to upload to Ghost.

The extra steps go between the checkout step, and the deploy step, like this:

      - uses: actions/checkout@master
      - name: Use Node.js 10
        uses: actions/setup-node@v1
          node-version: 10
      - name: install and test
        run: |
          npm install
          npm test
      - name: Deploy Ghost Theme
        uses: TryGhost/action-deploy-theme@v1.2.0

Now you can easily run npm test to check gscan before pushing, but the build will catch this if you forget.

Option 2 - use gscan directly in workflow

Option 2 is quicker, and should keep your build time down as well as we only ever install gscan - whereas if you have other dependencies, option 1 would install those too.

This time, we just edit the workflow .yml file, again to add 2 new steps between the checkout step and the deploy step:

      - uses: actions/checkout@master
      - name: Use Node.js 10
        uses: actions/setup-node@v1
          node-version: 10
      - name: Run gscan
        run: |
          npm install --global gscan@latest
          gscan --fatal --verbose $GITHUB_WORKSPACE
      - name: Deploy Ghost Theme
        uses: TryGhost/action-deploy-theme@v1.2.0

You can customise the gscan command - if you remove the --fatal flag gscan will error if there’s even the smallest compatibility issue - great for theme developers who want to publish their work, less great for people making 1 off themes who might not care.


Thanks a lot! :slight_smile:

Will look into these as I play more with the other Ghost installations and themes I have to update.

I installed node and npm locally now so I should be able to check it now.

I’ve just finished trying Ghost Action, it’s really a great tool, congratulations!
I certainly don’t go back to using the old procedures anymore.

Great thread, this has helped me a lot. Does anyone have an action that runs gulp before deploying, for example to minify files? I’m still new to github actions and trying to figure how to chain them together.

You don’t necessarily need an action, you can just add a step that does that. You can use prebuilt actions (with the using key), or you can run your own shell scripts / commands. That’s what Hannah did in option 2 for running gscan

Where do I put the minified files? Do I have the action create a new branch and then deploy from that?