6

I can't figure out how to automatically deploy newly pushed commits of Cloud Functions either from Cloud Source Control or from GitHub directly. I have found a similar solution by creating another function and GitHub webhook, but since Functions can't SSH (and have SSH keys installed), it is only working with Public Repos. (https://cloud.google.com/community/tutorials/cloud-functions-github-auto-deployer)

Any ideas how to achieve this? Thanks

jirizavadil
  • 71
  • 1
  • 4

2 Answers2

7

You could use Google Cloud Builder to achieve this goal. Create a trigger on your repository, and the triggered build deploys the new code to Google Cloud Function.

I made a quick example: https://github.com/Philmod/auto-deploy-gcf

Cheers, Philmod

Philmod
  • 171
  • 5
5

I managed to find a reasonable workaround for this issue. I hope that it helps others struggling with this same issue.

Required setup

Before you get started with these steps, you'll need to setup SSH keys on your CI/CD system. This is what grants your build system ssh access to your private repo. Here are a couple of articles which discuss how to do that.

You'll also need to install the package via git+ssh so that it's included in your package.json (and optionally yarn.lock).

yarn add git+ssh://git@gitlab.com:erichiggins/top_secret.git

At this point, you should see the following entry in your package.json:

...
"dependencies": {
  "top_secret": "git+ssh://git@gitlab.com:erichiggins/top_secret.git"
},
...

Installing the package (twice)

Here are the commands I run inside a shell script on my CI/CD setup, just before the deploy stage, in order to install private repos as packages using git+ssh. I'll use a fake package name of top_secret for my example to make it more clear.

(I'm using yarn and GitLab in this example, but the same applies to npm and GitHub if you prefer.)

yarn install
cd node_modules/top_secret
yarn pack
mv top_secret-v*.tgz ../../
cd ../../
yarn add file:top_secret-v1.0.0.tgz

Note: The yarn pack command will produce a filename that includes a version number, but you can't yarn add with a wildcard (*). I've run into issues using yarn pack --filename with a generic, version-less filename, so you may need to either hardcode this or find a creative solution that uses the filename generated by yarn pack.

Results

If you try running these two commands locally, you'll notice that you end up with just one new entry for top_secret inside the dependencies section of your package.json file, which will look like this:

"top_secret": "file:node_modules/top_secret",

Here's what's happening:

  1. You're installing the private repo as a package via git+ssh on a system that has access.
  2. You're repackaging it from your node_modules/ directory into a tarball file (.tgz).
  3. You're installing the same package from a local tarball file using file:
  4. Because the package name is identical, it replaces the git+ssh entry in package.json with the file: entry.

Your deployment to Cloud Functions should now proceed without any issues, and with your private package included. Good luck and let me know if you have any problems with these instructions -- I'd be happy to correct any mistakes and rewrite anything that is unclear.

Alternative approach

If you don't mind the extra effort or the private repo does not change frequently enough to justify the additional complexity in your CI/CD, you can also use npm pack/yarn pack to create a tarball file, run the same yarn add file:... command listed above to modify your package.json and simply check the tarball file into your repo.

Note: Be mindful that if the repo you're checking the tarball file into is public, the source of your private repo/package will also be made public.

References:

erichiggins
  • 586
  • 1
  • 4
  • 9
  • 1
    I can't seem to get this to work - the deploy fails every time because it's not uploading the node_modules folder and therefore it can't find my private module. What are you using to deploy the function? – Tom Mar 22 '18 at 13:01
  • @Tom This code snippet may need an adjustment -- I seem to recall it working for me, then having an issue later. I'll go through it today and fix it, then let you know what changes are needed. Hopefully we can get it working for you. – erichiggins Mar 23 '18 at 14:39
  • @Tom I've updated the instructions to reflect a solution that should work and added a simpler alternative solution. Hope this helps! – erichiggins Mar 23 '18 at 19:21
  • I use PACKED=`ls ${NAME}-*.tgz` from a generic script. However, if I start with an empty node_modules directory, `npm install ./${PACKED} --ignore-scripts --offline` downloads half the internet when all I want to do is edit package.json – Nicholas Albion Jul 05 '18 at 11:45
  • sed -E -i -e "s/\"${NAME}\": ?\"[^\"]*\"(,?)$/\"${NAME}\": \"file:${PACKED}\"\1/" package.json – Nicholas Albion Jul 05 '18 at 12:34
  • @Philmod answer below is more elegant, given the platform in question is Cloud Functions. – faridghar Jun 04 '20 at 08:21