私の現在の職場での開発について少しお話しします。
アジャイル開発の方法論を使用します。最初にスクラムを実践し、現在はかんばんに取り組んでいます。 当初、私自身はそのような出来事についてかなり懐疑的でしたが、ほんの数週間後にはうまくいくと確信しました。
このような開発プロセスの説明は、1つだけではなく、大きな投稿のトピックです。さらに、ネットワーク上に大量の文献があるため、ここに何があるかについては説明しません。反復の完了後(反復時間はチーム自身が選択し、通常1から3週間かかります)、かんばんの場合、機能は実行された直後にプロダクションで起動されます(もちろん、テストされます)。
頻繁なリリースは単に優れているだけでなく、優れています。合理化された頻繁なリリースプロセスにより、開発者は更新を恐れず、顧客は進捗を確認できます。
この開発プロセスは継続的インテグレーションと重複しています。 彼についても、本や長い記事が簡潔に書かれています-これは、統合問題の最も迅速な特定と解決のためのプロジェクトの頻繁な自動アセンブリの実装です( wikipedia )。
分散システムを開発しています。バックエンド(API)としてのperl、javascriptで記述されたクライアントコード、および継続的統合サーバーとしてのjenkins ciがあります。
それに慣れていない人のために、私は指でジェンキンとは何かを説明します。それは、アセンブリのタスクが設定されるウェブインターフェースを備えたサービスです。 タスクは、パッケージをビルドするためにサーバーが実行する必要があるものに関するステップバイステップの指示であり、この場合はrpmです。 たとえば、これは通常次のように発生します。
- VCS(バージョン管理システム)からチェックアウトします。
- テストを実行します。
- 必要なファイル構造をコンパイルおよびアセンブルします。
- rpmファイルにパックします。
- リポジトリに入れます。
rpmパッケージを作成するには、 specファイルを書き込む必要があります 。これは、宛先マシンでパッケージをビルドおよびインストールするための一連の指示でもあります。
そのため、rpmパッケージがビルドされるCIサーバーがあり、そのパッケージはyumリポジトリーに入り、パッケージがインストールされる宛先サーバーまたはサーバークラスターがあります。
このプロジェクトでは、CPANでモジュールを使用します。コードを再利用するのは良いことですが、オーバーヘッドが伴うため、多くの人がperlを嫌います。
依存関係
例を考えてみましょう。特定のハッシュアルゴリズムを使用する必要がありました。タスクはかなり簡単です。CPANでモジュールを取得し、開発環境に配置します。
# cpanm Some::CPAN::Module
その後、コードを記述します。
use Some::CPAN::Module; sub encrypt { my $string = shift; return Some::CPAN::Module::mkHash($string); }
生地で覆います:
ok(encrypt("test") eq Some::CPAN::Module::mkHash("test"), "encrypt function");
コードが機能し、テストの対象になっているため、私たちは非常に満足しています。 彼をコミットし、パッケージを収集しようとします。 アセンブリは私たちの心の中に構成されています:パッケージを組み立てる段階で、単体テストが起動されます。これは非常に便利です。テストが失敗した場合、それは悪いコードを意味し、それ以上収集する意味がありません。
そして問題はここにあります:テストは失敗します-ビルドサーバーにモジュールは必要ありません。
または別の状況:テストがないため、このコードはパッケージをリポジトリに残し、開始されていないサービスを取得しますが、既に本番サーバーでエラーをキャッチするのははるかに困難です。
テストをビルドして合格するには、specファイルに依存関係を追加します。
BuildRequires: perl-Some-CPAN-Module
移行先サーバーに展開するには、次を追加します。
Requires: perl-Some-CPAN-Module
運がよければ、必要なrpmはすでにyumリポジトリにあります。そうでない場合は、パッケージを収集してyumリポジトリに配置する必要があります。
そのため、リポジトリ内のパッケージはビルド/プロダクションサーバーに配置されますが、1つの問題があり、バージョンが異なります:コードとテストを書いている間に、モジュール作成者は自分のモジュールの重大な脆弱性を修正し、突然何らかの理由で新しいバージョンをリリースしました前のものと互換性がなくなり、テストはまだ失敗し、アセンブリは失敗し、サービスは開始しません。
解決策:コードが動作するモジュールのバージョンを確認し、このバージョンでrpmを収集し、speファイルでモジュールの正確なバージョンを指定します。
BuildRequires: perl-Some-CPAN-Module = 1.41 Requires: perl-Some-CPAN-Module = 1.41
CPANを含むモジュールに独自の依存関係がある場合、別の問題が発生する可能性があります。たとえば、Some :: CPAN :: Moduleは、他の:: CPAN :: Moduleに依存するため、バージョンパッケージを再度アセンブルしてインストールした後、開発環境とビルドサーバーに依存します別れ、テストに失敗しても、サービスは開始されません。 また、実際のプロジェクトには、このようなモジュールが12個以上存在する可能性があります。 狭い円では、これは中毒のクラゲと呼ばれます。
解決策:依存関係の依存関係を追跡し、それらのすべてを仕様ファイルで指定することもできますが、この解決方法では追跡とその後のアセンブリに多大な労力と時間が必要です。 これは開発方法論で制限されています。
別の解決策も考えられます。たとえば、 pintoを使用して独自のCPANミラーを上げることですが、これはこの記事のトピックではありません。
別の解決策があります。
CPANの主な問題は、CPANが長い間発明されており、少なくとも一度CPANにモジュールをレイアウトした人なら誰でも私が書いていることを理解しているということです。 幸いなことに、perlの最近のツールが登場し始めました。
カートン
カートンと呼ばれるツールについてお話したいと思います。 著者の宮川達彦は、 スターマンやcpanmなどの便利なユーティリティの著者でもあります。
カートンとは何ですか? これは、真珠モジュールの依存関係マネージャーです。 RubyのBundlerの影響下で書かれました。
その本質は、依存関係が宣言されているプロジェクトディレクトリにファイルが作成されるという事実に要約されます-cpanfile 。 このファイルでは、開発者は必要なモジュールとそのバージョンをリストします。
requires 'Some::CPAN::Module', '1.45';
その後、コマンドが実行されます:
carton install
そして、必要なモジュールがlocal / libディレクトリに置かれ、cpanfile.snapshotも作成されます。このファイルには、CPANとともにインストールされたモジュールに関する情報が保存されます。 このファイルはVCSにも追加する必要があります。これにより、後でビルドサーバーでスナップショットからカートンインストールの依存関係が開始され、環境のIDが保証されます。
ここで必要なことは、ローカル/ libディレクトリを
@INC
追加すること
@INC
です。
必要な正確なバージョンまたは有効なバージョンの範囲を指定できます。
requires 'Some::CPAN::Module', '>= 1.41, < 1.46';
さらに、さまざまな環境に固有のモジュールを指定できます。例:
osname 'MSWin32' => sub { requires 'Win32::File'; }; on 'test' => sub { requires 'Test::More', '>= 0.96, < 2.0'; recommends 'Test::TCP', '1.12'; }; on 'develop' => sub { recommends 'Devel::NYTProf'; };
カートンは、同じ著者のもう1つの便利なユーティリティであるcpanmとハーネスで動作します。モジュールを直接インストールしてくれたことに感謝することができます。
cpanfileにすべての依存関係があり、cpanfile.snapshotに開発環境のスナップショットがあり、これらすべてがspecファイルのVCSに配置されているので、テストを実行する前にcarton installコマンドを追加できます。
パッケージをrpmパッケージの対象となるサーバーに展開するときに、同じコマンドをインストールステージに追加できます。
しかし、さらに進んだ。
カートンの作成者は、ユーティリティが次のように機能するというビジョンを持っています。
# cap carton install
インターネットまたはローカルCPANミラーから依存関係の全体をダウンロードする必要があるのは少し奇妙ですが、これにはかなり時間がかかりますが、その時点でネットワークに問題があった場合はどうでしょうか。
もっと一貫性のある方法があり、rpmパッケージのビルド段階でモジュールをインストールできます。 そして、すべての依存関係を一度に配置するüber-rpmパッケージを作成することにしました。 このパッケージは、コードとのパッケージ依存関係として宣言されており、アセンブリ中およびテスト中のテストに合格するためにビルドサーバーにインストールできます。
このアプローチは、たとえばscalaのプロジェクトで一般的です。すべてのプロジェクトの依存関係とコードをさらに進めるüber-jarが作成され、すべての依存関係が既にコンパイルされたüber-binaryが作成されます。
ビルドプロセスのセットアップと自動化が完了したので、リリースと依存関係のクラゲを恐れることはできませんが、生成するアルゴリズムと製品に焦点を当てます:)