Creating deployment artifacts every time you check something in to GitHub gets old fast. Jenkins can handle that for you. This post walks through using Jenkins with the tibcli utility to deploy Node.js apps to TIBCO Cloud Integration every time updates are pushed to GitHub.
Some assumptions #
A few assumptions going in, which should cover most readers. If you have questions, post them at the TIBCO Community.
- You’re using GitHub to store your projects and you’ve got a repo for your Node.js app
- You’re familiar with Jenkins
- You’ve modeled an API Spec on TIBCO Cloud Integration
- You’ve downloaded the tibcli utility from TIBCO Cloud Integration and the user that will run the JENKINS server has to login with the tibcli at least once
Python #
Wait, Python?! We are doing Node.js, don’t worry. The tibcli utility works in interactive mode, so we’ll use a Python script to automate the build tasks and push the app to TIBCO Cloud Integration. You’ll need the pexpect module:
sudo pip install pexpectCopy and modify the script below. Save it somewhere memorable — I named mine server.py.
### Imports
import sys
import os
import shutil
import zipfile
import pexpect
### Constants
DEPLOYMENT_PATH = './deployment'
APP_NAME = sys.argv[1]
TIBCLI_PATH = sys.argv[2]
APP_PUSH_CMD = 'tibcli app push'
PASSWORD = sys.argv[3]
def replace_unicode(cmd_output):
cmd_output = cmd_output.replace('\b', '')
cmd_output = cmd_output.replace('\x1b', '')
cmd_output = cmd_output.replace('[32m', '')
cmd_output = cmd_output.replace('[31m', '')
cmd_output = cmd_output.replace('[0m', '')
return cmd_output
def with_interactive_login(child):
cmd_output = str(child.before)
child.sendline(PASSWORD)
cmd_output += str(child.after)
return cmd_output
def zipdir(path, ziph):
for root, dirs, files in os.walk(path):
for file in files:
ziph.write(os.path.join(root, file))
if not os.path.exists(DEPLOYMENT_PATH):
os.makedirs(DEPLOYMENT_PATH)
if os.path.exists('./' + APP_NAME + '/node_modules'):
shutil.rmtree('./' + APP_NAME + '/node_modules')
shutil.copy2('manifest.json',DEPLOYMENT_PATH + '/manifest.json')
zipf = zipfile.ZipFile(DEPLOYMENT_PATH + '/app.zip', 'w', zipfile.ZIP_DEFLATED)
zipdir('./' + APP_NAME, zipf)
zipf.close()
cmd_output = ''
child = pexpect.spawn(TIBCLI_PATH + '/' + APP_PUSH_CMD,cwd=DEPLOYMENT_PATH)
if child.expect(["Password", pexpect.EOF, pexpect.TIMEOUT], timeout=300) == 0:
cmd_output = with_interactive_login(child)
else:
print("command time out occur")
cmd_output += str(child.before)
cmd_output = replace_unicode(cmd_output)
print(cmd_output)Getting your butler #
Jenkins is a self-contained, open source automation server for building, testing, and deploying software. For this tutorial I went with the Long-term Support Release (LTS). You can download and install Jenkins for just about any OS, and there’s a Docker container available too.
Note: Securing your Jenkins installation is definitely worth doing. There are plenty of good tutorials on that, so I’ll skip it here.
Plugins #
If you’ve installed the latest version of Jenkins there is only one additional plugin we need:
- NodeJS Plugin
Install it via Manage Jenkins -> Manage Plugins and search on the Available tab.
Connect to GitHub #
We need Jenkins to know about your GitHub repos. Rather than polling, we’ll have GitHub tell Jenkins when updates happen via webhooks. You’ll need a Personal Access Token from GitHub (Settings menu) with access to:
- repo
- notifications
- user
Save that token — you’ll need it shortly.
Back in Jenkins, go to Credentials -> System and add two Global credentials:
- The first is for the GitHub Plug-in in Jenkins
- Kind: Secret text
- Scope: Global
- Secret: The Personal Access Token from GitHub
- ID: Something to remember this credential by
- Description: A good description is helpful to remember this credential by
- The second will be for the Jenkins project accessing your GitHub repo
- Kind: Username with password
- Scope: Global
- Username: Your GitHub username
- Password: The Personal Access Token from GitHub
- ID: Something to remember this credential by
- Description: A good description is helpful to remember this credential by
Go to Manage Jenkins -> Configure System, scroll to the GitHub section, select Add GitHub server and pick the first credential from the dropdown. Hit Test Connection to verify, then Save.
Adding Node.js to Jenkins #
Go to Manage Jenkins -> Global Tool Configuration and scroll to the NodeJS section. The NodeJS plugin lets you install and manage different versions of Node.js for your builds. Add a new installation, keep install from nodejs.org selected, choose your version, and hit Save.
Setting up CI and CD #
Now for the actual pipeline. Add a New Item, give it a name, and select Freestyle project.
Source Code Management #
Select Git, paste your repository URL, and pick the second set of credentials you created earlier.
Build Triggers #
Choose GitHub hook trigger for GITScm polling. This injects a webhook into your repo so every new commit triggers a build.
Build Environments #
Check Provide Node & npm bin/ folder to PATH and select the Node.js version you configured.
Build #
Add a build step Execute shell with:
# Copy the deployment script to this folder
cp /path/to/server.py .
python server.py <YOUR APPNAME> <LOCATION OF TIBCLI> <YOUR PASSWORD>Post-build Actions #
Add Archive the artifacts with files set to deployment/** to keep your build artifacts. Then add Delete workspace when build is done to clean up.