int(178)
array(6) {
  [0]=>
  object(WP_Post)#8937 (39) {
    ["ID"]=>
    int(105)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_date_gmt"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_content"]=>
    string(0) ""
    ["post_title"]=>
    string(4) "Home"
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(4) "home"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=105"
    ["menu_order"]=>
    int(1)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(105)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(1) "2"
    ["object"]=>
    string(4) "page"
    ["type"]=>
    string(9) "post_type"
    ["type_label"]=>
    string(4) "Page"
    ["url"]=>
    string(31) "https://www.primitivesense.com/"
    ["title"]=>
    string(4) "Home"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
  [1]=>
  object(WP_Post)#8936 (39) {
    ["ID"]=>
    int(101)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_date_gmt"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_content"]=>
    string(1) " "
    ["post_title"]=>
    string(0) ""
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(3) "101"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=101"
    ["menu_order"]=>
    int(2)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(101)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(2) "12"
    ["object"]=>
    string(4) "page"
    ["type"]=>
    string(9) "post_type"
    ["type_label"]=>
    string(4) "Page"
    ["url"]=>
    string(53) "https://www.primitivesense.com/we-are-primitivesense/"
    ["title"]=>
    string(5) "About"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
  [2]=>
  object(WP_Post)#8935 (39) {
    ["ID"]=>
    int(112)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-03-19 20:56:47"
    ["post_date_gmt"]=>
    string(19) "2019-03-19 20:56:47"
    ["post_content"]=>
    string(0) ""
    ["post_title"]=>
    string(8) "Projects"
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(8) "projects"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=112"
    ["menu_order"]=>
    int(3)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(112)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(3) "112"
    ["object"]=>
    string(6) "custom"
    ["type"]=>
    string(6) "custom"
    ["type_label"]=>
    string(11) "Custom Link"
    ["title"]=>
    string(8) "Projects"
    ["url"]=>
    string(9) "/projects"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
  [3]=>
  object(WP_Post)#8934 (39) {
    ["ID"]=>
    int(102)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_date_gmt"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_content"]=>
    string(1) " "
    ["post_title"]=>
    string(0) ""
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(3) "102"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=102"
    ["menu_order"]=>
    int(4)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(102)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(2) "10"
    ["object"]=>
    string(4) "page"
    ["type"]=>
    string(9) "post_type"
    ["type_label"]=>
    string(4) "Page"
    ["url"]=>
    string(39) "https://www.primitivesense.com/writing/"
    ["title"]=>
    string(7) "Writing"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
  [4]=>
  object(WP_Post)#8933 (39) {
    ["ID"]=>
    int(315)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_date_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content"]=>
    string(0) ""
    ["post_title"]=>
    string(7) "Process"
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(7) "process"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=315"
    ["menu_order"]=>
    int(5)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(315)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(3) "315"
    ["object"]=>
    string(6) "custom"
    ["type"]=>
    string(6) "custom"
    ["type_label"]=>
    string(11) "Custom Link"
    ["title"]=>
    string(7) "Process"
    ["url"]=>
    string(12) "/our-process"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
  [5]=>
  object(WP_Post)#8932 (39) {
    ["ID"]=>
    int(104)
    ["post_author"]=>
    string(1) "2"
    ["post_date"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_date_gmt"]=>
    string(19) "2019-02-18 18:15:04"
    ["post_content"]=>
    string(1) " "
    ["post_title"]=>
    string(0) ""
    ["post_excerpt"]=>
    string(0) ""
    ["post_status"]=>
    string(7) "publish"
    ["comment_status"]=>
    string(6) "closed"
    ["ping_status"]=>
    string(6) "closed"
    ["post_password"]=>
    string(0) ""
    ["post_name"]=>
    string(3) "104"
    ["to_ping"]=>
    string(0) ""
    ["pinged"]=>
    string(0) ""
    ["post_modified"]=>
    string(19) "2019-04-12 13:11:30"
    ["post_modified_gmt"]=>
    string(19) "2019-04-12 12:11:30"
    ["post_content_filtered"]=>
    string(0) ""
    ["post_parent"]=>
    int(0)
    ["guid"]=>
    string(37) "https://www.primitivesense.com/?p=104"
    ["menu_order"]=>
    int(6)
    ["post_type"]=>
    string(13) "nav_menu_item"
    ["post_mime_type"]=>
    string(0) ""
    ["comment_count"]=>
    string(1) "0"
    ["filter"]=>
    string(3) "raw"
    ["db_id"]=>
    int(104)
    ["menu_item_parent"]=>
    string(1) "0"
    ["object_id"]=>
    string(1) "6"
    ["object"]=>
    string(4) "page"
    ["type"]=>
    string(9) "post_type"
    ["type_label"]=>
    string(4) "Page"
    ["url"]=>
    string(54) "https://www.primitivesense.com/contact-primitivesense/"
    ["title"]=>
    string(7) "Contact"
    ["target"]=>
    string(0) ""
    ["attr_title"]=>
    string(0) ""
    ["description"]=>
    string(0) ""
    ["classes"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["xfn"]=>
    string(0) ""
    ["childItems"]=>
    NULL
    ["active"]=>
    bool(false)
  }
}

PrimitiveSense, specialists in communicating technical Web Design & Development based in Newcastle upon Tyne.

Get In Touch

