開発の自動化について長い間話していません。 したがって、今回は、リリース時間を3日間から1日間に短縮し、プロセスからエラーの可能性がある人の参加を削除する方法について説明します。
長くて厄介な道について話すことは常に困難です。 しかし、近年、Yandex.Money開発インフラストラクチャは、私たちにとって最も重要なプロセスであるリリースという自動化に向けて大きな一歩を踏み出しました。これは単なる罪ではありません。 実際、 Bitbucket 、 Jenkins 、 Jiraの束に基づいて、継続的インテグレーションと継続的デリバリの完全なソリューションが判明しました。
誰がそれをすべて必要としますか
Yandex.Moneyの開発では、継続的インテグレーションと継続的デリバリ(CI / CD)のプロセスが比較的長い間使用されてきたため、小さなバッチで生産への変更を配信し、高いリリースペースを維持できます。
基本的に、これはソフトウェア開発への単なるアプローチです。
継続的インテグレーションには、頻繁な自動化されたプロジェクトビルドが含まれ、インテグレーションの問題を迅速に特定します。 常に最新のテスト対応バージョンの製品を使用できます。
- 継続的配信には、「戦闘」システムへの更新の頻繁な配信が含まれます。 製品は現在のバージョンでサポートされており、各リリースでは変更の量が少ないため、更新中のエラーは追跡しやすくなっています。
一般的に、誰もが複雑なリリースプロセスを必要とするわけではありません。 たとえば、スタートアップにとっては不必要な段階が多いため、スタートアップにとって有用ではない可能性があります。スタートアップが集まり、すべてを狭い円で議論するのが簡単です。 ただし、これが構造内でうまくいかず、リリースプロセスが不十分であるために、一度に数十の重要な変更が同時に発生するとすぐに脅かされる場合は、開発の自動化を検討する価値があります。
さらに、自動化されたプロセスにより、チームの労力を大幅に削減できます。 CI / CDの自動化を行わないと、人為的エラーや多くの手動操作が発生する危険があります。 たとえば、タスク管理とBitbucketリポジトリとの統合に最適な人気のタスクトラッカーJiraを使用していますが、その助けを借りてリリースサイクルを自動化することは困難です。 したがって、ジェンキンス以前の開発プロセスは次のようになりました。
Yandex.Moneyのリリースプロセス。
タスク開発とバグ修正は、 Successful Git Branching Modelを使用して行われ、テストはFeature Branchで行われました。 受け入れテストのリリース候補版の準備中に、手動操作のすべての地獄が起こりました。 開発者は次の手順を完了する必要がありました。
devでリリースブランチをカットして、次のリリースを準備します。
将来のリリース候補版のコードを収集します。
コミットに関するコメントから、リリースに含まれるすべてのJiraタスクを見つけ、Jiraのリリースに添付します。
ロードおよび受け入れテスト用にチケットをJiraで作成します。
- 最後に、リリースを担当するマネージャーは、チケットに関連付けられたすべてのタスクがテストされ、テスト後またはテスト中に表示されないことを確認する必要がありました。
これら5つのポイントの開発と責任者とのリリースの承認により、1日から1週間かかりました。 これは永遠に続くことができなかったので、 Jenkinsでのこのプロセスの自動化がすぐに登場しました。
自動化するもの
4年前、私たちは何かを変える時だと気付きました。システムのサイズ、従業員の数、バトルサーバーの変更が目の前に増えていました。 2014年以降、リリース数は3倍に増加しました-1か月あたり45個から150個です。
そのとき、私たちは次の荷物を持って走りました:
支払いサービスは、いくつかのモノリスで構成されていました。
必須の自動テストはありませんでした。
- 自動化されたコードレビューとアプリケーションの展開はありませんでした。
実稼働環境への展開のためにリリースを承認した後、運用エンジニアのグループが働き始めました。 支払いサービスのコンポーネントはクラスター構成で機能するため、各コンポーネントの更新プログラムの展開により、数十回の反復が発生しました。 いくつかの環境でリリースを展開するだけで、毎日5人が使用していました。
これにより、リリースが少なく、スタッフが会議室に集まり、すべてを迅速に話し合い、調整できるようになります。 しかし、ある時点でそれは深刻な問題となり、リリースのペースを速めるのにブレーキをかけました。 開発プロセスを再考する長い旅を始めました。これは次のように要約できます。
実際、完全に自動化されたリリース準備プロセスでも、運用部門の生産性に出くわすため、ペースを大幅に上げることはできません。ある時点では、1つの更新プログラムのみを展開するのが慣例です。 これは、リリースにより発生する可能性のあるエラーの診断を容易にするために行われます。
運用に移行するためのリリースの作成とテストだけでなく、 展開自体も自動化する必要があることがわかりました。 つまり、開発と運用の一部のプロセスを改善することです。 操作を自動化する最初の試みは、以前の記事の1つで説明されただけでした。この経験は役に立ち、ミスが技術的な解決策を思い起こさせました。 現在、ほとんどのコンポーネントに実装されており、将来、別の出版物の理由になる可能性があります。
なぜジェンキンス
以前はJetBrains Teamcityを使用してコードを構築していましたが、開発者とサービスの数の増加は、Yandex.Moneyのこのようなソリューションの経済的不便さを示していませんでした。 したがって、彼らはオープンソースに目を向け、「第2バージョン」として、オープンで無料のJenkinsに基づいて同等のことを行いました。
自動化タスクは次のとおりです。
動的なJenkinsタスクの生成。 コンポーネント内のコンポーネントとブランチのレベルでタスクを作成して最新の状態に保つことができます。
テストの準備 :
リリースブランチの切断。 BitbucketのJenkinsパネルのボタンは、devブランチから新しいリリースブランチを作成します。このブランチには、開発者からのすべての変更が既に追加されています。
テスト用のアセンブリ。 別のスクリプトがテスト用のパッケージを収集します。 JenkinsはJiraでRLチケットを作成し、説明に適した開発者タスクをバインドします。
- このスクリプトは、受け入れテストと統合テストのタスクを生成します。 Jenkinsは、リリースに含まれるタスクのすべてのオブザーバーにリリース情報を記載した電子メールを送信します。
本番展開 :
実稼働環境での展開用にビルドします。 開発者のチームでは、Jenkinsはリリースブランチのコードをマスターに、マスターから開発者に追加し(開発者が最新バージョンを入手できるように)、展開用のパッケージを作成します。
- ビルド後、JenkinsスクリプトはJiraでタスクを作成して運用部門のリリースを展開し、担当者に送信します-運用環境にアップロードできます。
各段階をより詳細に分析します。
Jenkinsの動的タスク生成
新しいタスク記述ファイルをコンポーネントリポジトリに追加すると、Jenkinsはそのタスクのアセンブリタスクを自動的に作成します。 SyncBitbucketメカニズムがこれを担当し、その実例はGithubにあります。
Bitbucketとの相互作用は、APIとJenkinsを介して行われます-Job DSLプラグインを使用します。
動的生成の手順は次のとおりです。
Bitbucket同期タスクを手動で作成します(ファイルsynchronizeBitbucket.groovy )。 タスクはBitbucketプロジェクトを実行し、個々のプロジェクトを同期するためのタスクを生成します。 プロジェクトとは、目的が似たエンティティ(サービス、ライブラリ、gradleプラグイン)があるリポジトリのセットです。 新しいプロジェクトの出現を追跡できないため、このタスクはスケジュールに従って実行されます。
プロジェクトを同期するためのタスク(ファイルsynchronizeProject.groovy )もスケジュールに従って起動され、リポジトリを検索し、各リポジトリを同期するためのタスクを作成します。
- リポジトリを同期するタスク(ファイルsynchronizeRepo.groovy )は、メカニズムの主要部分です。 その目標は、すべてのブランチを調べて、ブランチ内のスクリプトファイルを見つけてタスクを生成し、実行することです。 タスクは、リポジトリにコミットすることで起動されます。
タスクを生成するためのスクリプトは、 JobDSLplugin形式で記述されています。 開発者が新しいタイプのタスクをJenkinsに追加するには、リポジトリのルートディレクトリの\ Jenkinsフォルダーにjenkins_プレフィックスを持つファイルを配置するだけです。 タスク作成スクリプトでは、たとえば、Jenkinsのブランチ名、リポジトリアドレス、ディレクトリアドレスなど、リポジトリ同期メカニズムによって提供されるデータを使用できます。
リリースブランチをカットするタスクの説明の例:
folder(jobParams.jenkinsDirectory) if (jobParams.gitBranch != "dev") { return } job(jobParams.jenkinsDirectory + "/createReleaseBranch") { jdk('jdk1.8.0') scm { git { remote { url(jobParams.gitRepoUrl) refspec('refs/remotes/origin/*') branches("**/$jobParams.gitBranch") } } } steps { gradle { makeExecutable(true) description(' ') tasks(':createReleaseBranch') } } }
同様のメカニズムにより、最小限の労力でコンポーネントごとにリリースサイクルの段階を実装することができました。 Travis CIに類似していることがわかり 、各ブランチについて、独自のアセンブリセットを作成できます。
試験準備
Jenkinsでリリースサイクルを自動化するには、リリースサイクルの各段階で「起動ボタン」のように見えるいくつかのスクリプトを作成する必要がありました。
createReleaseBranch-リリースブランチの切断。
- prepareReleaseForTesting-テストリリースのアセンブリ、テスターへの問題の説明。
スクリプトは、各コンポーネントの動的なタスク生成の段階で作成されます。 つまり、リリースサイクルの1つまたは別の段階の開始は、リリースの準備が行われているコンポーネントの特定のスクリプトの起動を意味します。
devブランチからcreateReleaseBranchを実行すると、Bitbucketにリリースブランチが、Jenkinsに別のフォルダーが形成されます。 フォルダの名前は、「release_version」スキームに従って自動的に選択されます。
次に、プログラマーは新しいフォルダーに移動し、 そこで別のprepareReleaseForTestingスクリプトを実行する必要があります 。このスクリプトは更新パッケージを収集し、リリースアセンブリに関する通知を関係者全員に送信します。 さらに、受け入れテストとストレステストタスクがJiraで作成されます。
テストのために新しいリリースを送信した直後に、すべての関係者にそのことを伝える必要があります。 そのため、プロダクトマネージャーは、事前にマーケティングとPRに同意し、ラインマネージャーは何が起きているのかを把握し、テクニカルサポートはユーザーの質問に対する回答を導き出すことができます。
RLは、リリースの説明が記載されたチケットであり、このリリースに含まれるタスクへのリンクが含まれています。
INT-リリースの受け入れテストのタスク。
- LOAD-負荷テストのタスク。
これらすべてを実現するには、ジェンキンスをジラと友達にすることが重要でした。 ここでは、Bitbucketのコード変更に対する開発者のこのような説明がよく見られるため、全体の問題は組織の問題にかかっています。
「ボタンが画面からクロールすることがある-修正済み」;
「上部にストリップを追加」;
- 「数字のチェックを修正しました。誓う必要はもうありません。」
このような説明では、Jiraでのタスクコードの変更の種類を理解することは困難です。 そのため、まず、Bitbucketの変更に関するコメントにタスク番号が含まれることに開発者に同意しました(たとえば、「BACKEND-186 Fixedメールの送信」)。 開発者はGitとBitbucketの履歴を分析するために必要であるため、この数値は以前のものでしたが、今では重要になっています。
人的要因が有効になり、誰かがそれを忘れた場合-ジェンキンスは一般的なリリースレターにコメントを「そのまま」追加し、たとえば、プロジェクトマネージャーがタスクをJiraのRLに割り当てます。
展開
Jenkinsの次の2つのタスクは、展開プロセスを担当します。
mergeToMaster-リリースブランチのテスト済みコードとマスターのマージ。
- prepareReleaseForProduction-マスターからのリリースのアセンブリおよび運用チームへの展開タスクの設定。
テスト後、責任者はJenkinsのリリースフォルダーに移動し、mergeToMasterスクリプトを実行します。これにより、Bitbucketでmerge release-> masterおよびmaster-> devが実行されます。
最終段階-生産のためのアセンブリが残ります。 prepareReleaseForProductionスクリプトがこれを担当します。これは、.DEBパッケージを収集し、タスクを運用部門に設定し、リリースの準備ができてアップロードできることを担当者に伝えます。
リリースサイクルを自動化する開発プロジェクトとして、テストフェーズをさらに完全に自動化するために、テスト部門で統合テストとのリンクを構築しています。 開発者がリリースをより頻繁にリリースするために、Jenkinsに1日に1回、devブランチの新しいタスクに関する通知を自動的に送信するように指示しました。 さらに、これにより、開発者、テスター、およびシステム管理者が将来の自動リリースカットに備えることが期待されています。
リリースへのアプローチについて知りたい-ヒューマンエラーにどのように対処しますか、安定したリリース率を維持していますか?