Probando Github Webhooks con ngrok

GitHub permite definir webhooks para los repositorios.

Si sobre el repositorio se realiza cierta acción (usualmente un push), github ejecuta el webhook que se haya asociado a esa acción (usualmente una solicitud post a un url indicado).

Por ejemplo, para el repositorio https://github.com/akobashikawa/travis-test-dev entro a Settings, Webhooks & services, Webhooks, Add webhook:

Payload URL: http://mydomain.com/postreceive
Content type: application/json
Secret: some_secret_word
Which events would you like to trigger this webhook?: Just the push event.
[x] Active


ngrok

ngrok es un servicio que permite que un servidor local pueda tener un ip público.

Por ejemplo, http://localhost:3000 puede ser visto en http://12345abc.ngrok.io/

Eso evita tener que usar un hosting para simplemente probar un webhook.

De ese modo, para probar el webhook, cree rápidamente este servidor web con nodejs:

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/', function(req, res) {
 console.log(req.url);
 res.send('Hello Express!');
});

app.post('/postreceive', function(req, res) {
 console.log(req.body);
 res.send('Post Response');
});

app.listen(3000, function() {
 console.log('Express app listening in 3000');
});


Levanté el servidor:

$ nodemon index.js

Una ventaja de usar nodemon es que el servidor se recarga automáticamente cada vez que actualizo el código.