Testing & deploying Google Cloud Functions in BitBucket Pipelines

Cloud Functions & BitBucket

The below will run you through on how to setup BitBucket Pipelines to test and deploy your Google Cloud Function. Compared to AWS we have found the documentation for Google Cloud Functions and the best practices for deployment from CI is lacking and wanted to document it to help the next soul.

The below assumes you have of:

  • A BitBucket account
  • A Google Cloud Account
  • Experience with BitBucket Pipelines
  • A Google Cloud function to deploy (They have a nice sample one here if not (https://cloud.google.com/functions/docs/quickstart)
  • A Project Setup in the Google Cloud Console
  • Docker

The below will take us through the following

  • Creating a service account to deploy the function
  • Exporting a service account key file which is used to authorise the deployment of the function
  • Creating a custom role with only the permissions required to deploy the function
  • Configuring BitBucket Pipelines

Firstly we need to create a service account is necessary for deploying the funtion (read more here on what it actually is – https://cloud.google.com/iam/docs/creating-managing-service-account-keys). In the Google Cloud Console, ensure you have you have selected the project you wish to work within in the top navigation bar.

In navigation menu open the service account page – IAM & admin > Service accounts. Click + CREATE SERVICE ACCOUNT at the top.

  1. Give your service account a meaninfuly name such as BitBucket CI Deployment.
  2. Click next and then add the Service Account Permissions, add the role of Service Account User.
  3. Click next and you will come to the final screen.
  4. Click create key and a JSON key file will be downloaded and keep this safe
  5. Click Done

This JSON key key file is your service account JSON key file and this is what we will use to authenticate to in order to deploy the cloud function.

We will now create the custom role.. Go to IAM & admin > Roles then click + Create Role at the top and Give this role the name of BitBucket CI Deployment Role.

Then add the following permissions


cloudfunctions.functions.get
cloudfunctions.functions.sourceCodeSet
cloudfunctions.operations.get
cloudfunctions.operations.list

Next we need to associate this role to the service account created above.

  1. Go to IAM & admin > IAM.
  2. Find the Service Account you created above named BitBucket CI Deployment and click edit.
  3. Search for the created role of BitBucket CI Deployment Role and apply.
  4. Click save.

Now we’ve created our user and the associated roles we’re ready to start configuring BitBucketPipe Lines.

First create a file named service-account.dist.json. In the root of your project and then copy the following contents


{
    "type": "service_account",
    "project_id": "$GCLOUD_PROJECT_ID",
    "private_key_id": "$GCLOUD_PRIVATE_KEY_ID",
    "private_key": "$GCLOUD_PRIVATE_KEY",
    "client_email": "$GCLOUD_EMAIL",
    "client_id": "$GCLOUD_CLIENT_ID",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "$GCLOUD_CERT_URL"
  }

This file above will represent the structure in JSON file that was downloaded previously when creating the service account. We will be using the BitBucket Repository / Environment variables to store the credentials from your service account JSON file.

Head over to your BitBucket Repo and go to Settings > Repository Variables. Add the following environment variables.


GCLOUD_PROJECT_ID
GCLOUD_PRIVATE_KEY_ID
GCLOUD_PRIVATE_KEY
GCLOUD_EMAIL
GCLOUD_CLIENT_ID
GCLOUD_CERT_URL

The values for each of these you will take from the Service JSON Key file that you downloaded earlier. So for example you will take the value of project_id and input it into GCLOUD_PROJECT_ID.
Now create the file bitbucket-pipelines.yml with the following contents:


stepdefinitions:
- tests: &tests
    name: Tests
    image: node:8.15-jessie
    caches:
    - node
    script:
    - npm install
    - npm test
pipelines:
  default:
  - step: *tests
  branches:
    master:
    - step: *tests
    - step:
        name: Deploy to Production
        deployment: production   # can be test, staging or production
        trigger: manual
        image: google/cloud-sdk:234.0.0
        script:
        - apt-get -y install gettext-base
        - envsubst < service-account.dist.json > service-account.json
        - gcloud auth activate-service-account --key-file=service-account.json
        - gcloud functions deploy MyFunction --runtime nodejs8 --trigger-http --project 

First we create a test stepdefinition. These are useful as they allow us to define one step without have to repeat them for each particular branch. This test uses a Node Image to install the dependencies and then run the tests.

In the pipelines node, we create a default node which simply states that for every branch run the test step. In the master node we simply invoke the test step and then create a new new step that deploys our Google Cloud Function. We set this as a deployment step (read more here – https://confluence.atlassian.com/bitbucket/bitbucket-deployments-940695276.html) and define that we have to deploy this manually.

We then use a Docker image of google/cloud-sdk which provides us an image which has all the tools required to deploy the Cloud SDK commands.

We install gettext-base which allows us use envsubst which interpolates the environment variables set up in BitBucket Repository Variables into service-account.dist.json and then outputs this to service-account.json.

The script then authenticates with Google Cloud using the service-account.json file, which will contain the values of your service account created above and then simply deploys the function.

Useful Resources

https://cloud.google.com/functions/docs/reference/iam/roles#additional-configuration
https://cloud.google.com/functions/docs/quickstart https://cloud.google.com/iam/docs/understanding-service-accounts

That’s it! If you have any issues please feel free to reach out to helpme@primitivesense.com and if your looking for a job (even remote) ping us at jobs@primitivesense.com.