/** * フォルダをコピーする * * @param array $params パラメータ * @param string $params.from コピー元のフォルダパス (source/ からの相対パス) * @param string $params.to コピー先のフォルダパス (source/ からの相対パス) * @param Phest $phest Phestオブジェクト * @return bool プラグインの成功判定 */ function plugin_watch_copydir(array $params, Phest $phest) { $dir_source = $phest->getSourcePath(); $from_dpath = $dir_source . '/' . $params['from']; $to_dpath = $dir_source . '/' . $params['to']; if (!is_dir($from_dpath)) { $phest->add('builderror', '[copydir] from はディレクトリではありません: ' . $from_dpath); return false; } $phest->addWatchList(File::getFileList($from_dpath)); $phest_plugin_copydir_list[$from_dpath] = $to_dpath; return true; }
/** * 指定したディレクトリから、ファイルのパスの配列を返す * * <pre> * ディレクトリのパスは返さず、ファイルパスのみ返す。 * ./test/ * index.php * counter.php * data/ * count.dat * img/ * * という構成があった場合、 * </pre> * <code> * $file_list = File::getFileList('./test'); * </code> * <pre> * は、 * * array( * './test/index.php', * './test/counter.php', * './test/data/count.dat' * ); * を返す。 * </pre> * * @param string $directory ディレクトリ * @param int $depth たどる階層の深さ -1 だと無制限 * @param array $ignore 無視するパターン (fnmatch関数の引数) * @param array $filter 検出するパターン (fnmatch関数の引数) * @return array ファイルパスのリスト */ public static function getFileList($directory, $depth = -1, $ignore = array(), $filter = array()) { if ($depth == 0) { return array(); } $directory = rtrim($directory, '\\/'); $tmp = array(); if (ECF_FILE_FILESYSTEMITERATOR_EXIST) { $iterator = new RecursiveDirectoryiterator($directory, FilesystemIterator::SKIP_DOTS); } else { $iterator = new RecursiveDirectoryiterator($directory); } foreach ($iterator as $path) { $filename = $path->getBasename(); foreach ((array) $ignore as $ival) { if (fnmatch($ival, $filename)) { continue 2; } } if ($path->isDir()) { if ($depth > 0) { $depth--; } foreach (File::getFileList($directory . '/' . $filename, $depth, $ignore, $filter) as $ppath) { $tmp[] = $ppath; } } else { if ($filter) { $hit = false; foreach ((array) $filter as $fval) { if (fnmatch($fval, $filename)) { $hit = true; break; } } if (!$hit) { continue; } } $tmp[] = $directory . '/' . $filename; } } return $tmp; }
/** * Amazon S3へProductionビルドをアップロード * * @param array $params パラメータ * @param bool $params.enable trueを指定すると実行 * @param string $params.bucket バケット名 * @param enum $params.region リージョン * @param string [$params.prefix] アップロードするキー名につけるPrefix * @param string $params.bucket バケット名 * @param array [$params.protectpatterns] 削除しないキー名の正規表現を配列で指定 * @param string $params.key AWSのアクセスキー * @param string $params.secret AWSのシークレットキー * @param Phest $phest Phestオブジェクト * @return bool プラグインの成功判定 */ function plugin_button_s3deploy(array $params, Phest $phest) { $phest->registerSection('s3deployerror', 'デプロイエラー', array('type' => 'danger')); if ($phest->hasError()) { $phest->add('s3deployerror', 'エラーが発生しているためデプロイしません'); return false; } $dryrun = true; if (isset($params['dryrun'])) { $dryrun = $params['dryrun']; } if ($dryrun) { $phest->registerSection('s3deploy', 'デプロイ完了 [dryrun]', array('type' => 'warning')); } else { $phest->registerSection('s3deploy', 'デプロイ完了'); } $prefix = ''; if (isset($params['prefix'])) { $prefix = $params['prefix']; } if (isset($params['buildtype'])) { $buildtype = $params['buildtype']; } else { $buildtype = 'production'; } $protectpatterns = array(); if (isset($params['protectpatterns']) and is_array($params['protectpatterns'])) { $protectpatterns = $params['protectpatterns']; } if (!is_array($protectpatterns)) { $protectpatterns = array(); } //ignore check $protect_req_list = array(); foreach ($protectpatterns as $pattern) { $protect_req_list[] = '/' . str_replace('/', '\\/', $pattern) . '/'; } //$buckets = $s3->listBuckets(); //print_a($buckets); $upload_dir = $phest->getOutputPath($phest->getLang(), $buildtype); if (!is_dir($upload_dir)) { $phest->add('s3deployerror', $buildtype . 'でビルドされたファイルが存在しません'); return false; } //認証情報を読み込み if (isset($params['credentialkey'])) { $credential = $phest->getCredential($params['credentialkey']); if (!$credential) { $phest->add('s3deployerror', 'credentialkeyで指定されたキーの認証情報が読み出せません: ' . $params['credentialkey']); } else { $params = array_merge($params, $credential); } } $is_error = false; $required = array('bucket', 'region', 'key', 'secret'); foreach ($required as $rval) { if (empty($params[$rval])) { $phest->add('s3deployerror', 'オプションが指定されていません: ' . $rval); $is_error = true; } } $region_key = ''; if (!$is_error) { $regions = array('US_EAST_1', 'VIRGINIA', 'NORTHERN_VIRGINIA', 'US_WEST_1', 'CALIFORNIA', 'NORTHERN_CALIFORNIA', 'US_WEST_2', 'OREGON', 'EU_WEST_1', 'IRELAND', 'AP_SOUTHEAST_1', 'SINGAPORE', 'AP_SOUTHEAST_2', 'SYDNEY', 'AP_NORTHEAST_1', 'TOKYO', 'SA_EAST_1', 'SAO_PAULO', 'US_GOV_WEST_1', 'GOV_CLOUD_US'); $region_key = strtoupper($params['region']); if (!in_array($region_key, $regions)) { $phest->add('s3deployerror', 'regionの指定が正しくありません。regionには次の値が指定できます(大文字小文字の違いは無視されます): ' . implode(', ', $regions)); $is_error = true; } } if ($is_error) { return false; } $bucket = $params['bucket']; $region = constant('\\Aws\\Common\\Enum\\Region::' . $region_key); $access_key = $params['key']; $secret_key = $params['secret']; $phest->add('s3deploy', 'リージョン: ' . $region . ' バケット: ' . $bucket . ' ビルド: ' . $buildtype); try { $s3 = S3Client::factory(array('key' => $access_key, 'secret' => $secret_key, 'region' => $region)); } catch (\Exception $e) { $phest->add('s3deployerror', $e->getMessage()); return false; } //S3上のアップロード状況を確認 $object_flag = array(); try { $iterator = $s3->getIterator('ListObjects', array('Bucket' => $bucket, 'Prefix' => $prefix)); foreach ($iterator as $object) { if ($object['Size'] !== 0 and substr($object['Key'], -1) !== '/') { $object_flag[$object['Key']] = true; } } } catch (\Exception $e) { $phest->add('s3deployerror', $e->getMessage()); return false; } $message_option = ''; if ($dryrun) { $message_option = ' <code>[dryrun]</code>'; } //ローカルファイルをスキャンしてアップロード $file_list = File::getFileList($upload_dir); foreach ($file_list as $filepath) { $key = strtr(ltrim(substr($filepath, strlen($upload_dir)), '\\/'), '\\', '/'); //upload $keyname = $prefix . $key; try { if (!$dryrun) { //何か出力しないとブラウザ側でタイムアウトするので空白を出力 echo '<span></span>'; @flush(); @ob_flush(); $result = $s3->putObject(array('Bucket' => $bucket, 'Key' => $keyname, 'Body' => EntityBody::factory(fopen($filepath, 'r')), 'ACL' => CannedAcl::PUBLIC_READ)); } if (isset($object_flag[$keyname])) { unset($object_flag[$keyname]); $phest->add('s3deploy', '更新: ' . $keyname . $message_option); } else { $phest->add('s3deploy', '追加: ' . $keyname . $message_option); } } catch (S3Exception $e) { $phest->add('s3deployerror', 'PutObject: ' . $e->getMessage()); } catch (\Exception $e) { $phest->add('s3deployerror', 'PutObject: ' . $e->getMessage()); return false; } } //サーバーにアップされてて、ローカルにないファイルを削除 foreach (array_chunk(array_keys($object_flag), 1000) as $chunked_key_list) { $key_list = array(); foreach ($chunked_key_list as $key) { //ignore check foreach ($protect_req_list as $pattern) { if (preg_match($pattern, $key)) { $phest->add('s3deploy', '保持: ' . $key . $message_option); continue 2; } } $key_list[] = array('Key' => $key); } if (!$key_list) { continue; } try { if (!$dryrun) { $result = $s3->deleteObjects(array('Bucket' => $bucket, 'Objects' => $key_list)); } foreach ($key_list as $item) { $phest->add('s3deploy', '削除: ' . current($item) . $message_option); } } catch (S3Exception $e) { $phest->add('s3deployerror', 'DeleteObject: ' . $e->getMessage()); } catch (\Exception $e) { $phest->add('s3deployerror', 'DeleteObject: ' . $e->getMessage()); return false; } } }
//coffee $phest->registerSection('coffeescripterror', 'CoffeeScript 構文エラー', array('type' => 'danger')); //jslint $phest->registerSection('jslint', 'JavaScript 文法エラー', array('type' => 'danger')); $phest->registerSection('jscompileerror', 'JavaScript コンパイルエラー', array('type' => 'danger')); $include_vars_list = array(); foreach ($vars_yaml['includes'] as $ipath) { $ipath = $dir_source . '/' . $ipath; if (file_exists($ipath)) { $phest->addWatchList($ipath); $include_vars_list[] = $ipath; } else { $phest->add('builderror', 'vars.yml インクルードしようとしたファイルは存在しません: ' . $ipath); } } $phest->addWatchList(File::getFileList($dir_source)); //phest pluginを処理 $loaded_plugins = array(); foreach ($plugin_list as $idx => $pdat) { $plugin_name = $pdat['name']; $plugin_params = $pdat['params']; if ($phest->loadPlugin($plugin_name)) { $loaded_plugins[$plugin_name] = true; $watch_func_name = 'ChatWork\\Phest\\plugin_watch_' . $plugin_name; if (function_exists($watch_func_name)) { $loaded_plugins[$plugin_name] = $watch_func_name($plugin_params, $phest); } } } if ($watch and !$phest->hasNew()) { exit;