Making WordPress.org


Ignore:
Timestamp:
09/07/2016 06:02:21 AM (10 years ago)
Author:
dd32
Message:

GitHub Sync: Add support for the application/x-www-form-urlencoded webhook format and add documentation.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sites/trunk/api.wordpress.org/public_html/dotorg/github-sync/feature-plugins.php

    r2698 r3983  
    11<?php
    22/**
    3  * A easy webhook to allow feature plugins to be sync'd to WordPress.org plugins SVN easier.
     3 * This webhook is very basic, but handles syncing a select few featured plugins over to plugins.svn.wordpress.org during development.
     4 *
     5 * To have your *feature project* handled by this sync script:
     6 * - Ensure you're listed on https://make.wordpress.org/core/features-as-plugins/ if you're not, ping in #meta
     7 * - Ping in #meta to get your project added to the whitelist within this file
     8 * - Add `https://api.wordpress.org/dotorg/github-sync/feature-plugins.php` as a `push` webhook on github with the secret we'll provide you.
     9 * - Push to github master and watch https://plugins.trac.wordpress.org/log/$plugin_slug/
     10 * - Profit from all the Open Source points you're getting!
    411 */
    512
    … …  
    815class GH2WORG {
    916
    10         private $whitelisted_repos = array(
    11                 // Github User/Repo => plugins.svn.wordpress.org/****/trunk/
    12                 'dd32/feature-plugin-testing' => 'test-plugin-3',
    13                 'voldemortensen/menu-customizer' => 'menu-customizer',
    14                 'georgestephanis/two-factor' => 'two-factor',
     17        private $whitelisted_repos = [
     18                // Github.com/{$user/repo-name} => plugins.svn.wordpress.org/{$slug}/trunk/
     19                'dd32/feature-plugin-testing'           => 'test-plugin-3',
     20                'georgestephanis/two-factor'            => 'two-factor',
    1521                'georgestephanis/application-passwords' => 'application-passwords',
    16                 'obenland/shiny-updates' => 'shiny-updates',
    17                 'pento/react' => 'react',
    18         );
     22                'obenland/shiny-updates'                => 'shiny-updates',
     23                'pento/react'                           => 'react',
     24        ];
    1925
    2026        function __construct() {
    21                 $this->populate_post_vars();
    22 
    23                 if ( ! $this->verify_github_signature() ) {
    24                         die( 'Cheating, huh?' );
    25                 }
    26 
    27                 $repo_name = $_POST['repository']['full_name'];
    28                 $repo_url  = $_POST['repository']['git_url'];
    29 
    30                 if ( ! $this->verify_valid_plugin( $repo_name ) ) {
    31                         die( 'Sorry, This Github repo is not configured for WordPress.org Plugins SVN Github Sync. Please contact us.' );
    32                 }
     27                $repo_name = $this->get_notified_repo();
    3328
    3429                $svn_directory = $this->whitelisted_repos[ $repo_name ];
    3530
    36                 $this->process_github_to_svn( $repo_url, $svn_directory );
     31                if ( ! $repo_name || ! $svn_directory ) {
     32                        die( 'Sorry, This Github repo is not configured for WordPress.org Plugins SVN Github Sync. Please ping in #meta on Slack for assistance.' );
     33                }
     34
     35                $this->process_github_to_svn( $repo_name, $svn_directory );
    3736        }
    3837
    39         function populate_post_vars() {
    40                 if ( 'application/json' == $_SERVER['HTTP_CONTENT_TYPE'] ) {
    41                         $_POST = @json_decode( file_get_contents('php://input'), true );
    42                 } else {
    43                         // Assuming Magic Quotes disabled like a good host.
    44                         $_POST = @json_decode( $_POST['payload'], true );
     38        /**
     39         * Determines the Github Repo (user/repo) which Github is notifying us about.
     40         *
     41         * - Extracts the repo from both `application/json` and `application/x-www-form-urlencoded` webhook variants.
     42         * - Verifies the signature of the request
     43         *
     44         * @return string|bool Github repo on success, false on failure.
     45         */
     46        function get_notified_repo() {
     47                $github_payload = file_get_contents( 'php://input' );
     48                $signature_of_payload = 'sha1=' . hash_hmac( 'sha1', $github_payload, FEATURE_PLUGIN_GH_SYNC_SECRET );
     49
     50                if ( ! hash_equals( $signature_of_payload, $_SERVER['HTTP_X_HUB_SIGNATURE'] ) ) {
     51                        return false;
    4552                }
     53
     54                /*
     55                 * Extract the payload from the `php://input` stream, although this is also present in
     56                 * $_POST, the Github signature is of this raw data, so we'll use that data.
     57                 */
     58                if ( 'application/x-www-form-urlencoded' === $_SERVER['HTTP_CONTENT_TYPE'] ) {
     59                        parse_str( $github_payload, $github_payload );
     60                        $github_payload = $github_payload['payload'];
     61                }
     62
     63                return json_decode( $github_payload, true )['repository']['full_name'];
    4664        }
    4765
    48         function verify_github_signature() {
    49                 if ( empty( $_SERVER['HTTP_X_HUB_SIGNATURE'] ) )
    50                         return false;
     66        /**
     67         * Triggers the shell script to migrate the Git commit to plugins.svn
     68         *
     69         * @param string $github_repo   The Github Repo which was modified (user/repo).
     70         * @param string $svn_directory The plugins.svn directory/plugin (plugin-slug).
     71         */
     72        function process_github_to_svn( $github_repo, $svn_directory ) {
    5173
    52                 list( $algo, $hash ) = explode( '=', $_SERVER['HTTP_X_HUB_SIGNATURE'], 2 );
    53 
    54                 // Todo? Doesn't handle standard $_POST, only application/json
    55                 $hmac = hash_hmac( $algo, file_get_contents('php://input' ), FEATURE_PLUGIN_GH_SYNC_SECRET );
    56 
    57                 return $hash === $hmac;
    58         }
    59 
    60         function verify_valid_plugin( $repo ) {
    61                 return isset( $this->whitelisted_repos[ $repo ] );
    62         }
    63 
    64         function process_github_to_svn( $github_url, $svn_directory ) {
    65 
    66                 putenv( 'PHP_SVN_USER=' . FEATURE_PLUGIN_GH_SYNC_USER );
     74                putenv( 'PHP_SVN_USER='     . FEATURE_PLUGIN_GH_SYNC_USER );
    6775                putenv( 'PHP_SVN_PASSWORD=' . FEATURE_PLUGIN_GH_SYNC_PASS );
    6876
    69                 echo shell_exec( __DIR__ . "/feature-plugins.sh $github_url $svn_directory 2>&1" );
     77                $github_repo   = escapeshellarg( $github_repo );
     78                $svn_directory = escapeshellarg( $svn_directory );
     79
     80                echo shell_exec( __DIR__ . "/feature-plugins.sh $github_repo $svn_directory 2>&1" );
    7081
    7182                putenv( 'PHP_SVN_USER' );
Note: See TracChangeset for help on using the changeset viewer.