🎋

Azure DevOpsで複数のOrganizationをまたいでソースを共有・参照する

2023/09/03に公開
2

複数のOrganizationでプロダクトコードの共有・参照がしたい

Azure DevOpsを使って以下のような要件をクリアするソースコード管理計画を考えることになりました。

背景

  • 複数のAzure DevOpsのOrganization, PJでプロダクトの開発をしている
  • Organization AlphaはProject AlphaというPrivate PJを持ち、プロダクトのメインのアセットを開発している。アセットのプロダクトコードはProject Alpha内のAzure Reposで管理されている。
  • Organization BravoはProject BravoというPrivate PJを持ち、Organization Alphaが開発したアセットをベースに別ドメインにカスタマイズされた機能の追加、拡張を行う。
  • Project Bravoのようにドメインごとにアセットをカスタマイズして機能拡張、追加を行うProjectは今後どんどん増える。

要件

  1. そのため、Organizaion BraboはProject Alpha内のAzure Repos内のアセットの最新のプロダクトコードをpullして参照するようにしたい。
  2. Project Alpha内のReposの内容は外部のOrganization, Projectからの変更によって一切汚されてはならない。

Bravoでのソースコード管理の要件:

  1. AlphaからCloneしたソースは常にすぐに見れる状態であること
  2. Bravoで開発しているプロダクトのコードにAlphaからCloneしたソースが混じってはいけない。AlphaからCloneしたソースとBravoで開発中のソースは明確に分離されてなくてはならない。
  3. 必要に応じて、Bravoで開発中のプロダクトにAからCloneしたソースをmergeできること

セキュリティ的・技術的な制約事項:

  1. できるだけAzure DevOps縛りで要件をクリアすること
  2. Alpha, Bravoは必ずそれぞれ別のOrganizationでホストされなければならない(Organization AlphaでProject Bravoをホストするような形に変えてはならない)
  3. Alpha, Bravoは必ずPrivateでなければならない。Publicにしてはならない。

解決方法を考えてみる

複数のPJの間でソースコードをやり取りする方法として一番はじめにパッと思いついたのはForkを使う方法です。
https://learn.microsoft.com/ja-jp/azure/devops/repos/git/forks?view=azure-devops&tabs=visual-studio

しかし、Azure DevOpsでForkできるのは同じOrganization配下にいるPJ同士です。別OrganizationにいるPrivate ProjectのReposをForkするのは無理です。
正直ForkでクリアできるようにOrganization Alpha配下にProject Alpha, Bravoがいる状態にしてForkできるようにする方が楽です。
でもこれは制約事項の2に反するのでダメです。というわけでFork案はボツ。

Forkより簡単な方法としてはProject AlphaをPublic Projectにしてしまえば、Bravoからも、今後増えるであろうCharlieやDeltaからも参照できるね!って方法ですが、これも制約事項の3に引っかかるのでダメです。

次に思いついたのは、もうすべてのソースコードをGitHub Enterpriseに移してしまう、という方法ですが、これもできるだけAzDO縛りでという制約事項1に引っかかるのでできればAzDO縛りでなんとかしたい、、、、

そうだ、PATがある

絶望してもう無理じゃん、、、?となってましたが下記のような感じでPAT(Personal Access Token)を使えばいけるのでは?となりました。

  1. Orgaization Alphaで他のOrganization/Projectから参照するときに使うPATを作成
  2. 1で生成したPATを使って、BravoでAplphaのReposをremote Repositoryとして登録してBravoのブランチにpullする

とりあえず試してみることにします。

PATについて詳しくはこちらをご覧ください。
https://learn.microsoft.com/ja-jp/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows

1. Organization AlphaでPATを作成

■作業環境:Alpha
Organization Alphaのリソースに外部からアクセスできるように、Organization Alphaを他Organization/Projectから参照するときに必要になるPAT(Personal Access Token)を生成します。

Organization Alphaのユーザー設定 > Personal Access Tokenを選択

+ New Tokenを選択

PAT名とアクセス可能なOrganization、有効期限を設定

Nameで任意のPATの名前をつけて、OrganizationでOrg-Alphaを選択します。

Expriration(UTC)でPATの有効期限を設定します。
デフォルトでは30日ですが、1ヶ月だとちょっと短くてメンテが大変なので、一旦Maxの1年にしておきます。

Custom definedにするとこんな感じで有効期限をカスタムで選べます。1年以上は指定できません。(2023/09/03時点)

アクセススコープを設定

次に、PATを使ってアクセス可能な範囲を設定します。
今回は、以下のような要件があるため、

  1. Organizaion BraboはProject Alpha内のAzure Repos内のアセットの最新のプロダクトコードをpullして参照するようにしたい。
  2. Project Alpha内のReposの内容は外部のOrganization, Projectからの変更によって一切汚されてはならない。

最小特権の原則から考えると、外部からOrganization Alphaのリソースに対しては「ReposのCodeの参照のみ許可、編集以上は禁止」が妥当な設定になるので、ScopeではCusom definedを選び、
Codeの項目をReadに設定します。
※Reposへのアクセス許可はCodeの項目で管理されます)

これで、要件の1, 2をクリアできるようなPATの設定が完了です。
Createを押下してPATを作成します。

PATが無事に作成されました。

どうしても忘れてしまった場合は、Regenerateで再生成してください。