Lugo ejecuté ngrok (que descargué de https://ngrok.com/download) en otra consola:

$ ./ngrok http 3000
...
ngrok by @inconshreveable                                      (Ctrl+C to quit)
                                                                               
Tunnel Status                 online                                           
Version                       2.0.25/2.1.1                                     
Region                        United States (us)                               
Web Interface                 http://127.0.0.1:4040                            
Forwarding                    http://57cdad67.ngrok.io -> localhost:3000       
Forwarding                    https://57cdad67.ngrok.io -> localhost:3000      
                                                                               
Connections                   ttl     opn     rt1     rt5     p50     p90      
                              0       0       0.00    0.00    0.00    0.00  

Luego defino un webhook con el payload URL: https://57cdad67.ngrok.io/postreceive

Pruebo luego hacer un push al repositorio y observo en la consola la solicitud post que github envía:

{ ref: 'refs/heads/master',
  before: '8d8523134683128d06e2178c49eacde2d46bddb3',
  after: 'd313dfc1d46a08773c4d1ac429654a2e1a375b62',
  created: false,
  deleted: false,
  forced: false,
  base_ref: null,
  compare: 'https://github.com/akobashikawa/travis-test-dev/compare/8d8523134683...d313dfc1d46a',
  commits: 
   [ { id: 'd313dfc1d46a08773c4d1ac429654a2e1a375b62',
       tree_id: 'd5746c384d3f2d6afae9f5b0f7b4ea44f7bbf8a5',
       distinct: true,
       message: 'Update README.md',
       timestamp: '2016-05-20T00:06:31-05:00',
       url: 'https://github.com/akobashikawa/travis-test-dev/commit/d313dfc1d46a08773c4d1ac429654a2e1a375b62',
       author: [Object],
       committer: [Object],
       added: [],
       removed: [],
       modified: [Object] } ],
  head_commit: 
   { id: 'd313dfc1d46a08773c4d1ac429654a2e1a375b62',
     tree_id: 'd5746c384d3f2d6afae9f5b0f7b4ea44f7bbf8a5',
     distinct: true,
     message: 'Update README.md',
     timestamp: '2016-05-20T00:06:31-05:00',
     url: 'https://github.com/akobashikawa/travis-test-dev/commit/d313dfc1d46a08773c4d1ac429654a2e1a375b62',
     author: 
      { name: 'Rulo Kobashikawa',
        email: 'akobashikawa@gmail.com',
        username: 'akobashikawa' },
     committer: 
      { name: 'Rulo Kobashikawa',
        email: 'akobashikawa@gmail.com',
        username: 'akobashikawa' },
     added: [],
     removed: [],
     modified: [ 'README.md' ] },
  repository: 
   { id: 55999700,
     name: 'travis-test-dev',
     full_name: 'akobashikawa/travis-test-dev',
     owner: { name: 'akobashikawa', email: 'akobashikawa@gmail.com' },
     private: false,
     html_url: 'https://github.com/akobashikawa/travis-test-dev',
     description: 'Tetsing travis. Dev repo.',
     fork: false,
     url: 'https://github.com/akobashikawa/travis-test-dev',
     forks_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/forks',
     keys_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/keys{/key_id}',
     collaborators_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/collaborators{/collaborator}',
     teams_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/teams',
     hooks_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/hooks',
     issue_events_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/issues/events{/number}',
     events_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/events',
     assignees_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/assignees{/user}',
     branches_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/branches{/branch}',
     tags_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/tags',
     blobs_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/git/blobs{/sha}',
     git_tags_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/git/tags{/sha}',
     git_refs_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/git/refs{/sha}',
     trees_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/git/trees{/sha}',
     statuses_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/statuses/{sha}',
     languages_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/languages',
     stargazers_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/stargazers',
     contributors_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/contributors',
     subscribers_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/subscribers',
     subscription_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/subscription',
     commits_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/commits{/sha}',
     git_commits_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/git/commits{/sha}',
     comments_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/comments{/number}',
     issue_comment_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/issues/comments{/number}',
     contents_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/contents/{+path}',
     compare_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/compare/{base}...{head}',
     merges_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/merges',
     archive_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/{archive_format}{/ref}',
     downloads_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/downloads',
     issues_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/issues{/number}',
     pulls_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/pulls{/number}',
     milestones_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/milestones{/number}',
     notifications_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/notifications{?since,all,participating}',
     labels_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/labels{/name}',
     releases_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/releases{/id}',
     deployments_url: 'https://api.github.com/repos/akobashikawa/travis-test-dev/deployments',
     created_at: 1460401727,
     updated_at: '2016-04-11T19:21:17Z',
     pushed_at: 1463720793,
     git_url: 'git://github.com/akobashikawa/travis-test-dev.git',
     ssh_url: 'git@github.com:akobashikawa/travis-test-dev.git',
     clone_url: 'https://github.com/akobashikawa/travis-test-dev.git',
     svn_url: 'https://github.com/akobashikawa/travis-test-dev',
     homepage: null,
     size: 3295,
     stargazers_count: 0,
     watchers_count: 0,
     language: 'PHP',
     has_issues: true,
     has_downloads: true,
     has_wiki: true,
     has_pages: false,
     forks_count: 0,
     mirror_url: null,
     open_issues_count: 1,
     forks: 0,
     open_issues: 1,
     watchers: 0,
     default_branch: 'master',
     stargazers: 0,
     master_branch: 'master' },
  pusher: { name: 'akobashikawa', email: 'akobashikawa@gmail.com' },
  sender: 
   { login: 'akobashikawa',
     id: 108734,
     avatar_url: 'https://avatars.githubusercontent.com/u/108734?v=3',
     gravatar_id: '',
     url: 'https://api.github.com/users/akobashikawa',
     html_url: 'https://github.com/akobashikawa',
     followers_url: 'https://api.github.com/users/akobashikawa/followers',
     following_url: 'https://api.github.com/users/akobashikawa/following{/other_user}',
     gists_url: 'https://api.github.com/users/akobashikawa/gists{/gist_id}',
     starred_url: 'https://api.github.com/users/akobashikawa/starred{/owner}{/repo}',
     subscriptions_url: 'https://api.github.com/users/akobashikawa/subscriptions',
     organizations_url: 'https://api.github.com/users/akobashikawa/orgs',
     repos_url: 'https://api.github.com/users/akobashikawa/repos',
     events_url: 'https://api.github.com/users/akobashikawa/events{/privacy}',
     received_events_url: 'https://api.github.com/users/akobashikawa/received_events',
     type: 'User',
     site_admin: false } }

Si ngrok se detiene (con CTRL+C), cuando se vuelve a ejecutar nos dará un url distinto al anterior y será necesario ir a github para editar la definición del webhook y colocar el nuevo payload url.

La acción que definí en el servidor web fue la de de mostrar en consola la solicitud post enviada por github. Se puede usar esa señal para ejecutar cualquier acción que se crea conveniente. Por ejemplo, descargar el repositorio y deployarlo automáticamente.

Relacionados