GitHub Continuous deployment to a Raspberry Pi

raspberry-logo

So, Im still playing with the Raspberry Pi while working on the wackcoon project (more to come on that) and I have the need to work in a group.  Instead of just using SCP to get files over to my device, I wanted to be able to have my Raspberry Pi update whenever there was an update to the master branch of the node project I was working on.  This would facility being able to work with a remote team (where the pi is in my network) and theoretically, if I had multiple wackcoon devices (although I have not thought about how to implement that yet.

 

To accomplish this, we will need the following.

  • A GitHub hook on the repository
  • A node app on the pi listening for messages from GitHub
  • A way for the pi to be reached from the internet

Github hook

The first thing we want to do is set up a hook on our github repository.  To do this, go to your GitHub repository click on the settings tab –> Webhooks & services –> Add webhookpideploy1

 

In the Add webhook screen we need to add just a few things :

  • Payload URL –  This is where it will send the information to whenever events happen on your master branch.  I will show you how I set this up in the next step.
  • Content type – You can select application/json (what I am using) or  application/x-www-form-urlencoded
  • Secret (not required) – this is a secret you supply to verify on the sender
  • Events – Which events you want to trigger this hook. The default is the push event and is what I am using for this example but there are many to choose from depending on your needs

(NOTE:  To learn about webhooks in depth, check out the documentation https://developer.github.com/webhooks/ )

Fill out this information and click on Add webhook

pideploy2

 

A node app on the Pi

The next step is to set up an application on the pi that will receive the event.  You can see what I have set up by looking at the wackcoon-hook project

https://github.com/DanielEgan/wackcoon-hook

All of the code is in the app.js file (check project for full code) .  It is a node site using express that has a route for a post on /payload.   So for instance, in this app it will be listening on http://localhost:5000/payload  (yes… localhost, we will get to that in a minute)

pideploy3

 

 

 

 

so lets look inside my express route for post.

pideploy4

The first thing I do is look through the JSON that the webhook sent me for a couple of pieces of information (there is a ton, I will post an example at the bottom of this post, or look in the docs)  I am just pulling out who did the push, and what repository they pushed to.

console.log(req.body.pusher.name + just pushed to + req.body.repository.name);

Next, after writing a simple message to the console, I am using a core node module called child_process  https://nodejs.org/api/child_process.html that will allow me to run commands on the machine it is running on.

I call git, the folder I want to run it on, the command, and any flags i want.  Since I might be using SCP to send files over the the Pi when testing, I hard reset it, clean it, pull, and then do a npm install in case any modules were added ( an added step could be to look through the JSON to see if the package.json was modified before running that last one, but I am not doing that), and finally running tsc since we are using typescript in the project.

	// reset any changes that have been made locally
	exec('git -C ~/projects/wackcoon-device reset --hard', execCallback);

	// and ditch any files that have been added locally too
	exec('git -C ~/projects/wackcoon-device clean -df', execCallback);

	// now pull down the latest
	exec('git -C ~/projects/wackcoon-device pull -f', execCallback);

	// and npm install with --production
	exec('npm -C ~/projects/wackcoon-device install --production', execCallback);

	// and run tsc
	exec('tsc', execCallback);

Obviously, make sure you run this project on your pi using  node app.js from the terminal

Again, you can see see the entire project looking at the wackcoon-hook project

https://github.com/DanielEgan/wackcoon-hook

A way for the pi to be reached from the internet

Since this site is running on localhost, we need a way for GitHub to access this site. There are quite a number of ways for you to accomplish this. You could use port forwarding on your router to make it accessible to the outside world.  Or you could use one of two dev tools that I have used.

localtunnel – http://localtunnel.me/  localtunnel is an npm module that will run on your pi (or other devices ) that allows you to set up a “tunnel” from your local port to a mapped url that you can use point git hub to.   This is an opensource free npm module. I have used it but it is a bit flaky, it will shut down periodically and you have to re-run it.  If you need help setting this up, here is a great tutorial to help you.  http://thisdavej.com/make-your-raspberry-pi-web-server-available-on-the-internet-with-node-js/

ngrok – https://ngrok.com/ –  This is a free teir, paid tier serves that, in there words helps you create “Secure tunnels to localhost” to answer the question ”I want to expose a local server behind a NAT or firewall to the internet.”  If you need help with this, you can check out this tutorial http://www.instructables.com/id/Raspberry-Pi-online-SSH-easy-way/?ALLSTEPS

That’s it, that is all you need.  Now you can work as a team and have them push to your master branch on GitHub and it will automatically push it to your pi.  If you have any questions fell free to ask them in the comments.

 

#############################

As promised, here is the JSON that is sent from the webhook

########## Headers ##########

Request URL: https://wackcoon.localtunnel.me/payload
Request method: POST
content-type: application/json
Expect:
User-Agent: GitHub-Hookshot/0b0c52f
X-GitHub-Delivery: 7507b280-318c-11e6-9322-eaaef242aa6c
X-GitHub-Event: push

######################
############ Body #########

Webhook – https://wackcoon.localtunnel.me/payload

  • {
      "ref": "refs/heads/master",
      "before": "3d23741be4de283f6bbfc10634c6b6ca909b8efc",
      "after": "0035745ae9ef481ac1477da1296b5253a2d22c0a",
      "created": false,
      "deleted": false,
      "forced": false,
      "base_ref": null,
      "compare": "https://github.com/DanielEgan/wackcoon-device/compare/3d23741be4de...0035745ae9ef",
      "commits": [
        {
          "id": "0035745ae9ef481ac1477da1296b5253a2d22c0a",
          "tree_id": "5d2e67e1235f175b93332125379924814cc357f3",
          "distinct": true,
          "message": "swapping out resemblejs for node-resemple-js",
          "timestamp": "2016-06-15T10:56:04-07:00",
          "url": "https://github.com/DanielEgan/wackcoon-device/commit/0035745ae9ef481ac1477da1296b5253a2d22c0a",
          "author": {
            "name": "Daniel Egan",
            "email": "daniel.egan@microsoft.com"
          },
          "committer": {
            "name": "Daniel Egan",
            "email": "daniel.egan@microsoft.com"
          },
          "added": [
    
          ],
          "removed": [
    
          ],
          "modified": [
            "index.js",
            "index.js.map",
            "index.ts",
            "package.json"
          ]
        }
      ],
      "head_commit": {
        "id": "0035745ae9ef481ac1477da1296b5253a2d22c0a",
        "tree_id": "5d2e67e1235f175b93332125379924814cc357f3",
        "distinct": true,
        "message": "swapping out resemblejs for node-resemple-js",
        "timestamp": "2016-06-15T10:56:04-07:00",
        "url": "https://github.com/DanielEgan/wackcoon-device/commit/0035745ae9ef481ac1477da1296b5253a2d22c0a",
        "author": {
          "name": "Daniel Egan",
          "email": "daniel.egan@microsoft.com"
        },
        "committer": {
          "name": "Daniel Egan",
          "email": "daniel.egan@microsoft.com"
        },
        "added": [
    
        ],
        "removed": [
    
        ],
        "modified": [
          "index.js",
          "index.js.map",
          "index.ts",
          "package.json"
        ]
      },
      "repository": {
        "id": 60712114,
        "name": "wackcoon-device",
        "full_name": "DanielEgan/wackcoon-device",
        "owner": {
          "name": "DanielEgan",
          "email": "daniel.egan@live.com"
        },
        "private": false,
        "html_url": "https://github.com/DanielEgan/wackcoon-device",
        "description": "",
        "fork": false,
        "url": "https://github.com/DanielEgan/wackcoon-device",
        "forks_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/forks",
        "keys_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/keys{/key_id}",
        "collaborators_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/collaborators{/collaborator}",
        "teams_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/teams",
        "hooks_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/hooks",
        "issue_events_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/issues/events{/number}",
        "events_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/events",
        "assignees_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/assignees{/user}",
        "branches_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/branches{/branch}",
        "tags_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/tags",
        "blobs_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/git/blobs{/sha}",
        "git_tags_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/git/tags{/sha}",
        "git_refs_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/git/refs{/sha}",
        "trees_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/git/trees{/sha}",
        "statuses_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/statuses/{sha}",
        "languages_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/languages",
        "stargazers_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/stargazers",
        "contributors_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/contributors",
        "subscribers_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/subscribers",
        "subscription_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/subscription",
        "commits_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/commits{/sha}",
        "git_commits_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/git/commits{/sha}",
        "comments_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/comments{/number}",
        "issue_comment_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/issues/comments{/number}",
        "contents_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/contents/{+path}",
        "compare_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/compare/{base}...{head}",
        "merges_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/merges",
        "archive_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/{archive_format}{/ref}",
        "downloads_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/downloads",
        "issues_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/issues{/number}",
        "pulls_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/pulls{/number}",
        "milestones_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/milestones{/number}",
        "notifications_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/notifications{?since,all,participating}",
        "labels_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/labels{/name}",
        "releases_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/releases{/id}",
        "deployments_url": "https://api.github.com/repos/DanielEgan/wackcoon-device/deployments",
        "created_at": 1465402669,
        "updated_at": "2016-06-08T16:26:28Z",
        "pushed_at": 1466013392,
        "git_url": "git://github.com/DanielEgan/wackcoon-device.git",
        "ssh_url": "git@github.com:DanielEgan/wackcoon-device.git",
        "clone_url": "https://github.com/DanielEgan/wackcoon-device.git",
        "svn_url": "https://github.com/DanielEgan/wackcoon-device",
        "homepage": "",
        "size": 212,
        "stargazers_count": 0,
        "watchers_count": 0,
        "language": "TypeScript",
        "has_issues": true,
        "has_downloads": true,
        "has_wiki": true,
        "has_pages": false,
        "forks_count": 0,
        "mirror_url": null,
        "open_issues_count": 0,
        "forks": 0,
        "open_issues": 0,
        "watchers": 0,
        "default_branch": "master",
        "stargazers": 0,
        "master_branch": "master"
      },
      "pusher": {
        "name": "DanielEgan",
        "email": "daniel.egan@live.com"
      },
      "sender": {
        "login": "DanielEgan",
        "id": 6954533,
        "avatar_url": "https://avatars.githubusercontent.com/u/6954533?v=3",
        "gravatar_id": "",
        "url": "https://api.github.com/users/DanielEgan",
        "html_url": "https://github.com/DanielEgan",
        "followers_url": "https://api.github.com/users/DanielEgan/followers",
        "following_url": "https://api.github.com/users/DanielEgan/following{/other_user}",
        "gists_url": "https://api.github.com/users/DanielEgan/gists{/gist_id}",
        "starred_url": "https://api.github.com/users/DanielEgan/starred{/owner}{/repo}",
        "subscriptions_url": "https://api.github.com/users/DanielEgan/subscriptions",
        "organizations_url": "https://api.github.com/users/DanielEgan/orgs",
        "repos_url": "https://api.github.com/users/DanielEgan/repos",
        "events_url": "https://api.github.com/users/DanielEgan/events{/privacy}",
        "received_events_url": "https://api.github.com/users/DanielEgan/received_events",
        "type": "User",
        "site_admin": false
      }
    }

Remote Debugging Node on a Raspberry Pi

raspberry-logoI have been working on a project called Wackcoon (more on that later) that uses Node and runs on a Raspberry pi.  Like all development projects, I needed to debug not only my work but sometimes errors being thrown from node modules that I am using. Wrapping up my code in Try/Catch blocks and sending the error to console.log() got old really fast.  Since I could not test locally since I am running Linux on the raspberry pi,  I wanted to use Visual Studio Code to remote debug my project on the raspberry pi device itself.

The raspberry pi is on my network at home so on the pi I rand a ifconfig command to get the ip address of the device.

Then I went to Visual Studio Code and clicked on the debug icon (little bug in figure below)  I also made sure that Attach was selected in the debug dropdown on top.

debug1

Next I modified my launch.json file.  This is created the first time you run debug ( the green arrow ) .  In the launch.json file there are two sections.  One configuration is for launch ( debugging locally) and the other is for attaching to a already running process.  I put in the IP address that I got in the last step.

debug2

Now on the raspberry pi, I open a terminal and run the app using the –debug-brk option.  I can also just use the –debug option but the first one will have the application pause and wait for me on the first line of my code.

debug3

Now when I start my debug in Visual Studio Code (green arrow) you can see that it is sitting in break mode at line one.

debug4

I can set breakpoints, step in, step over, Step out, add watches, etc.. since this is being streamed from the pi, I cannot modify it on the fly like you can when you debug locally but still pretty cool.

Hope this helps

Daniel

 

 

Syncing my PowerShell profile between machines

powershellicon

 

Ok.. once again we are on the topic of PowerShell.  This is a simple tip but is helpful if you use different machines for your development. I use three different machines, and as you can see by a few of my posts, I have a few modifications to my PowerShell Profile.

 

So it is import for me to have all of my machines use the same profile in order to keep them in sync.  In order to do this I have a profile named SharedPowershell_profile.ps1 located in my dropbox (one drive others will work as well).  Then in the profile on my local machine, my profile looks like this.

 

psprofieshared

 

 

 

I do this on all of my machines, and so whenever I make a change to the shared profile all of the machines get the change.

That’s it :)

If you are looking at doing this in a more secure way, or on a file share, check out the post by Jason Helmick http://www.jasonhelmick.com/2012/08/10/sharing-common-powershell-profiles-for-a-powershell-admin-team/

 

 

More PowerShell Function Hacks

powershellicon

 

Following up on my last post (PowerShell Profile Shortcuts), I have another really cool hack if you, like me, are creating many github repositories for hackathons or demos.

 

Wouldn’t it be cool if you could use the following from the command line

createrepo mynewrepo

And it would

  1. Create a repo on git hub
  2. Clone it locally
  3. CD into that directory
  4. Create a readme.md file
  5. Create a package.json
  6. Create a basic gitignore file
  7. Add all files using git add .
  8. Create a commit
  9. Push back up to your repo

Well you can, just create a function in my powershell profile to do all of this. (See below)

There are three prerequisites:

  1. Install gh —   (npm install -g gh)
  2. Install gig       (npm install -g gig)
  3. Set up npm init defaults (http://iamsim.me/set-your-npm-init-defaults/))
  4. change references to your own github account (says YourGitHubAccount in code now)

To modify your powershell profile

If using VS Code  just type code $profile from your powerhell command line. Otherwise, there are plenty of tutorials on how to modify your profile like this one (http://www.techrepublic.com/blog/data-center/how-to-use-a-powershell-profile-to-simplify-tasks/)

Either way, once you get it open, just paste this in (after prerequisites above) and change the github account to yours.

Function createrepo($reponame){
  #need to install gh --- npm install -g gh
  gh re --new $reponame -B false
  git clone https://github.com/YourGitHubAccount/$reponame.git
  cd $reponame
  #need to install gig npm install -g gig
  gig gen node
  #need to have defaults set up for this (http://iamsim.me/set-your-npm-init-defaults/)
  npm init -y
  #now add a readme file
  echo "# $reponame" >> README.md
  
  echo "## Synopsis" >> README.md

  echo "At the top of the file there should be a short introduction and/ or overview that explains **what** the project is. This description should match descriptions added for package managers (Gemspec, package.json, etc.)" >> README.md

  echo "## Code Example" >> README.md

  echo "Show what the library does as concisely as possible, developers should be able to figure out **how** your project solves their problem by looking at the code example. Make sure the API you are showing off is obvious, and that your code is short and concise." >> README.md

  echo "## Motivation" >> README.md

  echo "A short description of the motivation behind the creation and maintenance of the project. This should explain **why** the project exists." >> README.md

  echo "## Installation" >> README.md

  echo "Provide code examples and explanations of how to get the project." >> README.md

  echo "## API Reference" >> README.md

  echo "Depending on the size of the project, if it is small and simple enough the reference docs can be added to the README. For medium size to larger projects it is important to at least provide a link to where the API reference docs live." >> README.md

  echo "## Tests" >> README.md

  echo "Describe and show how to run the tests with code examples." >> README.md

  echo "## Contributors" >> README.md

  echo "Let people know how they can dive into the project, include important links to things like issue trackers, irc, twitter accounts if applicable." >> README.md

  echo "## License" >> README.md

  echo "A short snippet describing the license (MIT, Apache, etc.)" >> README.md
  git add .
  git commit -m "first commit"
  #if you dont want it to prompt you for credentials every time run this : git config --global credential.helper wincred 
  git push -u origin master
}

Powershell profile shortcuts

powershellicon

Since I have been using the MEAN stack and node quite a bit lately, I have found my self to be using the command line all of the time.  Not just in using node and git, but also to create files (touch), launch my editor (code or subl), and work with mongodb (mongo).  My command line of choice for my windows machines is cmder (you can find it at http://www.cmder.net ).  I will do another post as to why  I like it but in this post I wanted to show you just a few of the things I have added to make life easier from the command line.

 

First, cmder uses conemu ( https://conemu.github.io/ ) which is not a shell, but adds features to the shell you prefer to use, in this case powershell.  The small additions to my profile that I am going to show you will work with powershell and so, in essence with cmder.

The first one is purely cosmetic.  When I load up powershell, I want it to do two things.

  1. start up in the folder that I choose
  2. show my branding on top of the screen

 

In powershell, anything not wrapped in a function will run when powershell is loaded.  So at the top of my profile file I have the following

psprofilepic1
When I start up PowerShell, it is branded with TheSociableGeek on top, and starts in my c:\projects folder.  To create the ascii text, you can use any online ascii art editor like http://www.network-science.de/ascii/

Here is what it looks like when PowerShell starts.

newcommand

The next thing I wanted was the ability to create a directory and cd into it at the same time, which you can on mac terminal or Linux using the && characters. PowerShell does not like the  && characters.

So for this I created a function called mcd in which I pass the name of the folder I want to create.

mcd

 

 

as you can see, running the mcd command just calls the md (make directory) and cd (change directory) commands with the name I pass it.

Next, one of the things that happens all the time is that I use the clear command when the command window gets too cluttered.  I wanted something that not only cleared the window, but put my branding back up at the top like it does when it starts. Again, purely cosmetic, but I like it.

So I created a function called cl that clears the screen and prints out the ascii again.  I know, I could have used a variable and used this for both start up and the cl function, but I was lazy. (I also stole this idea from Jeremy Foster http://www.codefoster.com who has helped me with everything commandline.. thanks Jeremy)

clfunction

Finally, the last one I will show you is just launching a browser.  Since I am working with node all of the time, I wanted a quick way to launch the browser from the command line.  I am not always using browsersync in my projects or demos, so I wanted a quick way to launch different browsers.  I created two functions for each browser. One for a default url, and the other to open a localhost port with a ability to name the port I wanted.

launchbrosers
That way I can easily type something like chromelocal 8000  to launch the browser and get to testing things out.

Anyway, that’s all I wanted to share of my profile for now.  Hope this helps someone.

Daniel – TheSociableGeek

 

 

Hackathon Resources

tag-cloud-hackathon

 

It’s Hackathon time!

It’s that time of year again, and we are here to help. If you are participating in any of the great hackathons around the country, below you will find the resources you need to do cool stuff like, Machine Learning, Facial Recognition, emotion tracking and more.

Getting Started Tutorials

Cognitive Services

Cognitive Services  allows developers to create smarter apps, which can do things like recognize faces and interpret natural language even if the app developers are not experts in those fields.

  • oxford2Visual tools: This service can analyze visual content to look for things like inappropriate content or a dominant color scheme. It also can detect and understand text in photos, such as a team name, and can sort photos by content, such as pictures of beaches, animals or food. Finally, it can automatically edit photos down to a recognizable and useful thumbnail for easy scanning.

 

  • oxford 1Face recognition: This technology automatically recognizes faces in photos, groups faces that look alike and verifies whether two faces are the same. It can be used for things like easily recognizing which users are in certain photos and allowing a user to log in using face authentication. It’s the same technology that is behind this fun new website that guesses how old a person looks based on a photograph.

 

Machine learning

ml1A fully managed cloud service that enables you to easily build, deploy, and share predictive analytics solutions. Azure Machine Learning means business. You can deploy your model into production as a web service in minutes—a web service that can be called from any device, anywhere and that can use any data source

Virtual Machines

Databases

Internet of Things

Web Apps

 

NASA Space Apps Challenge 2016

NasaSpaceApps

Houston! We have Apps!

It’s that time of year again, and we are here to help. If you are participating in this years NASA Space Apps Challenge, below you will find the resources you need to do cool stuff like, Machine Learning, Facial Recognition, emotion tracking and more.

How can we help?

But first things first, to get started, you will need to grab yourself some free Microsoft Cloud to do your computations, and Microsoft Azure has you covered.

Need to connect with the Microsoft Space Apps Team for technical mentoring? Just email spaceapps@Microsoft.com

Getting Connected – Setting up your Azure Pass

You should have received and Azure Pass from your organizer, all you need to do is take that card and head over to http://sogeek.us/getazurepass for step by step instructions on how to get set up.

Getting Started Tutorials

Project Oxford

Project Oxford allows developers to create smarter apps, which can do things like recognize faces and interpret natural language even if the app developers are not experts in those fields.

  • oxford2Visual tools: This service can analyze visual content to look for things like inappropriate content or a dominant color scheme. It also can detect and understand text in photos, such as a team name, and can sort photos by content, such as pictures of beaches, animals or food. Finally, it can automatically edit photos down to a recognizable and useful thumbnail for easy scanning.

 

  • oxford 1Face recognition: This technology automatically recognizes faces in photos, groups faces that look alike and verifies whether two faces are the same. It can be used for things like easily recognizing which users are in certain photos and allowing a user to log in using face authentication. It’s the same technology that is behind this fun new website that guesses how old a person looks based on a photograph.

 

Machine learning

ml1A fully managed cloud service that enables you to easily build, deploy, and share predictive analytics solutions. Azure Machine Learning means business. You can deploy your model into production as a web service in minutes—a web service that can be called from any device, anywhere and that can use any data source

Virtual Machines

Databases

Internet of Things

Web Apps

Grab the Meetup Slides

Get Inspired

If you are looking for some inspiration for your hack, check out the video below.

Space Apps New York City

Node.js intellisense

node-jsWorking in my node projects and presentations I pop back and forth between both Sublime Text 3 and VS Code but I find myself increasingly just using VS Code.  One of the reasons is that I am able to get great intellisense using the node and express typescript definition files.

As you can see by the screenshots below, even when I am just creating a simple server using the node http module, with VS Code, I get that great “.” intellesense.

vscodeintellsublimeintell

This is invaluable for any developer but especially for developers new to the stack that might not have all of the methods available stored in their head.

Getting node and express intellisense in VS Code

In order to get specific package intellisense in vs code you will need to install a couple of things.  There are a number of ways to do this but I am just going to use the command line (powershell or Terminal in OSX).  The first thing you need to do is to install TSD globally.

npm install -g tsd

When installing this will tell you that TSD is deprecated in favor of Typeings(https://github.com/typings/typings)  but I use TSD anyway.  Both will work similar with this a bit of a syntax difference when installing the tsd’s.

Once tsd is installed globally.  Make sure you are in the project folder that you need the intellisense in and run the following commands.


tsd query node --action install
tsd query express --action install

This will install the type definition files for both node and express. If you need tsd files for other things you can see what is available either at the github repository (where tsd pulls these files) https://github.com/DefinitelyTyped/DefinitelyTyped or the website http://definitelytyped.org/

 

I have tried to find a way to do this with sublime.

I checked http://definitelytyped.org/directory/tools.html and found under IDE tools sublime-typescript  https://github.com/raph-amiard/sublime-typescript but it said it was not maintained anymore and sent me here :  https://github.com/raph-amiard/sublime-typescript which itself is no longer maintained, which directed me here :  https://github.com/Phaiax/ArcticTypescript which is a fork of the last one and seems to be maintained but when I install it, I don’t see it giving me the intellisense I am looking for.

So at this point, I cant seem to get this in Sublime. If someone knows a way to implement this through a plugin, please let me know.

Gamemaker MVA Start Kits

GMStarterKits A while back I did a Microsoft Virtual Academy training session on Creating Your First 2D Game with Gamemaker.  This has seen a lot of traction lately.  One of the things I talked about in the session is using the StarterKits that we developed for our Game Camps to give you a running start on either a Maze Game, an Endless Runner Game or a Platform Game.  The place those files were hosted is no longer there so I decided to host them here on my site since I have been getting lots of requests for them.

You can find the StarterKits here :

http://thesociablegeek.com/wp-content/uploads/StarterKits.zip

of course you can check out the MVA on Gamemaker here:

https://mva.microsoft.com/en-us/training-courses/creating-your-first-2d-game-with-gamemaker-8480?l=DleVcsXz_6504984382

Using Curl in Powershell

So you are a windows user, but really like what you have been able to do using curl on your Mac.  On windows you use PowerShell, what if you want to use cURL?

First of all, what is cURL?  To pull directly from their website :

curl is an open source command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2, cookies, user+password authentication (Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos), file transfer resume, proxy tunneling and more.

More simply stated, cURL is a tool that is used at the command line for transferring data.

So now what if you want to use it in PowerShell?  If you are using version 5.x of  PowerShell you may think that you already have it.  You can check your version of PowerShell by calling the command : $PSVersionTable.PSVersion
Ps1

 

Using cURL in PowerShell

You can type in a cURL command like one that downloads a file from a GitHub repository.

curl http://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/mongodb-on-ubuntu/azuredeploy.json > azuredeploy3.json

and  it will seem like it works but what it is actually doing is just using cURL as an alias. In the above instance, what will happen is that you will just get the headers instead of the file itself.  Alias’ in PowerShell allow you to create shortcuts for longer commands so you don’t have to type them out all of the time. If you type in the command Get-Alias, it will give you a list of all the Alias’ that are used in PowerShell. As you can see, the curl command just calls the Invoke-WebRequest command.  They are similar but not the same which is why the above request does not work for us.

ps2

To get this to work in PowerShell you would need to change the syntax slightly.

ps3

( file name cut off in image “https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/mongodb-on-ubuntu/azuredeploy.json”)

You then open the file from PowerShell either using Code or Sublime.

ps4
Utilizing the switches that Invoke-WebRequest uses instead of cURL does the trick.  But if you want to stay consistent and use the same commands on your MAC as you do on your PC, you will need to remove the alias and install cURL on the PC in order to achieve this.

The first thing you need to do is remove the alias.

Removing the cURL alias

If you don’t already have a profile, run the following command to create one.

New-Item $profile -force -itemtype file

Next, open up the profile file. (This will open the file up in notepad)

notepad $profile

add the following line to the profile file.

remove-item alias:curl

save the notepad file and close it.
Then either run the following command to reload the profile OR close and reopen Powershell to refresh.

remove-item alias:curl

(thanks to megamorf for these steps)

Now if you run the Get-Alias command again, you will see that the curl alias is gone.

Installing cURL on your PC

There are a number of ways you can do this.  One way is to use the cURL for Windows created by the Confused By Code author : http://www.confusedbycode.com/curl/ this is a step by step installer that installs curl, adds it to your path, installs the certs etc.. but in keeping with my new mindset of doing everything from the command line that I can, I decided to install it using Chocolately. https://chocolatey.org/

Chocolatey is a Linux style command line packet manager for windows.  I will be using it in the future so it makes sense to use it for this.   To install it do the following

Open up PowerShell in Admin Mode and run the following command.

iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))

Once you have installed Chocolatey, you can then use it to install curl. (Open and close PowerShell first)

choco install curl

Now you have curl installed but if you try to run the curl command from above, you will receive some OpenSSL errors. To fix this you have two choices, One use the -R switch to ignore the certs (not recommended) OR install the certs.

To install the certs, navigate to C:\ProgramData\chocolatey\lib\curl\tools ( do it in windows explorer or powershell, doesn’t matter to me)

Double click mk-ca-bundle.vbs, or if you have Perl, mk-ca-bundle.pl. The script will download a new SSL bundle from Mozilla. It will be called ca-bundle.crt. once it is downloaded rename the file to curl-bundle.crt and leave it in the same directory.

Open and close PowerShell and then run the following command.

curl https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/mongodb-on-ubuntu/azuredeploy.json > azuredeploy6.json

(By the way, this is an ARM template that I am using to install MongoDB in Azure on Ubuntu if you are curious. See my Mean On Azure Series if you want to learn more. http://sogeek.us/meanonazure)

That’s all.. I hope you found that useful.

Daniel – The Sociable Geek