2. PATを使ってBravoからAlphaのReposのソースをPull

■作業環境:Bravo

背景を思い出します。

Organization BravoはProject BravoというPrivate PJを持ち、Organization Alphaが開発したアセットをベースに別ドメインにカスタマイズされた機能の追加、拡張を行う

とあるので、BravoでAlphaのReposにいるプロダクトコードを見れるようにするため、
BravoのRemote RepositoryにAlphaのReposを追加してalpha-baseブランチにpullします。

BravoでAlphaのReposをRemote Repositoryに追加

Alphaで作成したPATを使ってAlphaのReposをBravoのRemotoe Repositporyに追加

$ git remote add {Repos名} https://{YOUR_PAT}@dev.azure.com/{YOUR_ORGANIZATION_NAME}/{YOUR_PROJECT_NAME}/_git/{YOUR_REPOS_NAME} {BRANCH_NAME}

// {YOUR_PAT}:Organization Alphaで生成したPAT
// {YOUR_ORGANIZATION_NAME}:参照したいソースがあるOrganizationの名前
// {YOUR_PROJECT_NAME}:参照したいソースがあるProjectの名前
// {YOUR_REPOS_NAME}: 参照したいソースがあるRepositoryの名前

ちゃんとRemote repositoryに追加出来てるか下記コマンドで確認

$ git remote

Bravoのブランチ戦略を考える

■作業環境:Bravo
Bravo→AlphaへのService connectionの作成、BravoでのAlphaのReposのImportが完了したので、次はBravoのPJ内で安全にソースコードを運用していくためのブランチ戦略を考えてみます。
要件はこんな感じだったので、これを達成するようなブランチ戦略を考えてみます。

Bravoでのソースコード管理の要件:

  1. AlphaからCloneしたソースは常にすぐに見れる状態であること
  2. Bravoで開発しているプロダクトのコードにAlphaからCloneしたソースが混じってはいけな>い。AlphaからCloneしたソースとBravoで開発中のソースは明確に分離されてなくてはならない。
  3. 必要に応じて、Bravoで開発中のプロダクトにAからCloneしたソースをPullできること

こんな感じにしてみます。

main(Bravoでプロダクト開発を行うためのbranch) ←alpha-baseをmerge : これをdefaultとする
 └── alpha-base: ここにReomote Reposとして登録したAlphaからプロダクトコードをpullする : これはlockする

alpha-baseをロックすることにより、Alphaからpullしたプロダクトコードのみを入れるalpha-baseは他branchからの変更から守られ、常にクリーンな状態を保つことができます。
AzDOでのブランチのデフォルト化、lock/unlockは、設定したいブランチの三点リーダーのMore Optionの箇所から設定できます。

これで、Bravoでのソースコード管理要件をクリアできます。

BravoからAlphaのソースコードをpullするときの運用はこんな感じになります。

  1. alpha-baseにAlphaからの変更をpull
  2. 必要に応じて main に alpha-base の変更をマージして調整・確認を行う。

これじゃalpha-baseとmainを統合するときにめちゃくちゃ慎重にならないといけない、、、
もう少し統合のコストが高くても変更に対する防御力高めの戦略がお好みの場合は、
こんな感じで統合専用のintegrationブランチを挟んでもいいでしょう。

main(Bravoでプロダクト開発を行うためのbranch) ←integrationをmerge : これをdefaultとする
  └── integration: ここでmainとalpha-baseを統合する
 └── alpha-base: ここにReomote Reposとして登録したAlphaからプロダクトコードをpullする : これはlockする

PATを使用してBravoにAlphaのReposをRemote Reposとして追加

では、いよいよBravoからAlphaの最新のソースコードを取得します。

■作業環境:Alpha
検証のため、Alphaに適当に変更を入れます。
今回はこんな感じでReadMe.mdに変更を加えてAlphaのReposのmainにpushします。

■作業環境:Bravo alpha-base branch
では、Bravoのapha-baseにAlphaからの変更を取り込みます。
さっきのブランチ戦略に基づき、Alphaのソースコードをpullするためのブランチ、alpha-baseに切り替えます。

alpha-baseにcheckoutしたら、以下のコマンドでAlphaのmainにいるソースをpullします。

git pull {YOUR_REMOTE_REPO_NAME} {BRANCH_NAME}

// {YOUR_REMOTE_REPO_NAME}:取得したいremote repositoryの名前
// {BRNCH_NAME}:取得したいremote branchの名前

はい、無事にBravoにAlphaの変更を取得することができたのでBravoのmainに変更をPushします。

成功!

まとめ

こんな感じでPAT作って使えばOrganization間でのリソースの参照が可能になります。
複数のOrganization間でのリソースのアクセスを許可する際には「何ができてればいいのか」「何をさせたくないか」をポイントに最小特権の原則に基いてセキュリティ面に考慮したアクセス制限の構成、また各Reposを好ましくない変更から守れるようなブランチ戦略、ブランチポリシーの設定を行って下さい。

Discussion

yuriemoriyuriemori

冷静に考えたらService Connectionいらなかったのであとで編集します

yuriemoriyuriemori

service connectionはいらなかったのでその手順を削除。
Bravo→Alphaでの参照方法として、BravoのRemote RepositoryにAlphaのReposをPATを使って追加する方法に変更。
Bravoでのブランチ戦略をよりシンプルな方法に変更。