LoginSignup
1
0

More than 3 years have passed since last update.

phpでgithubにファイルをアップロードする関数をつくってみた

Last updated at Posted at 2019-05-15

ツール等でGithubのレポジトリに直接ファイルをアップロードしたいなー
っておもっていろんな記事をみてたらGitHubAPIでできるっぽいので
どうせなら汎用的にしておいたほうが個人的にもよさげだったので
phpで関数化しておきました
GitHubAPIはV3です

エラーチェックなど一切してないのでそのあたりはみなさんのほうでなんとかしてください💦
逆にこういう問題おこったよってのもぜひコメントにお寄せください!

あと、実際に利用する際は壊れてもいいリポジトリで試してからにしてください。
(これを開発中、Tree作成するときにbase_treeを指定しなかったために、まっさらになること連発しましたので・・もちろん履歴は追えるのはGitのいいところなのでもとに戻せます。。が、、)

流れ的には
 ローカルファイルからBlob作成
 最新Treeを取得
 最新TreeのRootにBlob化したファイルを追加しTreeを作成
 作成したTreeをCommit
 CommitをHEADに反映する
という一連の流れにしています。

元来、パス指定したところのTreeにBlob追加したほうが良さそうですが
めんどくさがりましたw

ちなみにGitHub API access_tokenは
https://github.com/settings/applications/new
にアクセスしてアプリケーションを作成します。
callbackurlは存在しないURLでもOKです

Client IDが発行されるのでそのIDを以下のURLに付けてアクセス
https://github.com/login/oauth/authorize?scope=repo&client_id=XXXXXXXXX
してoauth認証をします

callbackURLにたどりつきますが、存在しないページにアクセスされるのですが
そのURLのcode引数を利用して以下のURLとしてアクセスします

アクセスすると
access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&scope=repo&token_type=bearer
てなデータが取得できます。
このaccess_tokenを利用することになります。


$authtoken="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";  //GitHub API access_token

$projectname="hogehoge";        //
$repogitoryname="fugafuga"; //リポジトリ名 projectname/repogitorynameという形になります
$branch="master";       //ブランチ名 masterブランチ以外も指定できます


$realfilename="testtest.php";   //アップロードしたいファイル名
$gitfilepath="untarara/testtest.php";   //GitHub上でのファイル名 フルパスで。ただし先頭には/をつけないように!
$commitmessage="commit_".date("YmsHis");        //コミットメッセージ

//実行!
$ret = github_fileupload($projectname,$repogitoryname,$branch,$authtoken , $realfilename,$gitfilepath,$commitmessage);

print_r($ret);


function github_fileupload($projectname,$repogitoryname,$branch,$authtoken , $realfilename,$gitfilepath,$commitmessage)
{
    if($branch=="")
    {
        $branch="master";
    }
    ////////////////////
    //BLOB create
    $base64=base64_encode(file_get_contents($realfilename));
    $apiurl="https://api.github.com/repos/".$projectname."/".$repogitoryname."/git/blobs";
    $postdata=array("content"=>$base64,
                "encoding"=>"base64"
    );
    $ret=github_apiaccess($apiurl,$authtoken,$postdata);
    $retdata=json_decode($ret,true);
    //print_r($retdata);
    $sha_blob=$retdata["sha"];

    ////////////////////
    //Get latest Tree sha (latest commit hash)
    $apiurl="https://api.github.com/repos/".$projectname."/".$repogitoryname."/git/trees/".$branch;
    $postdata=null;
    $ret=github_apiaccess($apiurl,$authtoken,$postdata);
    $retdata=json_decode($ret,true);
    //print_r($retdata);
    $sha_latestcommithash=$retdata["sha"];
    //echo "*****sha_blob:".$sha_blob."\n";
    //echo "*****sha_prevcommithash:".$sha_latestcommithash."\n";

    ////////////////////
    //Create New tree(like git add file)
    $apiurl="https://api.github.com/repos/".$projectname."/".$repogitoryname."/git/trees";
    $postdata=array("base_tree"=>$sha_latestcommithash,
        "tree"=>array(array("path"=>$gitfilepath,
                        "mode"=>"100644",
                        "type"=>"blob",
                        "sha"=>$sha_blob))
        );

    $ret=github_apiaccess($apiurl,$authtoken,$postdata);
    $retdata=json_decode($ret,true);
    //print_r($retdata);
    $sha_newtree=$retdata["sha"];
    //echo "*****sha_newtree:".$sha_newtree."\n";

    ////////////////////
    //Commit
    $apiurl="https://api.github.com/repos/".$projectname."/".$repogitoryname."/git/commits";
    $postdata=array("message"=>$commitmessage,
                    "tree"=>$sha_newtree,
                    "parents"=>array($sha_latestcommithash)
        );
    $ret=github_apiaccess($apiurl,$authtoken,$postdata);
    $retdata=json_decode($ret,true);
    //print_r($retdata);
    $sha_newcommithash=$retdata["sha"];
    //echo "*****sha_newcommithash:".$sha_newcommithash."\n";

    ////////////////////
    //reflect head
    $apiurl="https://api.github.com/repos/".$projectname."/".$repogitoryname."/git/refs/heads/".$branch;
    $postdata=array("force"=>false,
                    "sha"=>$sha_newcommithash
            );
    $ret=github_apiaccess($apiurl,$authtoken,$postdata);
    $retdata=json_decode($ret,true);
    return $retdata;
}
function github_apiaccess($apiurl,$authtoken,$postdata)
{
    //echo $apiurl."\n";

    $header[]="Accept: application/json";
    $header[]="Content-Type: application/json";
    $header[]="Authorization: bearer ".$authtoken;
    $header[]="User-Agent: PHP_GITHUBAPI_FILEUPLOAD";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $apiurl); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    //curl_setopt($ch, CURLOPT_VERBOSE, true);

    //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    //curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
    //curl_setopt($ch, CURLOPT_AUTOREFERER, true);

    if(is_array($postdata) && $postdata!=null)
    {
        curl_setopt($ch, CURLOPT_POST, true);
        $postjson=json_encode($postdata, JSON_UNESCAPED_SLASHES);
        //echo "POSTJSON:".$postjson."\n";
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postjson);
    }

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $ret = curl_exec($ch);
    curl_close($ch);

    return $ret;
}



1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0