[{"data":1,"prerenderedAt":17347},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-GitHub":397},[4,192,200],{"title":5,"_path":6,"children":7,"icon":191},"Blog","/posts",[8,11,14,17,20,23,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,77,80,83,86,89,92,95,98,101,104,107,110,113,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,167,170,173,176,179,182,185,188],{"title":9,"_path":10},"Testing your API with REST Client","/posts/testing-your-api-with-rest-client",{"title":12,"_path":13},"HTML templating in Xamarin","/posts/html-templating-in-xamarin",{"title":15,"_path":16},"Goodbye Azure Portal, Welcome Azure CLI","/posts/welcome-azure-cli",{"title":18,"_path":19},"Coming across Gitpod","/posts/gitpod",{"title":21,"_path":22},"Handle token retrieval while querying an API","/posts/delegating-handler",{"title":24,"_path":25},"Clean up your local git branches.","/posts/cleaning-git-branches",{"title":27,"_path":28},"Automate configuration of Teams Tab SSO with PowerShell.","/posts/teams-sso-powershell",{"title":30,"_path":31},"How to do a technology watch? - Part 1","/posts/technology-watch-part1",{"title":33,"_path":34},"How to do a technology watch? - Part 2","/posts/technology-watch-part2",{"title":36,"_path":37},"You almost no longer need Key Vault references for Azure Functions.","/posts/azure-functions-custom-configuration",{"title":39,"_path":40},"How to do a technology watch? - Part 3","/posts/technology-watch-part3",{"title":42,"_path":43},"Forget DevOps, the future is already here!","/posts/devops-future",{"title":45,"_path":46},"Week 9, 2021 - Tips I learned this week","/posts/w09-2021-tips-learned-this-week",{"title":48,"_path":49},"Week 12, 2021 - Tips I learned this week","/posts/w12-2021-tips-learned-this-week",{"title":51,"_path":52},"Week 14, 2021 - Tips I learned this week","/posts/w14-2021-tips-learned-this-week",{"title":54,"_path":55},"Once upon a time in .NET","/posts/once-upon-a-time-in-dotnet",{"title":57,"_path":58},"Install your applications with winget","/posts/winget-import",{"title":60,"_path":61},"Customize your applications when installing them with winget","/posts/winget-override",{"title":63,"_path":64},"Week 22, 2021 - Tips I learned this week","/posts/w22-2021-tips-learned-this-week",{"title":66,"_path":67},"How to connect to an Azure SQL Database from C# using Azure AD","/posts/sqlclient-active-directory-authent",{"title":69,"_path":70},"Producing packages for Windows Package Manager","/posts/wingetcreate",{"title":72,"_path":73},"4 tips about GitHub Actions environment variables and contexts","/posts/github-actions-var-and-context",{"title":75,"_path":76},"AzureWebJobsStorage, the secret you don't need in your Function App.","/posts/azure-functions-without-azurewebjobsstorage",{"title":78,"_path":79},"ASP.NET Core - Lost in configuration","/posts/lost-in-configuration",{"title":81,"_path":82},"Week 39, 2021 - Tips I learned this week","/posts/w39-2021-tips-learned-this-week",{"title":84,"_path":85},"Week 41, 2021 - Tips I learned this week","/posts/w41-2021-tips-learned-this-week",{"title":87,"_path":88},"Migrating and open-sourcing my blog","/posts/migrating-blog",{"title":90,"_path":91},"Week 45, 2021 - Tips I learned this week","/posts/w45-2021-tips-learned-this-week",{"title":93,"_path":94},"Organize your GitHub stars with Astral","/posts/astral",{"title":96,"_path":97},"Pulumi with an Azure Blob Storage backend","/posts/pulumi-azure-backend",{"title":99,"_path":100},"IaC Hot Reload with Pulumi Watch","/posts/pulumi-watch",{"title":102,"_path":103},"Week 2, 2022 - Tips I learned this week","/posts/w02-2022-tips-learned-this-week",{"title":105,"_path":106},"Week 3, 2022 - Tips I learned this week","/posts/w03-2022-tips-learned-this-week",{"title":108,"_path":109},"Week 5, 2022 - Tips I learned this week","/posts/w05-2022-tips-learned-this-week",{"title":111,"_path":112},"How to provision an Azure SQL Database with Active Directory authentication","/posts/sqldatabase-active-directory-authent",{"title":114,"_path":115},"Why will I choose Pulumi over Terraform for my next project?","/posts/pulumi-vs-terraform",{"title":117,"_path":118},"Week 19, 2022 - Tips I learned this week","/posts/w19-2022-tips-learned-this-week",{"title":120,"_path":121},"Week 20, 2022 - Tips I learned this week","/posts/w20-2022-tips-learned-this-week",{"title":123,"_path":124},"Keeping secrets secure when using API Clients","/posts/http-clients-secrets",{"title":126,"_path":127},"What made me want to be a developer?","/posts/be-a-developer",{"title":129,"_path":130},"What can we do when stuck with a programming problem?","/posts/get-unstuck",{"title":132,"_path":133},"How did I automate the setup of my developer Windows laptop?","/posts/automate-developer-machine",{"title":135,"_path":136},"Discussion about API clients","/posts/http-clients",{"title":138,"_path":139},"Week 46, 2022 - Tips I learned this week","/posts/w46-2022-tips-learned-this-week",{"title":141,"_path":142},"When Pulumi met Nuke: a .NET love story","/posts/when-pulumi-met-nuke",{"title":144,"_path":145},"A year of learning and sharing - Dev Retro 2022","/posts/2022-retro",{"title":147,"_path":148},"Perform Dynamic Execution of an npm Package","/posts/pnpm-dlx",{"title":150,"_path":151},"Manage multiple Node.js versions","/posts/pnpm-env",{"title":153,"_path":154},"Introducing the Vue.js CI/CD series","/posts/vuecicd-introduction",{"title":156,"_path":157},"Execute commands using your project dependencies","/posts/pnpm-exec",{"title":159,"_path":160},"Vue.js CI/CD: Continuous Integration","/posts/vuecicd-ci",{"title":162,"_path":163},"Who is using pnpm?","/posts/pnpm-who-is-using",{"title":165,"_path":166},"Create an Azure-Ready GitHub Repository using Pulumi","/posts/azure-ready-github-repository",{"title":168,"_path":169},"Deploying to Azure from Azure DevOps without secrets","/posts/ado-workload-identity-federation",{"title":171,"_path":172},"Effortlessly Configure GitHub Repositories for Azure Deployment via OIDC","/posts/scripting-azure-ready-github-repository",{"title":174,"_path":175},"Playing with the .NET 8 Web API template","/posts/playing-with-dotnet8",{"title":177,"_path":178},"Another year of sharing and learning - Dev Retro 2023","/posts/2023-retro",{"title":180,"_path":181},"Week 4, 2024 - Tips I learned this week","/posts/w04-2024-tips-learned-this-week",{"title":183,"_path":184},"Using dependency injection with Azure .NET SDK","/posts/azure-sdk-di",{"title":186,"_path":187},"Having Fun With IT Event Calendars","/posts/it-event-calendars",{"title":189,"_path":190},"Call your Azure AD B2C protected API with authenticated HTTP requests from your JetBrains IDE","/posts/http-clients-oauth2","i-heroicons-newspaper",{"title":193,"_path":194,"children":195,"icon":199},"Goodies","/goodies",[196],{"title":197,"_path":198},"My Git Cheat Sheet","/goodies/gitcheatsheet","i-heroicons-gift-solid",{"title":201,"_path":202,"icon":203},"About","/about","i-heroicons-user-circle-solid",[205,207,209,211,214,217,220,223,226,229,231,234,237,240,242,244,247,250,253,255,258,261,264,267,270,273,276,279,282,285,287,289,292,294,297,300,303,305,308,310,313,316,319,322,325,327,329,332,335,338,341,344,347,350,353,356,359,361,363,366,369,372,375,377,380,383,385,388,391,394],[206,206],"tooling",[208,208],"vscode",[210,210],"rest",[212,213],"http","HTTP",[215,216],"razor","Razor",[218,219],"xamarin","Xamarin",[221,222],"templating","Templating",[224,225],"azure-cli","Azure CLI",[227,228],"azure","Azure",[230,230],"shell",[232,233],"github","GitHub",[235,236],"asp-net-core","ASP.NET Core",[238,239],"net",".NET",[241,241],"git",[243,243],"nushell",[245,246],"microsoft-teams","Microsoft Teams",[248,249],"powershell","PowerShell",[251,252],"azure-active-directory","Azure Active Directory",[254,254],"learning",[256,257],"azure-functions","Azure Functions",[259,260],"azure-key-vault","Azure Key Vault",[262,263],"configuration","Configuration",[265,266],"devops","DevOps",[268,269],"it","IT",[271,272],"tips-learned-this-week","tips learned this week",[274,275],"windows-terminal","Windows Terminal",[277,278],"azure-pipelines","Azure Pipelines",[280,281],"application-insights","Application Insights",[283,284],"azure-iot","Azure IoT",[286,286],"records",[288,288],"refit",[290,291],"development-box-setup","development box setup",[293,293],"winget",[295,296],"package-manager","package manager",[298,299],"azure-sql-database","Azure SQL Database",[301,302],"azure-sdk","Azure SDK",[304,304],"wingetcreate",[306,307],"github-actions","GitHub Actions",[309,309],"jq",[311,312],"pulumi","Pulumi",[314,315],"iac","IaC",[317,318],"azure-storage","Azure Storage",[320,321],"azure-signalr","Azure SignalR",[323,324],"visio","Visio",[326,326],"csharp",[328,328],"jest",[330,331],"statiq","Statiq",[333,334],"open-source","open source",[336,337],"visual-studio","Visual Studio",[339,340],"vue-js","Vue.js",[342,343],"azure-devops","Azure DevOps",[345,346],"vite","Vite",[348,349],"code-analysis","Code analysis",[351,352],"diagram","Diagram",[354,355],"terraform","Terraform",[357,358],"typescript","TypeScript",[360,360],"thoughts",[362,362],"pnpm",[364,365],"nuke","Nuke",[367,368],"pipelines","Pipelines",[370,371],"cicd","CI/CD",[373,374],"openid-connect","OpenID Connect",[376,376],"security",[378,379],"github-cli","GitHub CLI",[381,382],"microsoft-entra-id","Microsoft Entra ID",[384,384],"advent",[386,387],"finops","FinOps",[389,390],"anglesharp","AngleSharp",[392,393],"oauth2","OAuth2",[395,396],"azure-ad-b2c","Azure AD B2C",[398,3731,7949,15332,15576,15892,17078],{"_path":172,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":171,"description":402,"lead":403,"date":404,"image":405,"badge":407,"tags":408,"body":409,"_type":3726,"_id":3727,"_source":3728,"_file":3729,"_extension":3730},"posts",false,"","What if we could script the creation and configuration of a GitHub Repository so that it is ready to provision or deploy Azure resources from a GitHub Actions pipeline? We will do that in this article using the Azure CLI and GitHub CLI.","Scripting your Azure-Ready GitHub Repository using Azure and GitHub CLI","2023-10-23T00:00:00.000Z",{"src":406},"/images/azureOIDC_2.webp",{"label":266},[228,225,233,379,307,374,382],{"type":410,"children":411,"toc":3715},"root",[412,419,426,431,436,807,823,828,840,859,865,872,886,899,911,917,930,935,1006,1011,1101,1126,1131,1198,1229,1235,1240,1356,1388,1393,1565,1570,1703,1708,1923,1948,1961,2081,2086,2143,2149,2154,2174,2256,2261,2366,2375,2381,3655,3661,3674,3679,3699,3704,3709],{"type":413,"tag":414,"props":415,"children":416},"element","p",{},[417],{"type":418,"value":402},"text",{"type":413,"tag":420,"props":421,"children":423},"h2",{"id":422},"the-objective",[424],{"type":418,"value":425},"The Objective",{"type":413,"tag":414,"props":427,"children":428},{},[429],{"type":418,"value":430},"The goal is to go from nothing to running a GitHub Actions workflow that authenticates to Azure using Open ID Connect (so without secret credentials) in a newly created GitHub repository.",{"type":413,"tag":414,"props":432,"children":433},{},[434],{"type":418,"value":435},"The workflow we plan to run is as follows:",{"type":413,"tag":437,"props":438,"children":442},"pre",{"className":439,"code":440,"language":441,"meta":401,"style":401},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: Run Azure Login with OIDC\non:\n  workflow_dispatch:\n\npermissions:\n  id-token: write\n  contents: read\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Az CLI login'\n        uses: azure/login@v1\n        with:\n          client-id: ${{ secrets.AZURE_CLIENT_ID }}\n          tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n\n      - name: 'Run az commands'\n        run: |\n          az account show\n          az group list\n","yaml",[443],{"type":413,"tag":444,"props":445,"children":446},"code",{"__ignoreMap":401},[447,471,486,499,509,522,540,558,571,584,602,615,648,666,679,697,715,733,741,770,789,798],{"type":413,"tag":448,"props":449,"children":452},"span",{"class":450,"line":451},"line",1,[453,459,465],{"type":413,"tag":448,"props":454,"children":456},{"style":455},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[457],{"type":418,"value":458},"name",{"type":413,"tag":448,"props":460,"children":462},{"style":461},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[463],{"type":418,"value":464},":",{"type":413,"tag":448,"props":466,"children":468},{"style":467},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[469],{"type":418,"value":470}," Run Azure Login with OIDC\n",{"type":413,"tag":448,"props":472,"children":474},{"class":450,"line":473},2,[475,481],{"type":413,"tag":448,"props":476,"children":478},{"style":477},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[479],{"type":418,"value":480},"on",{"type":413,"tag":448,"props":482,"children":483},{"style":461},[484],{"type":418,"value":485},":\n",{"type":413,"tag":448,"props":487,"children":489},{"class":450,"line":488},3,[490,495],{"type":413,"tag":448,"props":491,"children":492},{"style":455},[493],{"type":418,"value":494},"  workflow_dispatch",{"type":413,"tag":448,"props":496,"children":497},{"style":461},[498],{"type":418,"value":485},{"type":413,"tag":448,"props":500,"children":502},{"class":450,"line":501},4,[503],{"type":413,"tag":448,"props":504,"children":506},{"emptyLinePlaceholder":505},true,[507],{"type":418,"value":508},"\n",{"type":413,"tag":448,"props":510,"children":512},{"class":450,"line":511},5,[513,518],{"type":413,"tag":448,"props":514,"children":515},{"style":455},[516],{"type":418,"value":517},"permissions",{"type":413,"tag":448,"props":519,"children":520},{"style":461},[521],{"type":418,"value":485},{"type":413,"tag":448,"props":523,"children":525},{"class":450,"line":524},6,[526,531,535],{"type":413,"tag":448,"props":527,"children":528},{"style":455},[529],{"type":418,"value":530},"  id-token",{"type":413,"tag":448,"props":532,"children":533},{"style":461},[534],{"type":418,"value":464},{"type":413,"tag":448,"props":536,"children":537},{"style":467},[538],{"type":418,"value":539}," write\n",{"type":413,"tag":448,"props":541,"children":543},{"class":450,"line":542},7,[544,549,553],{"type":413,"tag":448,"props":545,"children":546},{"style":455},[547],{"type":418,"value":548},"  contents",{"type":413,"tag":448,"props":550,"children":551},{"style":461},[552],{"type":418,"value":464},{"type":413,"tag":448,"props":554,"children":555},{"style":467},[556],{"type":418,"value":557}," read\n",{"type":413,"tag":448,"props":559,"children":561},{"class":450,"line":560},8,[562,567],{"type":413,"tag":448,"props":563,"children":564},{"style":455},[565],{"type":418,"value":566},"jobs",{"type":413,"tag":448,"props":568,"children":569},{"style":461},[570],{"type":418,"value":485},{"type":413,"tag":448,"props":572,"children":574},{"class":450,"line":573},9,[575,580],{"type":413,"tag":448,"props":576,"children":577},{"style":455},[578],{"type":418,"value":579},"  build-and-deploy",{"type":413,"tag":448,"props":581,"children":582},{"style":461},[583],{"type":418,"value":485},{"type":413,"tag":448,"props":585,"children":587},{"class":450,"line":586},10,[588,593,597],{"type":413,"tag":448,"props":589,"children":590},{"style":455},[591],{"type":418,"value":592},"    runs-on",{"type":413,"tag":448,"props":594,"children":595},{"style":461},[596],{"type":418,"value":464},{"type":413,"tag":448,"props":598,"children":599},{"style":467},[600],{"type":418,"value":601}," ubuntu-latest\n",{"type":413,"tag":448,"props":603,"children":605},{"class":450,"line":604},11,[606,611],{"type":413,"tag":448,"props":607,"children":608},{"style":455},[609],{"type":418,"value":610},"    steps",{"type":413,"tag":448,"props":612,"children":613},{"style":461},[614],{"type":418,"value":485},{"type":413,"tag":448,"props":616,"children":618},{"class":450,"line":617},12,[619,624,629,633,638,643],{"type":413,"tag":448,"props":620,"children":621},{"style":461},[622],{"type":418,"value":623},"      -",{"type":413,"tag":448,"props":625,"children":626},{"style":455},[627],{"type":418,"value":628}," name",{"type":413,"tag":448,"props":630,"children":631},{"style":461},[632],{"type":418,"value":464},{"type":413,"tag":448,"props":634,"children":635},{"style":461},[636],{"type":418,"value":637}," '",{"type":413,"tag":448,"props":639,"children":640},{"style":467},[641],{"type":418,"value":642},"Az CLI login",{"type":413,"tag":448,"props":644,"children":645},{"style":461},[646],{"type":418,"value":647},"'\n",{"type":413,"tag":448,"props":649,"children":651},{"class":450,"line":650},13,[652,657,661],{"type":413,"tag":448,"props":653,"children":654},{"style":455},[655],{"type":418,"value":656},"        uses",{"type":413,"tag":448,"props":658,"children":659},{"style":461},[660],{"type":418,"value":464},{"type":413,"tag":448,"props":662,"children":663},{"style":467},[664],{"type":418,"value":665}," azure/login@v1\n",{"type":413,"tag":448,"props":667,"children":669},{"class":450,"line":668},14,[670,675],{"type":413,"tag":448,"props":671,"children":672},{"style":455},[673],{"type":418,"value":674},"        with",{"type":413,"tag":448,"props":676,"children":677},{"style":461},[678],{"type":418,"value":485},{"type":413,"tag":448,"props":680,"children":682},{"class":450,"line":681},15,[683,688,692],{"type":413,"tag":448,"props":684,"children":685},{"style":455},[686],{"type":418,"value":687},"          client-id",{"type":413,"tag":448,"props":689,"children":690},{"style":461},[691],{"type":418,"value":464},{"type":413,"tag":448,"props":693,"children":694},{"style":467},[695],{"type":418,"value":696}," ${{ secrets.AZURE_CLIENT_ID }}\n",{"type":413,"tag":448,"props":698,"children":700},{"class":450,"line":699},16,[701,706,710],{"type":413,"tag":448,"props":702,"children":703},{"style":455},[704],{"type":418,"value":705},"          tenant-id",{"type":413,"tag":448,"props":707,"children":708},{"style":461},[709],{"type":418,"value":464},{"type":413,"tag":448,"props":711,"children":712},{"style":467},[713],{"type":418,"value":714}," ${{ secrets.AZURE_TENANT_ID }}\n",{"type":413,"tag":448,"props":716,"children":718},{"class":450,"line":717},17,[719,724,728],{"type":413,"tag":448,"props":720,"children":721},{"style":455},[722],{"type":418,"value":723},"          subscription-id",{"type":413,"tag":448,"props":725,"children":726},{"style":461},[727],{"type":418,"value":464},{"type":413,"tag":448,"props":729,"children":730},{"style":467},[731],{"type":418,"value":732}," ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n",{"type":413,"tag":448,"props":734,"children":736},{"class":450,"line":735},18,[737],{"type":413,"tag":448,"props":738,"children":739},{"emptyLinePlaceholder":505},[740],{"type":418,"value":508},{"type":413,"tag":448,"props":742,"children":744},{"class":450,"line":743},19,[745,749,753,757,761,766],{"type":413,"tag":448,"props":746,"children":747},{"style":461},[748],{"type":418,"value":623},{"type":413,"tag":448,"props":750,"children":751},{"style":455},[752],{"type":418,"value":628},{"type":413,"tag":448,"props":754,"children":755},{"style":461},[756],{"type":418,"value":464},{"type":413,"tag":448,"props":758,"children":759},{"style":461},[760],{"type":418,"value":637},{"type":413,"tag":448,"props":762,"children":763},{"style":467},[764],{"type":418,"value":765},"Run az commands",{"type":413,"tag":448,"props":767,"children":768},{"style":461},[769],{"type":418,"value":647},{"type":413,"tag":448,"props":771,"children":773},{"class":450,"line":772},20,[774,779,783],{"type":413,"tag":448,"props":775,"children":776},{"style":455},[777],{"type":418,"value":778},"        run",{"type":413,"tag":448,"props":780,"children":781},{"style":461},[782],{"type":418,"value":464},{"type":413,"tag":448,"props":784,"children":786},{"style":785},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[787],{"type":418,"value":788}," |\n",{"type":413,"tag":448,"props":790,"children":792},{"class":450,"line":791},21,[793],{"type":413,"tag":448,"props":794,"children":795},{"style":467},[796],{"type":418,"value":797},"          az account show\n",{"type":413,"tag":448,"props":799,"children":801},{"class":450,"line":800},22,[802],{"type":413,"tag":448,"props":803,"children":804},{"style":467},[805],{"type":418,"value":806},"          az group list\n",{"type":413,"tag":414,"props":808,"children":809},{},[810,812,821],{"type":418,"value":811},"This workflow is an example coming from ",{"type":413,"tag":813,"props":814,"children":818},"a",{"href":815,"rel":816},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-azure",[817],"nofollow",[819],{"type":418,"value":820},"the GitHub documentation",{"type":418,"value":822}," showing how to configure GitHub Actions workflow to access Azure resources protected by Microsoft Entra.",{"type":413,"tag":414,"props":824,"children":825},{},[826],{"type":418,"value":827},"To run this workflow we will need to automate the configuration of these resources:",{"type":413,"tag":414,"props":829,"children":830},{},[831],{"type":413,"tag":832,"props":833,"children":839},"img",{"alt":834,"className":835,"src":838},"A diagram showing the interactions between Azure and GitHub.",[836,837],"rounded-lg","mx-auto","/posts/images/scripting_azurereadygithub_azure_1.webp",[],{"type":413,"tag":841,"props":842,"children":844},"callout",{"icon":843},"i-heroicons-chat-bubble-left-20-solid",[845],{"type":413,"tag":414,"props":846,"children":847},{},[848,850,857],{"type":418,"value":849},"Looks familiar? That's the same diagram from my article about ",{"type":413,"tag":813,"props":851,"children":854},{"href":852,"rel":853},"https://www.techwatching.dev/posts/azure-ready-github-repository",[817],[855],{"type":418,"value":856},"creating an Azure-Ready GitHub Repository using Pulumi",{"type":418,"value":858},". The purpose was the same but using Pulumi instead of CLI tools. If you prefer a declarative Infrastructure as Code approach using programming languages over CLI tools, you should definitively read it 😉",{"type":413,"tag":420,"props":860,"children":862},{"id":861},"the-script",[863],{"type":418,"value":864},"The Script",{"type":413,"tag":866,"props":867,"children":869},"h3",{"id":868},"a-word-about-the-tools-used",[870],{"type":418,"value":871},"A word about the tools used",{"type":413,"tag":414,"props":873,"children":874},{},[875,877,884],{"type":418,"value":876},"I will be using ",{"type":413,"tag":813,"props":878,"children":881},{"href":879,"rel":880},"https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3",[817],[882],{"type":418,"value":883},"PowerShell which is cross-platform",{"type":418,"value":885},". However, if you prefer using a different shell, you will simply need to adjust some syntax (such as the environment variable declarations) to ensure compatibility.",{"type":413,"tag":414,"props":887,"children":888},{},[889,891,897],{"type":418,"value":890},"To create and configure the Microsoft Entra ID resources, we will need the ",{"type":413,"tag":813,"props":892,"children":895},{"href":893,"rel":894},"https://learn.microsoft.com/en-us/cli/azure/install-azure-cli",[817],[896],{"type":418,"value":225},{"type":418,"value":898},".",{"type":413,"tag":414,"props":900,"children":901},{},[902,904,910],{"type":418,"value":903},"To create and configure the GitHub repository, we will need the ",{"type":413,"tag":813,"props":905,"children":908},{"href":906,"rel":907},"https://cli.github.com/",[817],[909],{"type":418,"value":379},{"type":418,"value":898},{"type":413,"tag":866,"props":912,"children":914},{"id":913},"create-the-repository-on-github",[915],{"type":418,"value":916},"Create the repository on GitHub",{"type":413,"tag":414,"props":918,"children":919},{},[920,922,928],{"type":418,"value":921},"Let's assume we are already in a new directory with the YAML workflow file ",{"type":413,"tag":444,"props":923,"children":925},{"className":924},[],[926],{"type":418,"value":927},".github\\workflows\\main.yml",{"type":418,"value":929}," in it.",{"type":413,"tag":414,"props":931,"children":932},{},[933],{"type":418,"value":934},"First, we can initialize the git repository.",{"type":413,"tag":437,"props":936,"children":940},{"className":937,"code":938,"language":939,"meta":401,"style":401},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git init\ngit add .\ngit commit -m \"Intialize repository with the GitHub Actions workflow file\"\n","bash",[941],{"type":413,"tag":444,"props":942,"children":943},{"__ignoreMap":401},[944,957,974],{"type":413,"tag":448,"props":945,"children":946},{"class":450,"line":451},[947,952],{"type":413,"tag":448,"props":948,"children":950},{"style":949},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[951],{"type":418,"value":241},{"type":413,"tag":448,"props":953,"children":954},{"style":467},[955],{"type":418,"value":956}," init\n",{"type":413,"tag":448,"props":958,"children":959},{"class":450,"line":473},[960,964,969],{"type":413,"tag":448,"props":961,"children":962},{"style":949},[963],{"type":418,"value":241},{"type":413,"tag":448,"props":965,"children":966},{"style":467},[967],{"type":418,"value":968}," add",{"type":413,"tag":448,"props":970,"children":971},{"style":467},[972],{"type":418,"value":973}," .\n",{"type":413,"tag":448,"props":975,"children":976},{"class":450,"line":488},[977,981,986,991,996,1001],{"type":413,"tag":448,"props":978,"children":979},{"style":949},[980],{"type":418,"value":241},{"type":413,"tag":448,"props":982,"children":983},{"style":467},[984],{"type":418,"value":985}," commit",{"type":413,"tag":448,"props":987,"children":988},{"style":467},[989],{"type":418,"value":990}," -m",{"type":413,"tag":448,"props":992,"children":993},{"style":461},[994],{"type":418,"value":995}," \"",{"type":413,"tag":448,"props":997,"children":998},{"style":467},[999],{"type":418,"value":1000},"Intialize repository with the GitHub Actions workflow file",{"type":413,"tag":448,"props":1002,"children":1003},{"style":461},[1004],{"type":418,"value":1005},"\"\n",{"type":413,"tag":414,"props":1007,"children":1008},{},[1009],{"type":418,"value":1010},"Second, we can create the GitHub repository and push the git repository we just initialized in it.",{"type":413,"tag":437,"props":1012,"children":1015},{"className":1013,"code":1014,"language":248,"meta":401,"style":401},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","$repositoryName = \"MyAzureReadyRepository\"\ngh repo create $repositoryName --private --source=. --push\n",[1016],{"type":413,"tag":444,"props":1017,"children":1018},{"__ignoreMap":401},[1019,1051],{"type":413,"tag":448,"props":1020,"children":1021},{"class":450,"line":451},[1022,1027,1033,1038,1042,1047],{"type":413,"tag":448,"props":1023,"children":1024},{"style":461},[1025],{"type":418,"value":1026},"$",{"type":413,"tag":448,"props":1028,"children":1030},{"style":1029},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1031],{"type":418,"value":1032},"repositoryName ",{"type":413,"tag":448,"props":1034,"children":1035},{"style":461},[1036],{"type":418,"value":1037},"=",{"type":413,"tag":448,"props":1039,"children":1040},{"style":461},[1041],{"type":418,"value":995},{"type":413,"tag":448,"props":1043,"children":1044},{"style":467},[1045],{"type":418,"value":1046},"MyAzureReadyRepository",{"type":413,"tag":448,"props":1048,"children":1049},{"style":461},[1050],{"type":418,"value":1005},{"type":413,"tag":448,"props":1052,"children":1053},{"class":450,"line":473},[1054,1059,1063,1067,1072,1077,1081,1086,1091,1096],{"type":413,"tag":448,"props":1055,"children":1056},{"style":1029},[1057],{"type":418,"value":1058},"gh repo create ",{"type":413,"tag":448,"props":1060,"children":1061},{"style":461},[1062],{"type":418,"value":1026},{"type":413,"tag":448,"props":1064,"children":1065},{"style":1029},[1066],{"type":418,"value":1032},{"type":413,"tag":448,"props":1068,"children":1069},{"style":461},[1070],{"type":418,"value":1071},"--",{"type":413,"tag":448,"props":1073,"children":1074},{"style":1029},[1075],{"type":418,"value":1076},"private ",{"type":413,"tag":448,"props":1078,"children":1079},{"style":461},[1080],{"type":418,"value":1071},{"type":413,"tag":448,"props":1082,"children":1083},{"style":1029},[1084],{"type":418,"value":1085},"source",{"type":413,"tag":448,"props":1087,"children":1088},{"style":461},[1089],{"type":418,"value":1090},"=.",{"type":413,"tag":448,"props":1092,"children":1093},{"style":461},[1094],{"type":418,"value":1095}," --",{"type":413,"tag":448,"props":1097,"children":1098},{"style":1029},[1099],{"type":418,"value":1100},"push\n",{"type":413,"tag":841,"props":1102,"children":1104},{"icon":1103},"i-heroicons-light-bulb",[1105],{"type":413,"tag":414,"props":1106,"children":1107},{},[1108,1110,1116,1118,1124],{"type":418,"value":1109},"You can use the ",{"type":413,"tag":444,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":418,"value":1115},"--public",{"type":418,"value":1117}," flag instead of the ",{"type":413,"tag":444,"props":1119,"children":1121},{"className":1120},[],[1122],{"type":418,"value":1123},"--private",{"type":418,"value":1125}," one if you want your GitHub repository to be public.",{"type":413,"tag":414,"props":1127,"children":1128},{},[1129],{"type":418,"value":1130},"The repository's full name (containing the organization name) can be retrieved like this:",{"type":413,"tag":437,"props":1132,"children":1134},{"className":1013,"code":1133,"language":248,"meta":401,"style":401},"$repositoryFullName=$(gh repo view --json nameWithOwner -q \".nameWithOwner\")\n",[1135],{"type":413,"tag":444,"props":1136,"children":1137},{"__ignoreMap":401},[1138],{"type":413,"tag":448,"props":1139,"children":1140},{"class":450,"line":451},[1141,1145,1150,1155,1160,1164,1169,1174,1179,1184,1189,1193],{"type":413,"tag":448,"props":1142,"children":1143},{"style":461},[1144],{"type":418,"value":1026},{"type":413,"tag":448,"props":1146,"children":1147},{"style":1029},[1148],{"type":418,"value":1149},"repositoryFullName",{"type":413,"tag":448,"props":1151,"children":1152},{"style":461},[1153],{"type":418,"value":1154},"=$(",{"type":413,"tag":448,"props":1156,"children":1157},{"style":1029},[1158],{"type":418,"value":1159},"gh repo view ",{"type":413,"tag":448,"props":1161,"children":1162},{"style":461},[1163],{"type":418,"value":1071},{"type":413,"tag":448,"props":1165,"children":1166},{"style":1029},[1167],{"type":418,"value":1168},"json nameWithOwner ",{"type":413,"tag":448,"props":1170,"children":1171},{"style":461},[1172],{"type":418,"value":1173},"-",{"type":413,"tag":448,"props":1175,"children":1176},{"style":1029},[1177],{"type":418,"value":1178},"q ",{"type":413,"tag":448,"props":1180,"children":1181},{"style":461},[1182],{"type":418,"value":1183},"\"",{"type":413,"tag":448,"props":1185,"children":1186},{"style":467},[1187],{"type":418,"value":1188},".nameWithOwner",{"type":413,"tag":448,"props":1190,"children":1191},{"style":461},[1192],{"type":418,"value":1183},{"type":413,"tag":448,"props":1194,"children":1195},{"style":461},[1196],{"type":418,"value":1197},")\n",{"type":413,"tag":841,"props":1199,"children":1200},{"icon":1103},[1201],{"type":413,"tag":414,"props":1202,"children":1203},{},[1204,1206,1212,1214,1220,1222],{"type":418,"value":1205},"Passing the ",{"type":413,"tag":444,"props":1207,"children":1209},{"className":1208},[],[1210],{"type":418,"value":1211},"--json",{"type":418,"value":1213}," flag converts the output format to JSON which, combined with the ",{"type":413,"tag":444,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":418,"value":1219},"--q",{"type":418,"value":1221}," flag can be handy for filtering or formatting a command output. More on that ",{"type":413,"tag":813,"props":1223,"children":1226},{"href":1224,"rel":1225},"https://cli.github.com/manual/gh_help_formatting",[817],[1227],{"type":418,"value":1228},"in the documentation",{"type":413,"tag":866,"props":1230,"children":1232},{"id":1231},"create-the-microsoft-entra-id-resources",[1233],{"type":418,"value":1234},"Create the Microsoft Entra ID resources",{"type":413,"tag":414,"props":1236,"children":1237},{},[1238],{"type":418,"value":1239},"Later, we will need the subscription and the tenant identifiers. Let's retrieve them now and take this opportunity to check that we are logged in on the correct tenant with the correct subscription selected.",{"type":413,"tag":437,"props":1241,"children":1243},{"className":1013,"code":1242,"language":248,"meta":401,"style":401},"$subscriptionId=$(az account show --query \"id\" -o tsv)\n$tenantId=$(az account show --query \"tenantId\" -o tsv)\n",[1244],{"type":413,"tag":444,"props":1245,"children":1246},{"__ignoreMap":401},[1247,1304],{"type":413,"tag":448,"props":1248,"children":1249},{"class":450,"line":451},[1250,1254,1259,1263,1268,1272,1277,1281,1286,1290,1295,1300],{"type":413,"tag":448,"props":1251,"children":1252},{"style":461},[1253],{"type":418,"value":1026},{"type":413,"tag":448,"props":1255,"children":1256},{"style":1029},[1257],{"type":418,"value":1258},"subscriptionId",{"type":413,"tag":448,"props":1260,"children":1261},{"style":461},[1262],{"type":418,"value":1154},{"type":413,"tag":448,"props":1264,"children":1265},{"style":1029},[1266],{"type":418,"value":1267},"az account show ",{"type":413,"tag":448,"props":1269,"children":1270},{"style":461},[1271],{"type":418,"value":1071},{"type":413,"tag":448,"props":1273,"children":1274},{"style":1029},[1275],{"type":418,"value":1276},"query ",{"type":413,"tag":448,"props":1278,"children":1279},{"style":461},[1280],{"type":418,"value":1183},{"type":413,"tag":448,"props":1282,"children":1283},{"style":467},[1284],{"type":418,"value":1285},"id",{"type":413,"tag":448,"props":1287,"children":1288},{"style":461},[1289],{"type":418,"value":1183},{"type":413,"tag":448,"props":1291,"children":1292},{"style":461},[1293],{"type":418,"value":1294}," -",{"type":413,"tag":448,"props":1296,"children":1297},{"style":1029},[1298],{"type":418,"value":1299},"o tsv",{"type":413,"tag":448,"props":1301,"children":1302},{"style":461},[1303],{"type":418,"value":1197},{"type":413,"tag":448,"props":1305,"children":1306},{"class":450,"line":473},[1307,1311,1316,1320,1324,1328,1332,1336,1340,1344,1348,1352],{"type":413,"tag":448,"props":1308,"children":1309},{"style":461},[1310],{"type":418,"value":1026},{"type":413,"tag":448,"props":1312,"children":1313},{"style":1029},[1314],{"type":418,"value":1315},"tenantId",{"type":413,"tag":448,"props":1317,"children":1318},{"style":461},[1319],{"type":418,"value":1154},{"type":413,"tag":448,"props":1321,"children":1322},{"style":1029},[1323],{"type":418,"value":1267},{"type":413,"tag":448,"props":1325,"children":1326},{"style":461},[1327],{"type":418,"value":1071},{"type":413,"tag":448,"props":1329,"children":1330},{"style":1029},[1331],{"type":418,"value":1276},{"type":413,"tag":448,"props":1333,"children":1334},{"style":461},[1335],{"type":418,"value":1183},{"type":413,"tag":448,"props":1337,"children":1338},{"style":467},[1339],{"type":418,"value":1315},{"type":413,"tag":448,"props":1341,"children":1342},{"style":461},[1343],{"type":418,"value":1183},{"type":413,"tag":448,"props":1345,"children":1346},{"style":461},[1347],{"type":418,"value":1294},{"type":413,"tag":448,"props":1349,"children":1350},{"style":1029},[1351],{"type":418,"value":1299},{"type":413,"tag":448,"props":1353,"children":1354},{"style":461},[1355],{"type":418,"value":1197},{"type":413,"tag":841,"props":1357,"children":1358},{"icon":843},[1359],{"type":413,"tag":414,"props":1360,"children":1361},{},[1362,1364,1370,1372,1378,1380,1387],{"type":418,"value":1363},"Similar to the GitHub CLI, the Azure CLI has a ",{"type":413,"tag":444,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":418,"value":1369},"--query",{"type":418,"value":1371}," flag to filter a command output. There are also different output formats. The ",{"type":413,"tag":444,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":418,"value":1377},"tsv",{"type":418,"value":1379}," (tab-separated values) one is useful for capturing a value in an environment variable. If you are not very familiar with the Azure CLI, you can check my article on the topic ",{"type":413,"tag":813,"props":1381,"children":1384},{"href":1382,"rel":1383},"https://www.techwatching.dev/posts/welcome-azure-cli",[817],[1385],{"type":418,"value":1386},"here",{"type":418,"value":898},{"type":413,"tag":414,"props":1389,"children":1390},{},[1391],{"type":418,"value":1392},"To create the app registration and its associated service principal, we can execute the following commands:",{"type":413,"tag":437,"props":1394,"children":1396},{"className":1013,"code":1395,"language":248,"meta":401,"style":401},"$appId=$(az ad app create --display-name \"GitHub Action OIDC for ${repositoryFullName}\" --query \"appId\" -o tsv)\n$servicePrincipalId=$(az ad sp create --id $appId --query \"id\" -o tsv)\n",[1397],{"type":413,"tag":444,"props":1398,"children":1399},{"__ignoreMap":401},[1400,1494],{"type":413,"tag":448,"props":1401,"children":1402},{"class":450,"line":451},[1403,1407,1412,1416,1421,1425,1430,1434,1439,1443,1448,1453,1457,1462,1466,1470,1474,1478,1482,1486,1490],{"type":413,"tag":448,"props":1404,"children":1405},{"style":461},[1406],{"type":418,"value":1026},{"type":413,"tag":448,"props":1408,"children":1409},{"style":1029},[1410],{"type":418,"value":1411},"appId",{"type":413,"tag":448,"props":1413,"children":1414},{"style":461},[1415],{"type":418,"value":1154},{"type":413,"tag":448,"props":1417,"children":1418},{"style":1029},[1419],{"type":418,"value":1420},"az ad app create ",{"type":413,"tag":448,"props":1422,"children":1423},{"style":461},[1424],{"type":418,"value":1071},{"type":413,"tag":448,"props":1426,"children":1427},{"style":1029},[1428],{"type":418,"value":1429},"display",{"type":413,"tag":448,"props":1431,"children":1432},{"style":461},[1433],{"type":418,"value":1173},{"type":413,"tag":448,"props":1435,"children":1436},{"style":1029},[1437],{"type":418,"value":1438},"name ",{"type":413,"tag":448,"props":1440,"children":1441},{"style":461},[1442],{"type":418,"value":1183},{"type":413,"tag":448,"props":1444,"children":1445},{"style":467},[1446],{"type":418,"value":1447},"GitHub Action OIDC for ",{"type":413,"tag":448,"props":1449,"children":1450},{"style":461},[1451],{"type":418,"value":1452},"${",{"type":413,"tag":448,"props":1454,"children":1455},{"style":1029},[1456],{"type":418,"value":1149},{"type":413,"tag":448,"props":1458,"children":1459},{"style":461},[1460],{"type":418,"value":1461},"}\"",{"type":413,"tag":448,"props":1463,"children":1464},{"style":461},[1465],{"type":418,"value":1095},{"type":413,"tag":448,"props":1467,"children":1468},{"style":1029},[1469],{"type":418,"value":1276},{"type":413,"tag":448,"props":1471,"children":1472},{"style":461},[1473],{"type":418,"value":1183},{"type":413,"tag":448,"props":1475,"children":1476},{"style":467},[1477],{"type":418,"value":1411},{"type":413,"tag":448,"props":1479,"children":1480},{"style":461},[1481],{"type":418,"value":1183},{"type":413,"tag":448,"props":1483,"children":1484},{"style":461},[1485],{"type":418,"value":1294},{"type":413,"tag":448,"props":1487,"children":1488},{"style":1029},[1489],{"type":418,"value":1299},{"type":413,"tag":448,"props":1491,"children":1492},{"style":461},[1493],{"type":418,"value":1197},{"type":413,"tag":448,"props":1495,"children":1496},{"class":450,"line":473},[1497,1501,1506,1510,1515,1519,1524,1528,1533,1537,1541,1545,1549,1553,1557,1561],{"type":413,"tag":448,"props":1498,"children":1499},{"style":461},[1500],{"type":418,"value":1026},{"type":413,"tag":448,"props":1502,"children":1503},{"style":1029},[1504],{"type":418,"value":1505},"servicePrincipalId",{"type":413,"tag":448,"props":1507,"children":1508},{"style":461},[1509],{"type":418,"value":1154},{"type":413,"tag":448,"props":1511,"children":1512},{"style":1029},[1513],{"type":418,"value":1514},"az ad sp create ",{"type":413,"tag":448,"props":1516,"children":1517},{"style":461},[1518],{"type":418,"value":1071},{"type":413,"tag":448,"props":1520,"children":1521},{"style":1029},[1522],{"type":418,"value":1523},"id ",{"type":413,"tag":448,"props":1525,"children":1526},{"style":461},[1527],{"type":418,"value":1026},{"type":413,"tag":448,"props":1529,"children":1530},{"style":1029},[1531],{"type":418,"value":1532},"appId ",{"type":413,"tag":448,"props":1534,"children":1535},{"style":461},[1536],{"type":418,"value":1071},{"type":413,"tag":448,"props":1538,"children":1539},{"style":1029},[1540],{"type":418,"value":1276},{"type":413,"tag":448,"props":1542,"children":1543},{"style":461},[1544],{"type":418,"value":1183},{"type":413,"tag":448,"props":1546,"children":1547},{"style":467},[1548],{"type":418,"value":1285},{"type":413,"tag":448,"props":1550,"children":1551},{"style":461},[1552],{"type":418,"value":1183},{"type":413,"tag":448,"props":1554,"children":1555},{"style":461},[1556],{"type":418,"value":1294},{"type":413,"tag":448,"props":1558,"children":1559},{"style":1029},[1560],{"type":418,"value":1299},{"type":413,"tag":448,"props":1562,"children":1563},{"style":461},[1564],{"type":418,"value":1197},{"type":413,"tag":414,"props":1566,"children":1567},{},[1568],{"type":418,"value":1569},"We can now assign the contributor role to the service principal on the subscription.",{"type":413,"tag":437,"props":1571,"children":1573},{"className":1013,"code":1572,"language":248,"meta":401,"style":401},"az role assignment create --role contributor --subscription $subscriptionId --assignee-object-id  $servicePrincipalId --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscriptionId\n",[1574],{"type":413,"tag":444,"props":1575,"children":1576},{"__ignoreMap":401},[1577],{"type":413,"tag":448,"props":1578,"children":1579},{"class":450,"line":451},[1580,1585,1589,1594,1598,1603,1607,1612,1616,1621,1625,1630,1634,1639,1643,1648,1652,1656,1660,1665,1669,1674,1678,1683,1688,1693,1698],{"type":413,"tag":448,"props":1581,"children":1582},{"style":1029},[1583],{"type":418,"value":1584},"az role assignment create ",{"type":413,"tag":448,"props":1586,"children":1587},{"style":461},[1588],{"type":418,"value":1071},{"type":413,"tag":448,"props":1590,"children":1591},{"style":1029},[1592],{"type":418,"value":1593},"role contributor ",{"type":413,"tag":448,"props":1595,"children":1596},{"style":461},[1597],{"type":418,"value":1071},{"type":413,"tag":448,"props":1599,"children":1600},{"style":1029},[1601],{"type":418,"value":1602},"subscription ",{"type":413,"tag":448,"props":1604,"children":1605},{"style":461},[1606],{"type":418,"value":1026},{"type":413,"tag":448,"props":1608,"children":1609},{"style":1029},[1610],{"type":418,"value":1611},"subscriptionId ",{"type":413,"tag":448,"props":1613,"children":1614},{"style":461},[1615],{"type":418,"value":1071},{"type":413,"tag":448,"props":1617,"children":1618},{"style":1029},[1619],{"type":418,"value":1620},"assignee",{"type":413,"tag":448,"props":1622,"children":1623},{"style":461},[1624],{"type":418,"value":1173},{"type":413,"tag":448,"props":1626,"children":1627},{"style":1029},[1628],{"type":418,"value":1629},"object",{"type":413,"tag":448,"props":1631,"children":1632},{"style":461},[1633],{"type":418,"value":1173},{"type":413,"tag":448,"props":1635,"children":1636},{"style":1029},[1637],{"type":418,"value":1638},"id  ",{"type":413,"tag":448,"props":1640,"children":1641},{"style":461},[1642],{"type":418,"value":1026},{"type":413,"tag":448,"props":1644,"children":1645},{"style":1029},[1646],{"type":418,"value":1647},"servicePrincipalId ",{"type":413,"tag":448,"props":1649,"children":1650},{"style":461},[1651],{"type":418,"value":1071},{"type":413,"tag":448,"props":1653,"children":1654},{"style":1029},[1655],{"type":418,"value":1620},{"type":413,"tag":448,"props":1657,"children":1658},{"style":461},[1659],{"type":418,"value":1173},{"type":413,"tag":448,"props":1661,"children":1662},{"style":1029},[1663],{"type":418,"value":1664},"principal",{"type":413,"tag":448,"props":1666,"children":1667},{"style":461},[1668],{"type":418,"value":1173},{"type":413,"tag":448,"props":1670,"children":1671},{"style":1029},[1672],{"type":418,"value":1673},"type ServicePrincipal ",{"type":413,"tag":448,"props":1675,"children":1676},{"style":461},[1677],{"type":418,"value":1071},{"type":413,"tag":448,"props":1679,"children":1680},{"style":1029},[1681],{"type":418,"value":1682},"scope ",{"type":413,"tag":448,"props":1684,"children":1685},{"style":461},[1686],{"type":418,"value":1687},"/",{"type":413,"tag":448,"props":1689,"children":1690},{"style":1029},[1691],{"type":418,"value":1692},"subscriptions",{"type":413,"tag":448,"props":1694,"children":1695},{"style":461},[1696],{"type":418,"value":1697},"/$",{"type":413,"tag":448,"props":1699,"children":1700},{"style":1029},[1701],{"type":418,"value":1702},"subscriptionId\n",{"type":413,"tag":414,"props":1704,"children":1705},{},[1706],{"type":418,"value":1707},"Creating federated credentials is a bit more complex as one of the arguments needs to be an in-line JSON string.",{"type":413,"tag":437,"props":1709,"children":1711},{"className":1013,"code":1710,"language":248,"meta":401,"style":401},"$parametersJson = @{\n    name = \"FederatedIdentityForWorkshop\"\n    issuer = \"https://token.actions.githubusercontent.com\"\n    subject = \"repo:${repositoryFullName}:ref:refs/heads/main\"\n    description = \"Deployments for ${repositoryFullName}\"\n    audiences = @(\n        \"api://AzureADTokenExchange\"\n    )\n}\n",[1712],{"type":413,"tag":444,"props":1713,"children":1714},{"__ignoreMap":401},[1715,1742,1767,1792,1835,1869,1890,1907,1915],{"type":413,"tag":448,"props":1716,"children":1717},{"class":450,"line":451},[1718,1722,1727,1731,1737],{"type":413,"tag":448,"props":1719,"children":1720},{"style":461},[1721],{"type":418,"value":1026},{"type":413,"tag":448,"props":1723,"children":1724},{"style":1029},[1725],{"type":418,"value":1726},"parametersJson ",{"type":413,"tag":448,"props":1728,"children":1729},{"style":461},[1730],{"type":418,"value":1037},{"type":413,"tag":448,"props":1732,"children":1734},{"style":1733},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1735],{"type":418,"value":1736}," @",{"type":413,"tag":448,"props":1738,"children":1739},{"style":461},[1740],{"type":418,"value":1741},"{\n",{"type":413,"tag":448,"props":1743,"children":1744},{"class":450,"line":473},[1745,1750,1754,1758,1763],{"type":413,"tag":448,"props":1746,"children":1747},{"style":1029},[1748],{"type":418,"value":1749},"    name ",{"type":413,"tag":448,"props":1751,"children":1752},{"style":461},[1753],{"type":418,"value":1037},{"type":413,"tag":448,"props":1755,"children":1756},{"style":461},[1757],{"type":418,"value":995},{"type":413,"tag":448,"props":1759,"children":1760},{"style":467},[1761],{"type":418,"value":1762},"FederatedIdentityForWorkshop",{"type":413,"tag":448,"props":1764,"children":1765},{"style":461},[1766],{"type":418,"value":1005},{"type":413,"tag":448,"props":1768,"children":1769},{"class":450,"line":488},[1770,1775,1779,1783,1788],{"type":413,"tag":448,"props":1771,"children":1772},{"style":1029},[1773],{"type":418,"value":1774},"    issuer ",{"type":413,"tag":448,"props":1776,"children":1777},{"style":461},[1778],{"type":418,"value":1037},{"type":413,"tag":448,"props":1780,"children":1781},{"style":461},[1782],{"type":418,"value":995},{"type":413,"tag":448,"props":1784,"children":1785},{"style":467},[1786],{"type":418,"value":1787},"https://token.actions.githubusercontent.com",{"type":413,"tag":448,"props":1789,"children":1790},{"style":461},[1791],{"type":418,"value":1005},{"type":413,"tag":448,"props":1793,"children":1794},{"class":450,"line":501},[1795,1800,1804,1808,1813,1817,1821,1826,1831],{"type":413,"tag":448,"props":1796,"children":1797},{"style":1029},[1798],{"type":418,"value":1799},"    subject ",{"type":413,"tag":448,"props":1801,"children":1802},{"style":461},[1803],{"type":418,"value":1037},{"type":413,"tag":448,"props":1805,"children":1806},{"style":461},[1807],{"type":418,"value":995},{"type":413,"tag":448,"props":1809,"children":1810},{"style":467},[1811],{"type":418,"value":1812},"repo:",{"type":413,"tag":448,"props":1814,"children":1815},{"style":461},[1816],{"type":418,"value":1452},{"type":413,"tag":448,"props":1818,"children":1819},{"style":1029},[1820],{"type":418,"value":1149},{"type":413,"tag":448,"props":1822,"children":1823},{"style":461},[1824],{"type":418,"value":1825},"}",{"type":413,"tag":448,"props":1827,"children":1828},{"style":467},[1829],{"type":418,"value":1830},":ref:refs/heads/main",{"type":413,"tag":448,"props":1832,"children":1833},{"style":461},[1834],{"type":418,"value":1005},{"type":413,"tag":448,"props":1836,"children":1837},{"class":450,"line":511},[1838,1843,1847,1851,1856,1860,1864],{"type":413,"tag":448,"props":1839,"children":1840},{"style":1029},[1841],{"type":418,"value":1842},"    description ",{"type":413,"tag":448,"props":1844,"children":1845},{"style":461},[1846],{"type":418,"value":1037},{"type":413,"tag":448,"props":1848,"children":1849},{"style":461},[1850],{"type":418,"value":995},{"type":413,"tag":448,"props":1852,"children":1853},{"style":467},[1854],{"type":418,"value":1855},"Deployments for ",{"type":413,"tag":448,"props":1857,"children":1858},{"style":461},[1859],{"type":418,"value":1452},{"type":413,"tag":448,"props":1861,"children":1862},{"style":1029},[1863],{"type":418,"value":1149},{"type":413,"tag":448,"props":1865,"children":1866},{"style":461},[1867],{"type":418,"value":1868},"}\"\n",{"type":413,"tag":448,"props":1870,"children":1871},{"class":450,"line":524},[1872,1877,1881,1885],{"type":413,"tag":448,"props":1873,"children":1874},{"style":1029},[1875],{"type":418,"value":1876},"    audiences ",{"type":413,"tag":448,"props":1878,"children":1879},{"style":461},[1880],{"type":418,"value":1037},{"type":413,"tag":448,"props":1882,"children":1883},{"style":1733},[1884],{"type":418,"value":1736},{"type":413,"tag":448,"props":1886,"children":1887},{"style":461},[1888],{"type":418,"value":1889},"(\n",{"type":413,"tag":448,"props":1891,"children":1892},{"class":450,"line":542},[1893,1898,1903],{"type":413,"tag":448,"props":1894,"children":1895},{"style":461},[1896],{"type":418,"value":1897},"        \"",{"type":413,"tag":448,"props":1899,"children":1900},{"style":467},[1901],{"type":418,"value":1902},"api://AzureADTokenExchange",{"type":413,"tag":448,"props":1904,"children":1905},{"style":461},[1906],{"type":418,"value":1005},{"type":413,"tag":448,"props":1908,"children":1909},{"class":450,"line":560},[1910],{"type":413,"tag":448,"props":1911,"children":1912},{"style":461},[1913],{"type":418,"value":1914},"    )\n",{"type":413,"tag":448,"props":1916,"children":1917},{"class":450,"line":573},[1918],{"type":413,"tag":448,"props":1919,"children":1920},{"style":461},[1921],{"type":418,"value":1922},"}\n",{"type":413,"tag":841,"props":1924,"children":1925},{"icon":1103},[1926],{"type":413,"tag":414,"props":1927,"children":1928},{},[1929,1931,1937,1939,1946],{"type":418,"value":1930},"The ",{"type":413,"tag":444,"props":1932,"children":1934},{"className":1933},[],[1935],{"type":418,"value":1936},"subject",{"type":418,"value":1938}," property here specifies that the GitHub Actions workflow from the created repository is only authorized to authenticate to Azure when it runs on the main branch. Of course, there are other possible configurations, such as those involving pull requests or environments. Consult the ",{"type":413,"tag":813,"props":1940,"children":1943},{"href":1941,"rel":1942},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#example-subject-claims",[817],[1944],{"type":418,"value":1945},"documentation",{"type":418,"value":1947}," to learn more about these options.",{"type":413,"tag":414,"props":1949,"children":1950},{},[1951,1953,1960],{"type":418,"value":1952},"To make this JSON string an inline string with escaped quotes that works for the Azure CLI, we have to transform the string using a command I found in this ",{"type":413,"tag":813,"props":1954,"children":1957},{"href":1955,"rel":1956},"https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b",[817],[1958],{"type":418,"value":1959},"blog article",{"type":418,"value":898},{"type":413,"tag":437,"props":1962,"children":1964},{"className":1013,"code":1963,"language":248,"meta":401,"style":401},"$parameters = $($parametersJson | ConvertTo-Json -Depth 100 -Compress).Replace(\"`\"\", \"\\`\"\")\n",[1965],{"type":413,"tag":444,"props":1966,"children":1967},{"__ignoreMap":401},[1968],{"type":413,"tag":448,"props":1969,"children":1970},{"class":450,"line":451},[1971,1975,1980,1984,1989,1993,1998,2004,2008,2013,2018,2022,2027,2032,2037,2042,2046,2051,2055,2060,2064,2069,2073,2077],{"type":413,"tag":448,"props":1972,"children":1973},{"style":461},[1974],{"type":418,"value":1026},{"type":413,"tag":448,"props":1976,"children":1977},{"style":1029},[1978],{"type":418,"value":1979},"parameters ",{"type":413,"tag":448,"props":1981,"children":1982},{"style":461},[1983],{"type":418,"value":1037},{"type":413,"tag":448,"props":1985,"children":1986},{"style":461},[1987],{"type":418,"value":1988}," $($",{"type":413,"tag":448,"props":1990,"children":1991},{"style":1029},[1992],{"type":418,"value":1726},{"type":413,"tag":448,"props":1994,"children":1995},{"style":461},[1996],{"type":418,"value":1997},"|",{"type":413,"tag":448,"props":1999,"children":2001},{"style":2000},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[2002],{"type":418,"value":2003}," ConvertTo-Json",{"type":413,"tag":448,"props":2005,"children":2006},{"style":461},[2007],{"type":418,"value":1294},{"type":413,"tag":448,"props":2009,"children":2010},{"style":1029},[2011],{"type":418,"value":2012},"Depth ",{"type":413,"tag":448,"props":2014,"children":2015},{"style":1733},[2016],{"type":418,"value":2017},"100",{"type":413,"tag":448,"props":2019,"children":2020},{"style":461},[2021],{"type":418,"value":1294},{"type":413,"tag":448,"props":2023,"children":2024},{"style":1029},[2025],{"type":418,"value":2026},"Compress",{"type":413,"tag":448,"props":2028,"children":2029},{"style":461},[2030],{"type":418,"value":2031},")",{"type":413,"tag":448,"props":2033,"children":2034},{"style":1029},[2035],{"type":418,"value":2036},".Replace",{"type":413,"tag":448,"props":2038,"children":2039},{"style":461},[2040],{"type":418,"value":2041},"(",{"type":413,"tag":448,"props":2043,"children":2044},{"style":461},[2045],{"type":418,"value":1183},{"type":413,"tag":448,"props":2047,"children":2048},{"style":1029},[2049],{"type":418,"value":2050},"`\"",{"type":413,"tag":448,"props":2052,"children":2053},{"style":461},[2054],{"type":418,"value":1183},{"type":413,"tag":448,"props":2056,"children":2057},{"style":461},[2058],{"type":418,"value":2059},",",{"type":413,"tag":448,"props":2061,"children":2062},{"style":461},[2063],{"type":418,"value":995},{"type":413,"tag":448,"props":2065,"children":2066},{"style":467},[2067],{"type":418,"value":2068},"\\",{"type":413,"tag":448,"props":2070,"children":2071},{"style":1029},[2072],{"type":418,"value":2050},{"type":413,"tag":448,"props":2074,"children":2075},{"style":461},[2076],{"type":418,"value":1183},{"type":413,"tag":448,"props":2078,"children":2079},{"style":461},[2080],{"type":418,"value":1197},{"type":413,"tag":414,"props":2082,"children":2083},{},[2084],{"type":418,"value":2085},"And finally, we can create the federated credentials.",{"type":413,"tag":437,"props":2087,"children":2089},{"className":1013,"code":2088,"language":248,"meta":401,"style":401},"az ad app federated-credential create --id $appId --parameters $parameters\n",[2090],{"type":413,"tag":444,"props":2091,"children":2092},{"__ignoreMap":401},[2093],{"type":413,"tag":448,"props":2094,"children":2095},{"class":450,"line":451},[2096,2101,2105,2110,2114,2118,2122,2126,2130,2134,2138],{"type":413,"tag":448,"props":2097,"children":2098},{"style":1029},[2099],{"type":418,"value":2100},"az ad app federated",{"type":413,"tag":448,"props":2102,"children":2103},{"style":461},[2104],{"type":418,"value":1173},{"type":413,"tag":448,"props":2106,"children":2107},{"style":1029},[2108],{"type":418,"value":2109},"credential create ",{"type":413,"tag":448,"props":2111,"children":2112},{"style":461},[2113],{"type":418,"value":1071},{"type":413,"tag":448,"props":2115,"children":2116},{"style":1029},[2117],{"type":418,"value":1523},{"type":413,"tag":448,"props":2119,"children":2120},{"style":461},[2121],{"type":418,"value":1026},{"type":413,"tag":448,"props":2123,"children":2124},{"style":1029},[2125],{"type":418,"value":1532},{"type":413,"tag":448,"props":2127,"children":2128},{"style":461},[2129],{"type":418,"value":1071},{"type":413,"tag":448,"props":2131,"children":2132},{"style":1029},[2133],{"type":418,"value":1979},{"type":413,"tag":448,"props":2135,"children":2136},{"style":461},[2137],{"type":418,"value":1026},{"type":413,"tag":448,"props":2139,"children":2140},{"style":1029},[2141],{"type":418,"value":2142},"parameters\n",{"type":413,"tag":866,"props":2144,"children":2146},{"id":2145},"configure-the-github-actions-and-run-the-workflow",[2147],{"type":418,"value":2148},"Configure the GitHub Actions and run the workflow",{"type":413,"tag":414,"props":2150,"children":2151},{},[2152],{"type":418,"value":2153},"For the OIDC authentication to function properly, we need to set 3 GitHub Actions Secrets (could also be GitHub Actions variables as there are not really secrets):",{"type":413,"tag":2155,"props":2156,"children":2157},"ol",{},[2158,2164,2169],{"type":413,"tag":2159,"props":2160,"children":2161},"li",{},[2162],{"type":418,"value":2163},"The identifier of the Azure tenant",{"type":413,"tag":2159,"props":2165,"children":2166},{},[2167],{"type":418,"value":2168},"The identifier of the Azure subscription",{"type":413,"tag":2159,"props":2170,"children":2171},{},[2172],{"type":418,"value":2173},"The application identifier of the app registration",{"type":413,"tag":437,"props":2175,"children":2177},{"className":1013,"code":2176,"language":248,"meta":401,"style":401},"gh secret set AZURE_TENANT_ID --body $tenantId\ngh secret set AZURE_SUBSCRIPTION_ID --body $subscriptionId\ngh secret set AZURE_CLIENT_ID --body $appId\n",[2178],{"type":413,"tag":444,"props":2179,"children":2180},{"__ignoreMap":401},[2181,2207,2231],{"type":413,"tag":448,"props":2182,"children":2183},{"class":450,"line":451},[2184,2189,2193,2198,2202],{"type":413,"tag":448,"props":2185,"children":2186},{"style":1029},[2187],{"type":418,"value":2188},"gh secret set AZURE_TENANT_ID ",{"type":413,"tag":448,"props":2190,"children":2191},{"style":461},[2192],{"type":418,"value":1071},{"type":413,"tag":448,"props":2194,"children":2195},{"style":1029},[2196],{"type":418,"value":2197},"body ",{"type":413,"tag":448,"props":2199,"children":2200},{"style":461},[2201],{"type":418,"value":1026},{"type":413,"tag":448,"props":2203,"children":2204},{"style":1029},[2205],{"type":418,"value":2206},"tenantId\n",{"type":413,"tag":448,"props":2208,"children":2209},{"class":450,"line":473},[2210,2215,2219,2223,2227],{"type":413,"tag":448,"props":2211,"children":2212},{"style":1029},[2213],{"type":418,"value":2214},"gh secret set AZURE_SUBSCRIPTION_ID ",{"type":413,"tag":448,"props":2216,"children":2217},{"style":461},[2218],{"type":418,"value":1071},{"type":413,"tag":448,"props":2220,"children":2221},{"style":1029},[2222],{"type":418,"value":2197},{"type":413,"tag":448,"props":2224,"children":2225},{"style":461},[2226],{"type":418,"value":1026},{"type":413,"tag":448,"props":2228,"children":2229},{"style":1029},[2230],{"type":418,"value":1702},{"type":413,"tag":448,"props":2232,"children":2233},{"class":450,"line":488},[2234,2239,2243,2247,2251],{"type":413,"tag":448,"props":2235,"children":2236},{"style":1029},[2237],{"type":418,"value":2238},"gh secret set AZURE_CLIENT_ID ",{"type":413,"tag":448,"props":2240,"children":2241},{"style":461},[2242],{"type":418,"value":1071},{"type":413,"tag":448,"props":2244,"children":2245},{"style":1029},[2246],{"type":418,"value":2197},{"type":413,"tag":448,"props":2248,"children":2249},{"style":461},[2250],{"type":418,"value":1026},{"type":413,"tag":448,"props":2252,"children":2253},{"style":1029},[2254],{"type":418,"value":2255},"appId\n",{"type":413,"tag":414,"props":2257,"children":2258},{},[2259],{"type":418,"value":2260},"We can directly run the workflow from the GitHub CLI, and watch the run until it is completed.",{"type":413,"tag":437,"props":2262,"children":2264},{"className":1013,"code":2263,"language":248,"meta":401,"style":401},"gh workflow run main.yml\n$runId=$(gh run list --workflow=main.yml --json databaseId -q \".[0].databaseId\")\ngh run watch $runId\n",[2265],{"type":413,"tag":444,"props":2266,"children":2267},{"__ignoreMap":401},[2268,2276,2349],{"type":413,"tag":448,"props":2269,"children":2270},{"class":450,"line":451},[2271],{"type":413,"tag":448,"props":2272,"children":2273},{"style":1029},[2274],{"type":418,"value":2275},"gh workflow run main.yml\n",{"type":413,"tag":448,"props":2277,"children":2278},{"class":450,"line":473},[2279,2283,2288,2292,2297,2301,2306,2310,2315,2319,2324,2328,2332,2336,2341,2345],{"type":413,"tag":448,"props":2280,"children":2281},{"style":461},[2282],{"type":418,"value":1026},{"type":413,"tag":448,"props":2284,"children":2285},{"style":1029},[2286],{"type":418,"value":2287},"runId",{"type":413,"tag":448,"props":2289,"children":2290},{"style":461},[2291],{"type":418,"value":1154},{"type":413,"tag":448,"props":2293,"children":2294},{"style":1029},[2295],{"type":418,"value":2296},"gh run list ",{"type":413,"tag":448,"props":2298,"children":2299},{"style":461},[2300],{"type":418,"value":1071},{"type":413,"tag":448,"props":2302,"children":2303},{"style":1029},[2304],{"type":418,"value":2305},"workflow",{"type":413,"tag":448,"props":2307,"children":2308},{"style":461},[2309],{"type":418,"value":1037},{"type":413,"tag":448,"props":2311,"children":2312},{"style":1029},[2313],{"type":418,"value":2314},"main.yml ",{"type":413,"tag":448,"props":2316,"children":2317},{"style":461},[2318],{"type":418,"value":1071},{"type":413,"tag":448,"props":2320,"children":2321},{"style":1029},[2322],{"type":418,"value":2323},"json databaseId ",{"type":413,"tag":448,"props":2325,"children":2326},{"style":461},[2327],{"type":418,"value":1173},{"type":413,"tag":448,"props":2329,"children":2330},{"style":1029},[2331],{"type":418,"value":1178},{"type":413,"tag":448,"props":2333,"children":2334},{"style":461},[2335],{"type":418,"value":1183},{"type":413,"tag":448,"props":2337,"children":2338},{"style":467},[2339],{"type":418,"value":2340},".[0].databaseId",{"type":413,"tag":448,"props":2342,"children":2343},{"style":461},[2344],{"type":418,"value":1183},{"type":413,"tag":448,"props":2346,"children":2347},{"style":461},[2348],{"type":418,"value":1197},{"type":413,"tag":448,"props":2350,"children":2351},{"class":450,"line":488},[2352,2357,2361],{"type":413,"tag":448,"props":2353,"children":2354},{"style":1029},[2355],{"type":418,"value":2356},"gh run watch ",{"type":413,"tag":448,"props":2358,"children":2359},{"style":461},[2360],{"type":418,"value":1026},{"type":413,"tag":448,"props":2362,"children":2363},{"style":1029},[2364],{"type":418,"value":2365},"runId\n",{"type":413,"tag":414,"props":2367,"children":2368},{},[2369],{"type":413,"tag":832,"props":2370,"children":2374},{"alt":2371,"className":2372,"src":2373},"Screenshot of the GitHub Actions workfow run",[836,837],"/posts/images/scripting_azurereadygithub_github_1.webp",[],{"type":413,"tag":420,"props":2376,"children":2378},{"id":2377},"full-script",[2379],{"type":418,"value":2380},"Full script",{"type":413,"tag":437,"props":2382,"children":2384},{"className":1013,"code":2383,"language":248,"meta":401,"style":401},"# Initialize git repository with current code\n# You should have added the main.yml workflow file in the `.github\\workflows` directory \ngit init\ngit add .\ngit commit -m \"Intialize repository with the GitHub Actions workflow file\"\n\n# Create a new remote private GitHub repository\n$repositoryName = \"MyAzureReadyRepository\"\ngh repo create $repositoryName --private --source=. --push\n\n# Retrieve the repository full name (org/repo)\n$repositoryFullName=$(gh repo view --json nameWithOwner -q \".nameWithOwner\") \n\n# Retrieve the current subscription and current tenant identifiers \n$subscriptionId=$(az account show --query \"id\" -o tsv)\n$tenantId=$(az account show --query \"tenantId\" -o tsv)\n\n# Create an App Registration and its associated service principal\n$appId=$(az ad app create --display-name \"GitHub Action OIDC for ${repositoryFullName}\" --query \"appId\" -o tsv)\n$servicePrincipalId=$(az ad sp create --id $appId --query \"id\" -o tsv)\n\n# Assign the contributor role to the service principal on the subscription\naz role assignment create --role contributor --subscription $subscriptionId --assignee-object-id  $servicePrincipalId --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscriptionId\n\n# Prepare parameters for federated credentials\n$parametersJson = @{\n    name = \"FederatedIdentityForWorkshop\"\n    issuer = \"https://token.actions.githubusercontent.com\"\n    subject = \"repo:${repositoryFullName}:ref:refs/heads/main\"\n    description = \"Deployments for ${repositoryFullName}\"\n    audiences = @(\n        \"api://AzureADTokenExchange\"\n    )\n}\n\n# Change parameters to single line string with escaped quotes to make it work with Azure CLI\n# https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b\n$parameters = $($parametersJson | ConvertTo-Json -Depth 100 -Compress).Replace(\"`\"\", \"\\`\"\")\n\n# Create federated credentials\naz ad app federated-credential create --id $appId --parameters $parameters\n\n# Create GitHub secrets needed for the GitHub Actions\ngh secret set AZURE_TENANT_ID --body $tenantId\ngh secret set AZURE_SUBSCRIPTION_ID --body $subscriptionId\ngh secret set AZURE_CLIENT_ID --body $appId\n\n# Run workflow\ngh workflow run main.yml\n$runId=$(gh run list --workflow=main.yml --json databaseId -q \".[0].databaseId\")\ngh run watch $runId\n\n# Open the repostory in the browser\ngh repo view -w\n",[2385],{"type":413,"tag":444,"props":2386,"children":2387},{"__ignoreMap":401},[2388,2397,2405,2413,2421,2450,2457,2465,2492,2535,2542,2550,2606,2613,2621,2672,2723,2730,2738,2825,2892,2899,2907,3019,3027,3036,3060,3084,3108,3148,3180,3200,3216,3224,3232,3240,3249,3258,3358,3366,3375,3423,3431,3440,3464,3488,3512,3520,3529,3537,3605,3621,3629,3638],{"type":413,"tag":448,"props":2389,"children":2390},{"class":450,"line":451},[2391],{"type":413,"tag":448,"props":2392,"children":2394},{"style":2393},"--shiki-light:#90A4AE;--shiki-default:#546E7A;--shiki-dark:#676E95;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[2395],{"type":418,"value":2396},"# Initialize git repository with current code\n",{"type":413,"tag":448,"props":2398,"children":2399},{"class":450,"line":473},[2400],{"type":413,"tag":448,"props":2401,"children":2402},{"style":2393},[2403],{"type":418,"value":2404},"# You should have added the main.yml workflow file in the `.github\\workflows` directory \n",{"type":413,"tag":448,"props":2406,"children":2407},{"class":450,"line":488},[2408],{"type":413,"tag":448,"props":2409,"children":2410},{"style":1029},[2411],{"type":418,"value":2412},"git init\n",{"type":413,"tag":448,"props":2414,"children":2415},{"class":450,"line":501},[2416],{"type":413,"tag":448,"props":2417,"children":2418},{"style":1029},[2419],{"type":418,"value":2420},"git add .\n",{"type":413,"tag":448,"props":2422,"children":2423},{"class":450,"line":511},[2424,2429,2433,2438,2442,2446],{"type":413,"tag":448,"props":2425,"children":2426},{"style":1029},[2427],{"type":418,"value":2428},"git commit ",{"type":413,"tag":448,"props":2430,"children":2431},{"style":461},[2432],{"type":418,"value":1173},{"type":413,"tag":448,"props":2434,"children":2435},{"style":1029},[2436],{"type":418,"value":2437},"m ",{"type":413,"tag":448,"props":2439,"children":2440},{"style":461},[2441],{"type":418,"value":1183},{"type":413,"tag":448,"props":2443,"children":2444},{"style":467},[2445],{"type":418,"value":1000},{"type":413,"tag":448,"props":2447,"children":2448},{"style":461},[2449],{"type":418,"value":1005},{"type":413,"tag":448,"props":2451,"children":2452},{"class":450,"line":524},[2453],{"type":413,"tag":448,"props":2454,"children":2455},{"emptyLinePlaceholder":505},[2456],{"type":418,"value":508},{"type":413,"tag":448,"props":2458,"children":2459},{"class":450,"line":542},[2460],{"type":413,"tag":448,"props":2461,"children":2462},{"style":2393},[2463],{"type":418,"value":2464},"# Create a new remote private GitHub repository\n",{"type":413,"tag":448,"props":2466,"children":2467},{"class":450,"line":560},[2468,2472,2476,2480,2484,2488],{"type":413,"tag":448,"props":2469,"children":2470},{"style":461},[2471],{"type":418,"value":1026},{"type":413,"tag":448,"props":2473,"children":2474},{"style":1029},[2475],{"type":418,"value":1032},{"type":413,"tag":448,"props":2477,"children":2478},{"style":461},[2479],{"type":418,"value":1037},{"type":413,"tag":448,"props":2481,"children":2482},{"style":461},[2483],{"type":418,"value":995},{"type":413,"tag":448,"props":2485,"children":2486},{"style":467},[2487],{"type":418,"value":1046},{"type":413,"tag":448,"props":2489,"children":2490},{"style":461},[2491],{"type":418,"value":1005},{"type":413,"tag":448,"props":2493,"children":2494},{"class":450,"line":573},[2495,2499,2503,2507,2511,2515,2519,2523,2527,2531],{"type":413,"tag":448,"props":2496,"children":2497},{"style":1029},[2498],{"type":418,"value":1058},{"type":413,"tag":448,"props":2500,"children":2501},{"style":461},[2502],{"type":418,"value":1026},{"type":413,"tag":448,"props":2504,"children":2505},{"style":1029},[2506],{"type":418,"value":1032},{"type":413,"tag":448,"props":2508,"children":2509},{"style":461},[2510],{"type":418,"value":1071},{"type":413,"tag":448,"props":2512,"children":2513},{"style":1029},[2514],{"type":418,"value":1076},{"type":413,"tag":448,"props":2516,"children":2517},{"style":461},[2518],{"type":418,"value":1071},{"type":413,"tag":448,"props":2520,"children":2521},{"style":1029},[2522],{"type":418,"value":1085},{"type":413,"tag":448,"props":2524,"children":2525},{"style":461},[2526],{"type":418,"value":1090},{"type":413,"tag":448,"props":2528,"children":2529},{"style":461},[2530],{"type":418,"value":1095},{"type":413,"tag":448,"props":2532,"children":2533},{"style":1029},[2534],{"type":418,"value":1100},{"type":413,"tag":448,"props":2536,"children":2537},{"class":450,"line":586},[2538],{"type":413,"tag":448,"props":2539,"children":2540},{"emptyLinePlaceholder":505},[2541],{"type":418,"value":508},{"type":413,"tag":448,"props":2543,"children":2544},{"class":450,"line":604},[2545],{"type":413,"tag":448,"props":2546,"children":2547},{"style":2393},[2548],{"type":418,"value":2549},"# Retrieve the repository full name (org/repo)\n",{"type":413,"tag":448,"props":2551,"children":2552},{"class":450,"line":617},[2553,2557,2561,2565,2569,2573,2577,2581,2585,2589,2593,2597,2601],{"type":413,"tag":448,"props":2554,"children":2555},{"style":461},[2556],{"type":418,"value":1026},{"type":413,"tag":448,"props":2558,"children":2559},{"style":1029},[2560],{"type":418,"value":1149},{"type":413,"tag":448,"props":2562,"children":2563},{"style":461},[2564],{"type":418,"value":1154},{"type":413,"tag":448,"props":2566,"children":2567},{"style":1029},[2568],{"type":418,"value":1159},{"type":413,"tag":448,"props":2570,"children":2571},{"style":461},[2572],{"type":418,"value":1071},{"type":413,"tag":448,"props":2574,"children":2575},{"style":1029},[2576],{"type":418,"value":1168},{"type":413,"tag":448,"props":2578,"children":2579},{"style":461},[2580],{"type":418,"value":1173},{"type":413,"tag":448,"props":2582,"children":2583},{"style":1029},[2584],{"type":418,"value":1178},{"type":413,"tag":448,"props":2586,"children":2587},{"style":461},[2588],{"type":418,"value":1183},{"type":413,"tag":448,"props":2590,"children":2591},{"style":467},[2592],{"type":418,"value":1188},{"type":413,"tag":448,"props":2594,"children":2595},{"style":461},[2596],{"type":418,"value":1183},{"type":413,"tag":448,"props":2598,"children":2599},{"style":461},[2600],{"type":418,"value":2031},{"type":413,"tag":448,"props":2602,"children":2603},{"style":1029},[2604],{"type":418,"value":2605}," \n",{"type":413,"tag":448,"props":2607,"children":2608},{"class":450,"line":650},[2609],{"type":413,"tag":448,"props":2610,"children":2611},{"emptyLinePlaceholder":505},[2612],{"type":418,"value":508},{"type":413,"tag":448,"props":2614,"children":2615},{"class":450,"line":668},[2616],{"type":413,"tag":448,"props":2617,"children":2618},{"style":2393},[2619],{"type":418,"value":2620},"# Retrieve the current subscription and current tenant identifiers \n",{"type":413,"tag":448,"props":2622,"children":2623},{"class":450,"line":681},[2624,2628,2632,2636,2640,2644,2648,2652,2656,2660,2664,2668],{"type":413,"tag":448,"props":2625,"children":2626},{"style":461},[2627],{"type":418,"value":1026},{"type":413,"tag":448,"props":2629,"children":2630},{"style":1029},[2631],{"type":418,"value":1258},{"type":413,"tag":448,"props":2633,"children":2634},{"style":461},[2635],{"type":418,"value":1154},{"type":413,"tag":448,"props":2637,"children":2638},{"style":1029},[2639],{"type":418,"value":1267},{"type":413,"tag":448,"props":2641,"children":2642},{"style":461},[2643],{"type":418,"value":1071},{"type":413,"tag":448,"props":2645,"children":2646},{"style":1029},[2647],{"type":418,"value":1276},{"type":413,"tag":448,"props":2649,"children":2650},{"style":461},[2651],{"type":418,"value":1183},{"type":413,"tag":448,"props":2653,"children":2654},{"style":467},[2655],{"type":418,"value":1285},{"type":413,"tag":448,"props":2657,"children":2658},{"style":461},[2659],{"type":418,"value":1183},{"type":413,"tag":448,"props":2661,"children":2662},{"style":461},[2663],{"type":418,"value":1294},{"type":413,"tag":448,"props":2665,"children":2666},{"style":1029},[2667],{"type":418,"value":1299},{"type":413,"tag":448,"props":2669,"children":2670},{"style":461},[2671],{"type":418,"value":1197},{"type":413,"tag":448,"props":2673,"children":2674},{"class":450,"line":699},[2675,2679,2683,2687,2691,2695,2699,2703,2707,2711,2715,2719],{"type":413,"tag":448,"props":2676,"children":2677},{"style":461},[2678],{"type":418,"value":1026},{"type":413,"tag":448,"props":2680,"children":2681},{"style":1029},[2682],{"type":418,"value":1315},{"type":413,"tag":448,"props":2684,"children":2685},{"style":461},[2686],{"type":418,"value":1154},{"type":413,"tag":448,"props":2688,"children":2689},{"style":1029},[2690],{"type":418,"value":1267},{"type":413,"tag":448,"props":2692,"children":2693},{"style":461},[2694],{"type":418,"value":1071},{"type":413,"tag":448,"props":2696,"children":2697},{"style":1029},[2698],{"type":418,"value":1276},{"type":413,"tag":448,"props":2700,"children":2701},{"style":461},[2702],{"type":418,"value":1183},{"type":413,"tag":448,"props":2704,"children":2705},{"style":467},[2706],{"type":418,"value":1315},{"type":413,"tag":448,"props":2708,"children":2709},{"style":461},[2710],{"type":418,"value":1183},{"type":413,"tag":448,"props":2712,"children":2713},{"style":461},[2714],{"type":418,"value":1294},{"type":413,"tag":448,"props":2716,"children":2717},{"style":1029},[2718],{"type":418,"value":1299},{"type":413,"tag":448,"props":2720,"children":2721},{"style":461},[2722],{"type":418,"value":1197},{"type":413,"tag":448,"props":2724,"children":2725},{"class":450,"line":717},[2726],{"type":413,"tag":448,"props":2727,"children":2728},{"emptyLinePlaceholder":505},[2729],{"type":418,"value":508},{"type":413,"tag":448,"props":2731,"children":2732},{"class":450,"line":735},[2733],{"type":413,"tag":448,"props":2734,"children":2735},{"style":2393},[2736],{"type":418,"value":2737},"# Create an App Registration and its associated service principal\n",{"type":413,"tag":448,"props":2739,"children":2740},{"class":450,"line":743},[2741,2745,2749,2753,2757,2761,2765,2769,2773,2777,2781,2785,2789,2793,2797,2801,2805,2809,2813,2817,2821],{"type":413,"tag":448,"props":2742,"children":2743},{"style":461},[2744],{"type":418,"value":1026},{"type":413,"tag":448,"props":2746,"children":2747},{"style":1029},[2748],{"type":418,"value":1411},{"type":413,"tag":448,"props":2750,"children":2751},{"style":461},[2752],{"type":418,"value":1154},{"type":413,"tag":448,"props":2754,"children":2755},{"style":1029},[2756],{"type":418,"value":1420},{"type":413,"tag":448,"props":2758,"children":2759},{"style":461},[2760],{"type":418,"value":1071},{"type":413,"tag":448,"props":2762,"children":2763},{"style":1029},[2764],{"type":418,"value":1429},{"type":413,"tag":448,"props":2766,"children":2767},{"style":461},[2768],{"type":418,"value":1173},{"type":413,"tag":448,"props":2770,"children":2771},{"style":1029},[2772],{"type":418,"value":1438},{"type":413,"tag":448,"props":2774,"children":2775},{"style":461},[2776],{"type":418,"value":1183},{"type":413,"tag":448,"props":2778,"children":2779},{"style":467},[2780],{"type":418,"value":1447},{"type":413,"tag":448,"props":2782,"children":2783},{"style":461},[2784],{"type":418,"value":1452},{"type":413,"tag":448,"props":2786,"children":2787},{"style":1029},[2788],{"type":418,"value":1149},{"type":413,"tag":448,"props":2790,"children":2791},{"style":461},[2792],{"type":418,"value":1461},{"type":413,"tag":448,"props":2794,"children":2795},{"style":461},[2796],{"type":418,"value":1095},{"type":413,"tag":448,"props":2798,"children":2799},{"style":1029},[2800],{"type":418,"value":1276},{"type":413,"tag":448,"props":2802,"children":2803},{"style":461},[2804],{"type":418,"value":1183},{"type":413,"tag":448,"props":2806,"children":2807},{"style":467},[2808],{"type":418,"value":1411},{"type":413,"tag":448,"props":2810,"children":2811},{"style":461},[2812],{"type":418,"value":1183},{"type":413,"tag":448,"props":2814,"children":2815},{"style":461},[2816],{"type":418,"value":1294},{"type":413,"tag":448,"props":2818,"children":2819},{"style":1029},[2820],{"type":418,"value":1299},{"type":413,"tag":448,"props":2822,"children":2823},{"style":461},[2824],{"type":418,"value":1197},{"type":413,"tag":448,"props":2826,"children":2827},{"class":450,"line":772},[2828,2832,2836,2840,2844,2848,2852,2856,2860,2864,2868,2872,2876,2880,2884,2888],{"type":413,"tag":448,"props":2829,"children":2830},{"style":461},[2831],{"type":418,"value":1026},{"type":413,"tag":448,"props":2833,"children":2834},{"style":1029},[2835],{"type":418,"value":1505},{"type":413,"tag":448,"props":2837,"children":2838},{"style":461},[2839],{"type":418,"value":1154},{"type":413,"tag":448,"props":2841,"children":2842},{"style":1029},[2843],{"type":418,"value":1514},{"type":413,"tag":448,"props":2845,"children":2846},{"style":461},[2847],{"type":418,"value":1071},{"type":413,"tag":448,"props":2849,"children":2850},{"style":1029},[2851],{"type":418,"value":1523},{"type":413,"tag":448,"props":2853,"children":2854},{"style":461},[2855],{"type":418,"value":1026},{"type":413,"tag":448,"props":2857,"children":2858},{"style":1029},[2859],{"type":418,"value":1532},{"type":413,"tag":448,"props":2861,"children":2862},{"style":461},[2863],{"type":418,"value":1071},{"type":413,"tag":448,"props":2865,"children":2866},{"style":1029},[2867],{"type":418,"value":1276},{"type":413,"tag":448,"props":2869,"children":2870},{"style":461},[2871],{"type":418,"value":1183},{"type":413,"tag":448,"props":2873,"children":2874},{"style":467},[2875],{"type":418,"value":1285},{"type":413,"tag":448,"props":2877,"children":2878},{"style":461},[2879],{"type":418,"value":1183},{"type":413,"tag":448,"props":2881,"children":2882},{"style":461},[2883],{"type":418,"value":1294},{"type":413,"tag":448,"props":2885,"children":2886},{"style":1029},[2887],{"type":418,"value":1299},{"type":413,"tag":448,"props":2889,"children":2890},{"style":461},[2891],{"type":418,"value":1197},{"type":413,"tag":448,"props":2893,"children":2894},{"class":450,"line":791},[2895],{"type":413,"tag":448,"props":2896,"children":2897},{"emptyLinePlaceholder":505},[2898],{"type":418,"value":508},{"type":413,"tag":448,"props":2900,"children":2901},{"class":450,"line":800},[2902],{"type":413,"tag":448,"props":2903,"children":2904},{"style":2393},[2905],{"type":418,"value":2906},"# Assign the contributor role to the service principal on the subscription\n",{"type":413,"tag":448,"props":2908,"children":2910},{"class":450,"line":2909},23,[2911,2915,2919,2923,2927,2931,2935,2939,2943,2947,2951,2955,2959,2963,2967,2971,2975,2979,2983,2987,2991,2995,2999,3003,3007,3011,3015],{"type":413,"tag":448,"props":2912,"children":2913},{"style":1029},[2914],{"type":418,"value":1584},{"type":413,"tag":448,"props":2916,"children":2917},{"style":461},[2918],{"type":418,"value":1071},{"type":413,"tag":448,"props":2920,"children":2921},{"style":1029},[2922],{"type":418,"value":1593},{"type":413,"tag":448,"props":2924,"children":2925},{"style":461},[2926],{"type":418,"value":1071},{"type":413,"tag":448,"props":2928,"children":2929},{"style":1029},[2930],{"type":418,"value":1602},{"type":413,"tag":448,"props":2932,"children":2933},{"style":461},[2934],{"type":418,"value":1026},{"type":413,"tag":448,"props":2936,"children":2937},{"style":1029},[2938],{"type":418,"value":1611},{"type":413,"tag":448,"props":2940,"children":2941},{"style":461},[2942],{"type":418,"value":1071},{"type":413,"tag":448,"props":2944,"children":2945},{"style":1029},[2946],{"type":418,"value":1620},{"type":413,"tag":448,"props":2948,"children":2949},{"style":461},[2950],{"type":418,"value":1173},{"type":413,"tag":448,"props":2952,"children":2953},{"style":1029},[2954],{"type":418,"value":1629},{"type":413,"tag":448,"props":2956,"children":2957},{"style":461},[2958],{"type":418,"value":1173},{"type":413,"tag":448,"props":2960,"children":2961},{"style":1029},[2962],{"type":418,"value":1638},{"type":413,"tag":448,"props":2964,"children":2965},{"style":461},[2966],{"type":418,"value":1026},{"type":413,"tag":448,"props":2968,"children":2969},{"style":1029},[2970],{"type":418,"value":1647},{"type":413,"tag":448,"props":2972,"children":2973},{"style":461},[2974],{"type":418,"value":1071},{"type":413,"tag":448,"props":2976,"children":2977},{"style":1029},[2978],{"type":418,"value":1620},{"type":413,"tag":448,"props":2980,"children":2981},{"style":461},[2982],{"type":418,"value":1173},{"type":413,"tag":448,"props":2984,"children":2985},{"style":1029},[2986],{"type":418,"value":1664},{"type":413,"tag":448,"props":2988,"children":2989},{"style":461},[2990],{"type":418,"value":1173},{"type":413,"tag":448,"props":2992,"children":2993},{"style":1029},[2994],{"type":418,"value":1673},{"type":413,"tag":448,"props":2996,"children":2997},{"style":461},[2998],{"type":418,"value":1071},{"type":413,"tag":448,"props":3000,"children":3001},{"style":1029},[3002],{"type":418,"value":1682},{"type":413,"tag":448,"props":3004,"children":3005},{"style":461},[3006],{"type":418,"value":1687},{"type":413,"tag":448,"props":3008,"children":3009},{"style":1029},[3010],{"type":418,"value":1692},{"type":413,"tag":448,"props":3012,"children":3013},{"style":461},[3014],{"type":418,"value":1697},{"type":413,"tag":448,"props":3016,"children":3017},{"style":1029},[3018],{"type":418,"value":1702},{"type":413,"tag":448,"props":3020,"children":3022},{"class":450,"line":3021},24,[3023],{"type":413,"tag":448,"props":3024,"children":3025},{"emptyLinePlaceholder":505},[3026],{"type":418,"value":508},{"type":413,"tag":448,"props":3028,"children":3030},{"class":450,"line":3029},25,[3031],{"type":413,"tag":448,"props":3032,"children":3033},{"style":2393},[3034],{"type":418,"value":3035},"# Prepare parameters for federated credentials\n",{"type":413,"tag":448,"props":3037,"children":3039},{"class":450,"line":3038},26,[3040,3044,3048,3052,3056],{"type":413,"tag":448,"props":3041,"children":3042},{"style":461},[3043],{"type":418,"value":1026},{"type":413,"tag":448,"props":3045,"children":3046},{"style":1029},[3047],{"type":418,"value":1726},{"type":413,"tag":448,"props":3049,"children":3050},{"style":461},[3051],{"type":418,"value":1037},{"type":413,"tag":448,"props":3053,"children":3054},{"style":1733},[3055],{"type":418,"value":1736},{"type":413,"tag":448,"props":3057,"children":3058},{"style":461},[3059],{"type":418,"value":1741},{"type":413,"tag":448,"props":3061,"children":3063},{"class":450,"line":3062},27,[3064,3068,3072,3076,3080],{"type":413,"tag":448,"props":3065,"children":3066},{"style":1029},[3067],{"type":418,"value":1749},{"type":413,"tag":448,"props":3069,"children":3070},{"style":461},[3071],{"type":418,"value":1037},{"type":413,"tag":448,"props":3073,"children":3074},{"style":461},[3075],{"type":418,"value":995},{"type":413,"tag":448,"props":3077,"children":3078},{"style":467},[3079],{"type":418,"value":1762},{"type":413,"tag":448,"props":3081,"children":3082},{"style":461},[3083],{"type":418,"value":1005},{"type":413,"tag":448,"props":3085,"children":3087},{"class":450,"line":3086},28,[3088,3092,3096,3100,3104],{"type":413,"tag":448,"props":3089,"children":3090},{"style":1029},[3091],{"type":418,"value":1774},{"type":413,"tag":448,"props":3093,"children":3094},{"style":461},[3095],{"type":418,"value":1037},{"type":413,"tag":448,"props":3097,"children":3098},{"style":461},[3099],{"type":418,"value":995},{"type":413,"tag":448,"props":3101,"children":3102},{"style":467},[3103],{"type":418,"value":1787},{"type":413,"tag":448,"props":3105,"children":3106},{"style":461},[3107],{"type":418,"value":1005},{"type":413,"tag":448,"props":3109,"children":3111},{"class":450,"line":3110},29,[3112,3116,3120,3124,3128,3132,3136,3140,3144],{"type":413,"tag":448,"props":3113,"children":3114},{"style":1029},[3115],{"type":418,"value":1799},{"type":413,"tag":448,"props":3117,"children":3118},{"style":461},[3119],{"type":418,"value":1037},{"type":413,"tag":448,"props":3121,"children":3122},{"style":461},[3123],{"type":418,"value":995},{"type":413,"tag":448,"props":3125,"children":3126},{"style":467},[3127],{"type":418,"value":1812},{"type":413,"tag":448,"props":3129,"children":3130},{"style":461},[3131],{"type":418,"value":1452},{"type":413,"tag":448,"props":3133,"children":3134},{"style":1029},[3135],{"type":418,"value":1149},{"type":413,"tag":448,"props":3137,"children":3138},{"style":461},[3139],{"type":418,"value":1825},{"type":413,"tag":448,"props":3141,"children":3142},{"style":467},[3143],{"type":418,"value":1830},{"type":413,"tag":448,"props":3145,"children":3146},{"style":461},[3147],{"type":418,"value":1005},{"type":413,"tag":448,"props":3149,"children":3151},{"class":450,"line":3150},30,[3152,3156,3160,3164,3168,3172,3176],{"type":413,"tag":448,"props":3153,"children":3154},{"style":1029},[3155],{"type":418,"value":1842},{"type":413,"tag":448,"props":3157,"children":3158},{"style":461},[3159],{"type":418,"value":1037},{"type":413,"tag":448,"props":3161,"children":3162},{"style":461},[3163],{"type":418,"value":995},{"type":413,"tag":448,"props":3165,"children":3166},{"style":467},[3167],{"type":418,"value":1855},{"type":413,"tag":448,"props":3169,"children":3170},{"style":461},[3171],{"type":418,"value":1452},{"type":413,"tag":448,"props":3173,"children":3174},{"style":1029},[3175],{"type":418,"value":1149},{"type":413,"tag":448,"props":3177,"children":3178},{"style":461},[3179],{"type":418,"value":1868},{"type":413,"tag":448,"props":3181,"children":3183},{"class":450,"line":3182},31,[3184,3188,3192,3196],{"type":413,"tag":448,"props":3185,"children":3186},{"style":1029},[3187],{"type":418,"value":1876},{"type":413,"tag":448,"props":3189,"children":3190},{"style":461},[3191],{"type":418,"value":1037},{"type":413,"tag":448,"props":3193,"children":3194},{"style":1733},[3195],{"type":418,"value":1736},{"type":413,"tag":448,"props":3197,"children":3198},{"style":461},[3199],{"type":418,"value":1889},{"type":413,"tag":448,"props":3201,"children":3203},{"class":450,"line":3202},32,[3204,3208,3212],{"type":413,"tag":448,"props":3205,"children":3206},{"style":461},[3207],{"type":418,"value":1897},{"type":413,"tag":448,"props":3209,"children":3210},{"style":467},[3211],{"type":418,"value":1902},{"type":413,"tag":448,"props":3213,"children":3214},{"style":461},[3215],{"type":418,"value":1005},{"type":413,"tag":448,"props":3217,"children":3219},{"class":450,"line":3218},33,[3220],{"type":413,"tag":448,"props":3221,"children":3222},{"style":461},[3223],{"type":418,"value":1914},{"type":413,"tag":448,"props":3225,"children":3227},{"class":450,"line":3226},34,[3228],{"type":413,"tag":448,"props":3229,"children":3230},{"style":461},[3231],{"type":418,"value":1922},{"type":413,"tag":448,"props":3233,"children":3235},{"class":450,"line":3234},35,[3236],{"type":413,"tag":448,"props":3237,"children":3238},{"emptyLinePlaceholder":505},[3239],{"type":418,"value":508},{"type":413,"tag":448,"props":3241,"children":3243},{"class":450,"line":3242},36,[3244],{"type":413,"tag":448,"props":3245,"children":3246},{"style":2393},[3247],{"type":418,"value":3248},"# Change parameters to single line string with escaped quotes to make it work with Azure CLI\n",{"type":413,"tag":448,"props":3250,"children":3252},{"class":450,"line":3251},37,[3253],{"type":413,"tag":448,"props":3254,"children":3255},{"style":2393},[3256],{"type":418,"value":3257},"# https://medium.com/medialesson/use-dynamic-json-strings-with-azure-cli-commands-in-powershell-b191eccc8e9b\n",{"type":413,"tag":448,"props":3259,"children":3261},{"class":450,"line":3260},38,[3262,3266,3270,3274,3278,3282,3286,3290,3294,3298,3302,3306,3310,3314,3318,3322,3326,3330,3334,3338,3342,3346,3350,3354],{"type":413,"tag":448,"props":3263,"children":3264},{"style":461},[3265],{"type":418,"value":1026},{"type":413,"tag":448,"props":3267,"children":3268},{"style":1029},[3269],{"type":418,"value":1979},{"type":413,"tag":448,"props":3271,"children":3272},{"style":461},[3273],{"type":418,"value":1037},{"type":413,"tag":448,"props":3275,"children":3276},{"style":461},[3277],{"type":418,"value":1988},{"type":413,"tag":448,"props":3279,"children":3280},{"style":1029},[3281],{"type":418,"value":1726},{"type":413,"tag":448,"props":3283,"children":3284},{"style":461},[3285],{"type":418,"value":1997},{"type":413,"tag":448,"props":3287,"children":3288},{"style":2000},[3289],{"type":418,"value":2003},{"type":413,"tag":448,"props":3291,"children":3292},{"style":461},[3293],{"type":418,"value":1294},{"type":413,"tag":448,"props":3295,"children":3296},{"style":1029},[3297],{"type":418,"value":2012},{"type":413,"tag":448,"props":3299,"children":3300},{"style":1733},[3301],{"type":418,"value":2017},{"type":413,"tag":448,"props":3303,"children":3304},{"style":461},[3305],{"type":418,"value":1294},{"type":413,"tag":448,"props":3307,"children":3308},{"style":1029},[3309],{"type":418,"value":2026},{"type":413,"tag":448,"props":3311,"children":3312},{"style":461},[3313],{"type":418,"value":2031},{"type":413,"tag":448,"props":3315,"children":3316},{"style":1029},[3317],{"type":418,"value":2036},{"type":413,"tag":448,"props":3319,"children":3320},{"style":461},[3321],{"type":418,"value":2041},{"type":413,"tag":448,"props":3323,"children":3324},{"style":461},[3325],{"type":418,"value":1183},{"type":413,"tag":448,"props":3327,"children":3328},{"style":1029},[3329],{"type":418,"value":2050},{"type":413,"tag":448,"props":3331,"children":3332},{"style":461},[3333],{"type":418,"value":1183},{"type":413,"tag":448,"props":3335,"children":3336},{"style":461},[3337],{"type":418,"value":2059},{"type":413,"tag":448,"props":3339,"children":3340},{"style":461},[3341],{"type":418,"value":995},{"type":413,"tag":448,"props":3343,"children":3344},{"style":467},[3345],{"type":418,"value":2068},{"type":413,"tag":448,"props":3347,"children":3348},{"style":1029},[3349],{"type":418,"value":2050},{"type":413,"tag":448,"props":3351,"children":3352},{"style":461},[3353],{"type":418,"value":1183},{"type":413,"tag":448,"props":3355,"children":3356},{"style":461},[3357],{"type":418,"value":1197},{"type":413,"tag":448,"props":3359,"children":3361},{"class":450,"line":3360},39,[3362],{"type":413,"tag":448,"props":3363,"children":3364},{"emptyLinePlaceholder":505},[3365],{"type":418,"value":508},{"type":413,"tag":448,"props":3367,"children":3369},{"class":450,"line":3368},40,[3370],{"type":413,"tag":448,"props":3371,"children":3372},{"style":2393},[3373],{"type":418,"value":3374},"# Create federated credentials\n",{"type":413,"tag":448,"props":3376,"children":3378},{"class":450,"line":3377},41,[3379,3383,3387,3391,3395,3399,3403,3407,3411,3415,3419],{"type":413,"tag":448,"props":3380,"children":3381},{"style":1029},[3382],{"type":418,"value":2100},{"type":413,"tag":448,"props":3384,"children":3385},{"style":461},[3386],{"type":418,"value":1173},{"type":413,"tag":448,"props":3388,"children":3389},{"style":1029},[3390],{"type":418,"value":2109},{"type":413,"tag":448,"props":3392,"children":3393},{"style":461},[3394],{"type":418,"value":1071},{"type":413,"tag":448,"props":3396,"children":3397},{"style":1029},[3398],{"type":418,"value":1523},{"type":413,"tag":448,"props":3400,"children":3401},{"style":461},[3402],{"type":418,"value":1026},{"type":413,"tag":448,"props":3404,"children":3405},{"style":1029},[3406],{"type":418,"value":1532},{"type":413,"tag":448,"props":3408,"children":3409},{"style":461},[3410],{"type":418,"value":1071},{"type":413,"tag":448,"props":3412,"children":3413},{"style":1029},[3414],{"type":418,"value":1979},{"type":413,"tag":448,"props":3416,"children":3417},{"style":461},[3418],{"type":418,"value":1026},{"type":413,"tag":448,"props":3420,"children":3421},{"style":1029},[3422],{"type":418,"value":2142},{"type":413,"tag":448,"props":3424,"children":3426},{"class":450,"line":3425},42,[3427],{"type":413,"tag":448,"props":3428,"children":3429},{"emptyLinePlaceholder":505},[3430],{"type":418,"value":508},{"type":413,"tag":448,"props":3432,"children":3434},{"class":450,"line":3433},43,[3435],{"type":413,"tag":448,"props":3436,"children":3437},{"style":2393},[3438],{"type":418,"value":3439},"# Create GitHub secrets needed for the GitHub Actions\n",{"type":413,"tag":448,"props":3441,"children":3443},{"class":450,"line":3442},44,[3444,3448,3452,3456,3460],{"type":413,"tag":448,"props":3445,"children":3446},{"style":1029},[3447],{"type":418,"value":2188},{"type":413,"tag":448,"props":3449,"children":3450},{"style":461},[3451],{"type":418,"value":1071},{"type":413,"tag":448,"props":3453,"children":3454},{"style":1029},[3455],{"type":418,"value":2197},{"type":413,"tag":448,"props":3457,"children":3458},{"style":461},[3459],{"type":418,"value":1026},{"type":413,"tag":448,"props":3461,"children":3462},{"style":1029},[3463],{"type":418,"value":2206},{"type":413,"tag":448,"props":3465,"children":3467},{"class":450,"line":3466},45,[3468,3472,3476,3480,3484],{"type":413,"tag":448,"props":3469,"children":3470},{"style":1029},[3471],{"type":418,"value":2214},{"type":413,"tag":448,"props":3473,"children":3474},{"style":461},[3475],{"type":418,"value":1071},{"type":413,"tag":448,"props":3477,"children":3478},{"style":1029},[3479],{"type":418,"value":2197},{"type":413,"tag":448,"props":3481,"children":3482},{"style":461},[3483],{"type":418,"value":1026},{"type":413,"tag":448,"props":3485,"children":3486},{"style":1029},[3487],{"type":418,"value":1702},{"type":413,"tag":448,"props":3489,"children":3491},{"class":450,"line":3490},46,[3492,3496,3500,3504,3508],{"type":413,"tag":448,"props":3493,"children":3494},{"style":1029},[3495],{"type":418,"value":2238},{"type":413,"tag":448,"props":3497,"children":3498},{"style":461},[3499],{"type":418,"value":1071},{"type":413,"tag":448,"props":3501,"children":3502},{"style":1029},[3503],{"type":418,"value":2197},{"type":413,"tag":448,"props":3505,"children":3506},{"style":461},[3507],{"type":418,"value":1026},{"type":413,"tag":448,"props":3509,"children":3510},{"style":1029},[3511],{"type":418,"value":2255},{"type":413,"tag":448,"props":3513,"children":3515},{"class":450,"line":3514},47,[3516],{"type":413,"tag":448,"props":3517,"children":3518},{"emptyLinePlaceholder":505},[3519],{"type":418,"value":508},{"type":413,"tag":448,"props":3521,"children":3523},{"class":450,"line":3522},48,[3524],{"type":413,"tag":448,"props":3525,"children":3526},{"style":2393},[3527],{"type":418,"value":3528},"# Run workflow\n",{"type":413,"tag":448,"props":3530,"children":3532},{"class":450,"line":3531},49,[3533],{"type":413,"tag":448,"props":3534,"children":3535},{"style":1029},[3536],{"type":418,"value":2275},{"type":413,"tag":448,"props":3538,"children":3540},{"class":450,"line":3539},50,[3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593,3597,3601],{"type":413,"tag":448,"props":3542,"children":3543},{"style":461},[3544],{"type":418,"value":1026},{"type":413,"tag":448,"props":3546,"children":3547},{"style":1029},[3548],{"type":418,"value":2287},{"type":413,"tag":448,"props":3550,"children":3551},{"style":461},[3552],{"type":418,"value":1154},{"type":413,"tag":448,"props":3554,"children":3555},{"style":1029},[3556],{"type":418,"value":2296},{"type":413,"tag":448,"props":3558,"children":3559},{"style":461},[3560],{"type":418,"value":1071},{"type":413,"tag":448,"props":3562,"children":3563},{"style":1029},[3564],{"type":418,"value":2305},{"type":413,"tag":448,"props":3566,"children":3567},{"style":461},[3568],{"type":418,"value":1037},{"type":413,"tag":448,"props":3570,"children":3571},{"style":1029},[3572],{"type":418,"value":2314},{"type":413,"tag":448,"props":3574,"children":3575},{"style":461},[3576],{"type":418,"value":1071},{"type":413,"tag":448,"props":3578,"children":3579},{"style":1029},[3580],{"type":418,"value":2323},{"type":413,"tag":448,"props":3582,"children":3583},{"style":461},[3584],{"type":418,"value":1173},{"type":413,"tag":448,"props":3586,"children":3587},{"style":1029},[3588],{"type":418,"value":1178},{"type":413,"tag":448,"props":3590,"children":3591},{"style":461},[3592],{"type":418,"value":1183},{"type":413,"tag":448,"props":3594,"children":3595},{"style":467},[3596],{"type":418,"value":2340},{"type":413,"tag":448,"props":3598,"children":3599},{"style":461},[3600],{"type":418,"value":1183},{"type":413,"tag":448,"props":3602,"children":3603},{"style":461},[3604],{"type":418,"value":1197},{"type":413,"tag":448,"props":3606,"children":3608},{"class":450,"line":3607},51,[3609,3613,3617],{"type":413,"tag":448,"props":3610,"children":3611},{"style":1029},[3612],{"type":418,"value":2356},{"type":413,"tag":448,"props":3614,"children":3615},{"style":461},[3616],{"type":418,"value":1026},{"type":413,"tag":448,"props":3618,"children":3619},{"style":1029},[3620],{"type":418,"value":2365},{"type":413,"tag":448,"props":3622,"children":3624},{"class":450,"line":3623},52,[3625],{"type":413,"tag":448,"props":3626,"children":3627},{"emptyLinePlaceholder":505},[3628],{"type":418,"value":508},{"type":413,"tag":448,"props":3630,"children":3632},{"class":450,"line":3631},53,[3633],{"type":413,"tag":448,"props":3634,"children":3635},{"style":2393},[3636],{"type":418,"value":3637},"# Open the repostory in the browser\n",{"type":413,"tag":448,"props":3639,"children":3641},{"class":450,"line":3640},54,[3642,3646,3650],{"type":413,"tag":448,"props":3643,"children":3644},{"style":1029},[3645],{"type":418,"value":1159},{"type":413,"tag":448,"props":3647,"children":3648},{"style":461},[3649],{"type":418,"value":1173},{"type":413,"tag":448,"props":3651,"children":3652},{"style":1029},[3653],{"type":418,"value":3654},"w\n",{"type":413,"tag":420,"props":3656,"children":3658},{"id":3657},"final-thoughts",[3659],{"type":418,"value":3660},"Final Thoughts",{"type":413,"tag":414,"props":3662,"children":3663},{},[3664,3666,3672],{"type":418,"value":3665},"I am very glad to have scripted the creation and configuration of a GitHub repository ready to deploy to Azure. Even if I had already done the ",{"type":413,"tag":813,"props":3667,"children":3669},{"href":852,"rel":3668},[817],[3670],{"type":418,"value":3671},"same using Pulumi",{"type":418,"value":3673},", having a small script can sometimes be more convenient than having a full IaC program. In my case, I needed to automate that for a workshop, so it was easier to give participants a script to execute.",{"type":413,"tag":414,"props":3675,"children":3676},{},[3677],{"type":418,"value":3678},"However, I must admit that developing this script proved to be much more challenging than provisioning the same resources using Pulumi. I didn't expect it to take so much time: browsing the CLI documentation, finding the correct syntax, and understanding the cause of failures. In contrast, using the GitHub and Azure Pulumi providers in my TypeScript code turned out to be a much more enjoyable experience.",{"type":413,"tag":414,"props":3680,"children":3681},{},[3682,3684,3689,3691,3697],{"type":418,"value":3683},"Nevertheless, I was pleased to be introduced to the GitHub CLI, which I hadn't explored extensively until now. While I found it very useful, a few things bothered me. Not all commands can be used with the ",{"type":413,"tag":444,"props":3685,"children":3687},{"className":3686},[],[3688],{"type":418,"value":1211},{"type":418,"value":3690}," and ",{"type":413,"tag":444,"props":3692,"children":3694},{"className":3693},[],[3695],{"type":418,"value":3696},"-q",{"type":418,"value":3698}," parameters, which is not very convenient for scripting. Commands that create things (repo, workflow runs) don't return the identifier of the thing they create. I wish GitHub CLI would be more similar to Azure CLI in these matters. I have no doubt these will be improved over time.",{"type":413,"tag":414,"props":3700,"children":3701},{},[3702],{"type":418,"value":3703},"As for Azure CLI, I am still a big fan, although a bit disappointed to have struggled with the inline JSON string.",{"type":413,"tag":414,"props":3705,"children":3706},{},[3707],{"type":418,"value":3708},"Keep learning, keep sharing.",{"type":413,"tag":3710,"props":3711,"children":3712},"style",{},[3713],{"type":418,"value":3714},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":401,"searchDepth":473,"depth":473,"links":3716},[3717,3718,3724,3725],{"id":422,"depth":473,"text":425},{"id":861,"depth":473,"text":864,"children":3719},[3720,3721,3722,3723],{"id":868,"depth":488,"text":871},{"id":913,"depth":488,"text":916},{"id":1231,"depth":488,"text":1234},{"id":2145,"depth":488,"text":2148},{"id":2377,"depth":473,"text":2380},{"id":3657,"depth":473,"text":3660},"markdown","content:1.posts:55.scripting-azure-ready-github-repository.md","content","1.posts/55.scripting-azure-ready-github-repository.md","md",{"_path":169,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":168,"description":3732,"lead":3733,"date":3734,"image":3735,"badge":3737,"tags":3738,"body":3739,"_type":3726,"_id":7947,"_source":3728,"_file":7948,"_extension":3730},"If you are deploying your application to Azure from Azure Pipelines, you might want to leverage the ability to do so without using secrets thanks to Workload identity federation. In this article, I will demonstrate how to automate the configuration of your Azure DevOps project, with everything pre-configured to securely deploy applications to Azure.","Azure DevOps Workload identity federation (OIDC) with Pulumi","2023-09-21T00:00:00.000Z",{"src":3736},"/images/azuredevopsoidc.webp",{"label":266},[228,233,307,374,312,315,376,239],{"type":410,"children":3740,"toc":7934},[3741,3745,3751,3765,3779,3784,3804,3813,3831,3843,3848,3861,3866,3871,3879,3888,3893,3898,3908,3914,3920,3925,3987,3999,4058,4063,4102,4107,4152,4158,4163,4202,4216,4252,4276,4281,4638,4643,4657,4767,4772,5038,5078,5084,5098,5387,5400,5557,5562,5584,5810,5816,5821,5839,5844,6320,6335,6340,6657,6670,6676,6681,6694,6927,6932,7187,7192,7463,7468,7653,7658,7822,7835,7866,7875,7880,7886,7899,7904,7909,7914,7930],{"type":413,"tag":414,"props":3742,"children":3743},{},[3744],{"type":418,"value":3732},{"type":413,"tag":420,"props":3746,"children":3748},{"id":3747},"why-should-you-use-workload-identity-federation-for-your-deployment-pipelines",[3749],{"type":418,"value":3750},"Why should you use Workload Identity Federation for your deployment pipelines?",{"type":413,"tag":414,"props":3752,"children":3753},{},[3754,3756,3763],{"type":418,"value":3755},"I already wrote about the ",{"type":413,"tag":813,"props":3757,"children":3760},{"href":3758,"rel":3759},"https://www.techwatching.dev/posts/azure-ready-github-repository#the-problem-with-secret-credentials",[817],[3761],{"type":418,"value":3762},"problem of secret credentials",{"type":418,"value":3764},", but let me remind you 2 reasons why I think you should always avoid using secrets in your deployment pipelines:",{"type":413,"tag":3766,"props":3767,"children":3768},"ul",{},[3769,3774],{"type":413,"tag":2159,"props":3770,"children":3771},{},[3772],{"type":418,"value":3773},"It's more secure if you don't need a secret to authenticate to Azure",{"type":413,"tag":2159,"props":3775,"children":3776},{},[3777],{"type":418,"value":3778},"It's more practical if you don't need to handle secret rotation when secrets expire",{"type":413,"tag":414,"props":3780,"children":3781},{},[3782],{"type":418,"value":3783},"This is true whatever the CI/CD platform you are using.",{"type":413,"tag":414,"props":3785,"children":3786},{},[3787,3794,3796,3802],{"type":413,"tag":813,"props":3788,"children":3791},{"href":3789,"rel":3790},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation",[817],[3792],{"type":418,"value":3793},"Workload identity federation",{"type":418,"value":3795}," leverages OpenID Connect to solve these problems and avoid using secrets in your pipelines to authenticate to Azure. I previously published ",{"type":413,"tag":813,"props":3797,"children":3799},{"href":852,"rel":3798},[817],[3800],{"type":418,"value":3801},"an article about using Azure OpenID Connect with Pulumi in GitHub Actions",{"type":418,"value":3803},", but that also works with Azure Pipelines.",{"type":413,"tag":414,"props":3805,"children":3806},{},[3807],{"type":413,"tag":832,"props":3808,"children":3812},{"alt":3809,"className":3810,"src":3811},"Workload Identity Federation for Azure DevOps",[836,837],"/posts/images/azuredevopsoidc_schema_1.webp",[],{"type":413,"tag":841,"props":3814,"children":3816},{"icon":3815},"i-heroicons-information-circle",[3817],{"type":413,"tag":414,"props":3818,"children":3819},{},[3820,3822,3829],{"type":418,"value":3821},"Microsoft has announced the ",{"type":413,"tag":813,"props":3823,"children":3826},{"href":3824,"rel":3825},"https://devblogs.microsoft.com/devops/public-preview-of-workload-identity-federation-for-azure-pipelines/",[817],[3827],{"type":418,"value":3828},"public preview of Workload identity federation for Azure Pipelines",{"type":418,"value":3830}," on the 11th September 2023.",{"type":413,"tag":420,"props":3832,"children":3834},{"id":3833},"how-can-you-use-workload-identity-federation-to-deploy-to-azure-from-azure-pipelines",[3835,3837],{"type":418,"value":3836},"How can you use ",{"type":413,"tag":3838,"props":3839,"children":3840},"strong",{},[3841],{"type":418,"value":3842},"Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"type":413,"tag":414,"props":3844,"children":3845},{},[3846],{"type":418,"value":3847},"Azure Pipelines tasks use service connections to authenticate with external services. Specifically, for Azure, it is necessary to create an Azure Resource Manager service connection.",{"type":413,"tag":414,"props":3849,"children":3850},{},[3851,3853,3859],{"type":418,"value":3852},"You can create an Azure Resource Manager service connection that uses workload identity federation by configuring it in your Azure DevOps organization portal (check the documentation ",{"type":413,"tag":813,"props":3854,"children":3857},{"href":3855,"rel":3856},"https://learn.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=azure-devops#create-an-azure-resource-manager-service-connection-using-workload-identity-federation",[817],[3858],{"type":418,"value":1386},{"type":418,"value":3860},").",{"type":413,"tag":414,"props":3862,"children":3863},{},[3864],{"type":418,"value":3865},"Or ... you can automate that using Infrastructure as Code 😉.",{"type":413,"tag":414,"props":3867,"children":3868},{},[3869],{"type":418,"value":3870},"Yet, who wants to manually configure things from a wizard when everything can be automated in versioned code? So let's go the IaC way.",{"type":413,"tag":841,"props":3872,"children":3873},{"icon":843},[3874],{"type":413,"tag":414,"props":3875,"children":3876},{},[3877],{"type":418,"value":3878},"All kidding aside, I genuinely believe that there are many advantages to provisioning your Azure DevOps projects and their associated resources (Repos, Service Connections, policies, pipelines, ...) using Infrastructure as Code. It takes time to properly configure Azure DevOps projects, and if they are often organized similarly, it's more efficient to automate their configuration rather than doing it manually.",{"type":413,"tag":414,"props":3880,"children":3881},{},[3882],{"type":413,"tag":832,"props":3883,"children":3887},{"alt":3884,"className":3885,"src":3886},"Diagram to deploy from Azure Pipelines to Azure",[836,837],"/posts/images/azuredevopsoidc_schema_2.webp",[],{"type":413,"tag":414,"props":3889,"children":3890},{},[3891],{"type":418,"value":3892},"I will use Pulumi and its Azure DevOps provider to provision the necessary resources. The infrastructure as code will be written in C# but you could easily convert the C# code to any language that Pulumi supports (like TypeScript, I am a big fan of using TypeScript to write infrastructure code 🔥).",{"type":413,"tag":414,"props":3894,"children":3895},{},[3896],{"type":418,"value":3897},"Here is the complete solution to implement:",{"type":413,"tag":414,"props":3899,"children":3900},{},[3901],{"type":413,"tag":832,"props":3902,"children":3907},{"alt":3903,"className":3904,"src":3905,"width":3906},"Schema of the complete solution",[836,837],"/posts/images/azuredevopsoidc_schema_3.webp",1000,[],{"type":413,"tag":420,"props":3909,"children":3911},{"id":3910},"automate-the-configuration-of-workload-identity-federation-in-azure-devops",[3912],{"type":418,"value":3913},"Automate the configuration of Workload identity federation in Azure DevOps",{"type":413,"tag":866,"props":3915,"children":3917},{"id":3916},"create-the-pulumi-net-project",[3918],{"type":418,"value":3919},"Create the Pulumi .NET project",{"type":413,"tag":414,"props":3921,"children":3922},{},[3923],{"type":418,"value":3924},"Let's start by scaffolding a new Pulumi project using .NET:",{"type":413,"tag":437,"props":3926,"children":3928},{"className":937,"code":3927,"language":939,"meta":401,"style":401},"pulumi new csharp -n AzureDevOpsWorkloadIdentity -s dev -d \"A program to set up an Azure-Ready Azure DevOps repository\"\n",[3929],{"type":413,"tag":444,"props":3930,"children":3931},{"__ignoreMap":401},[3932],{"type":413,"tag":448,"props":3933,"children":3934},{"class":450,"line":451},[3935,3939,3944,3949,3954,3959,3964,3969,3974,3978,3983],{"type":413,"tag":448,"props":3936,"children":3937},{"style":949},[3938],{"type":418,"value":311},{"type":413,"tag":448,"props":3940,"children":3941},{"style":467},[3942],{"type":418,"value":3943}," new",{"type":413,"tag":448,"props":3945,"children":3946},{"style":467},[3947],{"type":418,"value":3948}," csharp",{"type":413,"tag":448,"props":3950,"children":3951},{"style":467},[3952],{"type":418,"value":3953}," -n",{"type":413,"tag":448,"props":3955,"children":3956},{"style":467},[3957],{"type":418,"value":3958}," AzureDevOpsWorkloadIdentity",{"type":413,"tag":448,"props":3960,"children":3961},{"style":467},[3962],{"type":418,"value":3963}," -s",{"type":413,"tag":448,"props":3965,"children":3966},{"style":467},[3967],{"type":418,"value":3968}," dev",{"type":413,"tag":448,"props":3970,"children":3971},{"style":467},[3972],{"type":418,"value":3973}," -d",{"type":413,"tag":448,"props":3975,"children":3976},{"style":461},[3977],{"type":418,"value":995},{"type":413,"tag":448,"props":3979,"children":3980},{"style":467},[3981],{"type":418,"value":3982},"A program to set up an Azure-Ready Azure DevOps repository",{"type":413,"tag":448,"props":3984,"children":3985},{"style":461},[3986],{"type":418,"value":1005},{"type":413,"tag":414,"props":3988,"children":3989},{},[3990,3992,3997],{"type":418,"value":3991},"This command creates a new pulumi project and stack from the ",{"type":413,"tag":444,"props":3993,"children":3995},{"className":3994},[],[3996],{"type":418,"value":326},{"type":418,"value":3998}," template:",{"type":413,"tag":3766,"props":4000,"children":4001},{},[4002,4023,4040],{"type":413,"tag":2159,"props":4003,"children":4004},{},[4005,4007,4013,4015,4021],{"type":418,"value":4006},"The name of the project \"",{"type":413,"tag":4008,"props":4009,"children":4010},"em",{},[4011],{"type":418,"value":4012},"AzureDevOpsWorkloadIdentity",{"type":418,"value":4014},"\" is specified using the ",{"type":413,"tag":444,"props":4016,"children":4018},{"className":4017},[],[4019],{"type":418,"value":4020},"-n",{"type":418,"value":4022}," option",{"type":413,"tag":2159,"props":4024,"children":4025},{},[4026,4028,4032,4033,4039],{"type":418,"value":4027},"The description of the project \"",{"type":413,"tag":4008,"props":4029,"children":4030},{},[4031],{"type":418,"value":3982},{"type":418,"value":4014},{"type":413,"tag":444,"props":4034,"children":4036},{"className":4035},[],[4037],{"type":418,"value":4038},"-d",{"type":418,"value":4022},{"type":413,"tag":2159,"props":4041,"children":4042},{},[4043,4045,4050,4051,4057],{"type":418,"value":4044},"The stack of the project \"",{"type":413,"tag":4008,"props":4046,"children":4047},{},[4048],{"type":418,"value":4049},"dev",{"type":418,"value":4014},{"type":413,"tag":444,"props":4052,"children":4054},{"className":4053},[],[4055],{"type":418,"value":4056},"-s",{"type":418,"value":4022},{"type":413,"tag":414,"props":4059,"children":4060},{},[4061],{"type":418,"value":4062},"This project will need 3 different providers:",{"type":413,"tag":3766,"props":4064,"children":4065},{},[4066,4078,4091],{"type":413,"tag":2159,"props":4067,"children":4068},{},[4069,4071],{"type":418,"value":4070},"the ",{"type":413,"tag":813,"props":4072,"children":4075},{"href":4073,"rel":4074},"https://www.pulumi.com/registry/packages/azure-native/",[817],[4076],{"type":418,"value":4077},"Azure Native provider",{"type":413,"tag":2159,"props":4079,"children":4080},{},[4081,4082,4089],{"type":418,"value":4070},{"type":413,"tag":813,"props":4083,"children":4086},{"href":4084,"rel":4085},"https://www.pulumi.com/registry/packages/azuread/",[817],[4087],{"type":418,"value":4088},"Azure Active Directory provider",{"type":418,"value":4090}," (provider for Microsoft Entra ID)",{"type":413,"tag":2159,"props":4092,"children":4093},{},[4094,4095],{"type":418,"value":4070},{"type":413,"tag":813,"props":4096,"children":4099},{"href":4097,"rel":4098},"https://www.pulumi.com/registry/packages/azuredevops/",[817],[4100],{"type":418,"value":4101},"Azure DevOps provider",{"type":413,"tag":414,"props":4103,"children":4104},{},[4105],{"type":418,"value":4106},"So we can add the following Nuget packages to our project:",{"type":413,"tag":3766,"props":4108,"children":4109},{},[4110,4124,4138],{"type":413,"tag":2159,"props":4111,"children":4112},{},[4113],{"type":413,"tag":813,"props":4114,"children":4117},{"href":4115,"rel":4116},"https://www.nuget.org/packages/Pulumi.AzureNative",[817],[4118],{"type":413,"tag":444,"props":4119,"children":4121},{"className":4120},[],[4122],{"type":418,"value":4123},"Pulumi.AzureNative",{"type":413,"tag":2159,"props":4125,"children":4126},{},[4127],{"type":413,"tag":813,"props":4128,"children":4131},{"href":4129,"rel":4130},"https://www.nuget.org/packages/Pulumi.AzureAD",[817],[4132],{"type":413,"tag":444,"props":4133,"children":4135},{"className":4134},[],[4136],{"type":418,"value":4137},"Pulumi.AzureAD",{"type":413,"tag":2159,"props":4139,"children":4140},{},[4141],{"type":413,"tag":813,"props":4142,"children":4145},{"href":4143,"rel":4144},"https://www.nuget.org/packages/Pulumi.AzureDevOps",[817],[4146],{"type":413,"tag":444,"props":4147,"children":4149},{"className":4148},[],[4150],{"type":418,"value":4151},"Pulumi.AzureDevOps",{"type":413,"tag":866,"props":4153,"children":4155},{"id":4154},"create-the-azure-devops-project",[4156],{"type":418,"value":4157},"Create the Azure DevOps project",{"type":413,"tag":414,"props":4159,"children":4160},{},[4161],{"type":418,"value":4162},"First, we must select the Azure DevOps organization where we wish to create a project and set its URL in our Pulumi configuration.",{"type":413,"tag":437,"props":4164,"children":4166},{"className":937,"code":4165,"language":939,"meta":401,"style":401},"pulumi config set azuredevops:orgServiceUrl XXXXXXXXXXXXXX --secret\n",[4167],{"type":413,"tag":444,"props":4168,"children":4169},{"__ignoreMap":401},[4170],{"type":413,"tag":448,"props":4171,"children":4172},{"class":450,"line":451},[4173,4177,4182,4187,4192,4197],{"type":413,"tag":448,"props":4174,"children":4175},{"style":949},[4176],{"type":418,"value":311},{"type":413,"tag":448,"props":4178,"children":4179},{"style":467},[4180],{"type":418,"value":4181}," config",{"type":413,"tag":448,"props":4183,"children":4184},{"style":467},[4185],{"type":418,"value":4186}," set",{"type":413,"tag":448,"props":4188,"children":4189},{"style":467},[4190],{"type":418,"value":4191}," azuredevops:orgServiceUrl",{"type":413,"tag":448,"props":4193,"children":4194},{"style":467},[4195],{"type":418,"value":4196}," XXXXXXXXXXXXXX",{"type":413,"tag":448,"props":4198,"children":4199},{"style":467},[4200],{"type":418,"value":4201}," --secret\n",{"type":413,"tag":414,"props":4203,"children":4204},{},[4205,4207,4214],{"type":418,"value":4206},"Second, we need to supply the necessary Azure DevOps credentials. For that, we can ",{"type":413,"tag":813,"props":4208,"children":4211},{"href":4209,"rel":4210},"https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows#create-a-pat",[817],[4212],{"type":418,"value":4213},"create a personal access token",{"type":418,"value":4215}," and add it to our Pulumi configuration.",{"type":413,"tag":437,"props":4217,"children":4219},{"className":937,"code":4218,"language":939,"meta":401,"style":401},"pulumi config set azuredevops:personalAccessToken YYYYYYYYYYYYYY --secret\n",[4220],{"type":413,"tag":444,"props":4221,"children":4222},{"__ignoreMap":401},[4223],{"type":413,"tag":448,"props":4224,"children":4225},{"class":450,"line":451},[4226,4230,4234,4238,4243,4248],{"type":413,"tag":448,"props":4227,"children":4228},{"style":949},[4229],{"type":418,"value":311},{"type":413,"tag":448,"props":4231,"children":4232},{"style":467},[4233],{"type":418,"value":4181},{"type":413,"tag":448,"props":4235,"children":4236},{"style":467},[4237],{"type":418,"value":4186},{"type":413,"tag":448,"props":4239,"children":4240},{"style":467},[4241],{"type":418,"value":4242}," azuredevops:personalAccessToken",{"type":413,"tag":448,"props":4244,"children":4245},{"style":467},[4246],{"type":418,"value":4247}," YYYYYYYYYYYYYY",{"type":413,"tag":448,"props":4249,"children":4250},{"style":467},[4251],{"type":418,"value":4201},{"type":413,"tag":841,"props":4253,"children":4255},{"icon":4254},"i-fluent-emoji-flat-locked-with-key",[4256],{"type":413,"tag":414,"props":4257,"children":4258},{},[4259,4261,4267,4269,4274],{"type":418,"value":4260},"I followed the documentation but to be honest, I don't think it's necessary to include the ",{"type":413,"tag":444,"props":4262,"children":4264},{"className":4263},[],[4265],{"type":418,"value":4266},"--secret",{"type":418,"value":4268}," option for the organization URL as it's not really a sensitive value that needs to be encrypted. However, ",{"type":413,"tag":3838,"props":4270,"children":4271},{},[4272],{"type":418,"value":4273},"it's mandatory to include it for the access token",{"type":418,"value":4275}," so that we can safely commit the configuration files without creating security risks.",{"type":413,"tag":414,"props":4277,"children":4278},{},[4279],{"type":418,"value":4280},"Third, we can create the DevOps project:",{"type":413,"tag":437,"props":4282,"children":4285},{"className":4283,"code":4284,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","var project = new Project(\"AzureReadyADOProject\", new()\n{\n    Description = \"New project with everything correctly configured to provision Azure resources or deploy applications to Azure\",\n    Features = new()\n    {\n        [\"boards\"] = \"disabled\",\n        [\"repositories\"] = \"enabled\",\n        [\"pipelines\"] = \"enabled\",\n        [\"testplans\"] = \"disabled\",\n        [\"artifacts\"] = \"disabled\"\n    },\n});\n",[4286],{"type":413,"tag":444,"props":4287,"children":4288},{"__ignoreMap":401},[4289,4342,4349,4379,4395,4403,4450,4495,4538,4582,4622,4630],{"type":413,"tag":448,"props":4290,"children":4291},{"class":450,"line":451},[4292,4297,4302,4307,4311,4316,4320,4324,4329,4333,4337],{"type":413,"tag":448,"props":4293,"children":4294},{"style":949},[4295],{"type":418,"value":4296},"var",{"type":413,"tag":448,"props":4298,"children":4299},{"style":949},[4300],{"type":418,"value":4301}," project",{"type":413,"tag":448,"props":4303,"children":4304},{"style":461},[4305],{"type":418,"value":4306}," =",{"type":413,"tag":448,"props":4308,"children":4309},{"style":461},[4310],{"type":418,"value":3943},{"type":413,"tag":448,"props":4312,"children":4313},{"style":949},[4314],{"type":418,"value":4315}," Project",{"type":413,"tag":448,"props":4317,"children":4318},{"style":461},[4319],{"type":418,"value":2041},{"type":413,"tag":448,"props":4321,"children":4322},{"style":461},[4323],{"type":418,"value":1183},{"type":413,"tag":448,"props":4325,"children":4326},{"style":467},[4327],{"type":418,"value":4328},"AzureReadyADOProject",{"type":413,"tag":448,"props":4330,"children":4331},{"style":461},[4332],{"type":418,"value":1183},{"type":413,"tag":448,"props":4334,"children":4335},{"style":461},[4336],{"type":418,"value":2059},{"type":413,"tag":448,"props":4338,"children":4339},{"style":461},[4340],{"type":418,"value":4341}," new()\n",{"type":413,"tag":448,"props":4343,"children":4344},{"class":450,"line":473},[4345],{"type":413,"tag":448,"props":4346,"children":4347},{"style":461},[4348],{"type":418,"value":1741},{"type":413,"tag":448,"props":4350,"children":4351},{"class":450,"line":488},[4352,4357,4361,4365,4370,4374],{"type":413,"tag":448,"props":4353,"children":4354},{"style":1029},[4355],{"type":418,"value":4356},"    Description ",{"type":413,"tag":448,"props":4358,"children":4359},{"style":461},[4360],{"type":418,"value":1037},{"type":413,"tag":448,"props":4362,"children":4363},{"style":461},[4364],{"type":418,"value":995},{"type":413,"tag":448,"props":4366,"children":4367},{"style":467},[4368],{"type":418,"value":4369},"New project with everything correctly configured to provision Azure resources or deploy applications to Azure",{"type":413,"tag":448,"props":4371,"children":4372},{"style":461},[4373],{"type":418,"value":1183},{"type":413,"tag":448,"props":4375,"children":4376},{"style":461},[4377],{"type":418,"value":4378},",\n",{"type":413,"tag":448,"props":4380,"children":4381},{"class":450,"line":501},[4382,4387,4391],{"type":413,"tag":448,"props":4383,"children":4384},{"style":1029},[4385],{"type":418,"value":4386},"    Features ",{"type":413,"tag":448,"props":4388,"children":4389},{"style":461},[4390],{"type":418,"value":1037},{"type":413,"tag":448,"props":4392,"children":4393},{"style":461},[4394],{"type":418,"value":4341},{"type":413,"tag":448,"props":4396,"children":4397},{"class":450,"line":511},[4398],{"type":413,"tag":448,"props":4399,"children":4400},{"style":461},[4401],{"type":418,"value":4402},"    {\n",{"type":413,"tag":448,"props":4404,"children":4405},{"class":450,"line":524},[4406,4411,4415,4420,4424,4429,4433,4437,4442,4446],{"type":413,"tag":448,"props":4407,"children":4408},{"style":461},[4409],{"type":418,"value":4410},"        [",{"type":413,"tag":448,"props":4412,"children":4413},{"style":461},[4414],{"type":418,"value":1183},{"type":413,"tag":448,"props":4416,"children":4417},{"style":467},[4418],{"type":418,"value":4419},"boards",{"type":413,"tag":448,"props":4421,"children":4422},{"style":461},[4423],{"type":418,"value":1183},{"type":413,"tag":448,"props":4425,"children":4426},{"style":461},[4427],{"type":418,"value":4428},"]",{"type":413,"tag":448,"props":4430,"children":4431},{"style":461},[4432],{"type":418,"value":4306},{"type":413,"tag":448,"props":4434,"children":4435},{"style":461},[4436],{"type":418,"value":995},{"type":413,"tag":448,"props":4438,"children":4439},{"style":467},[4440],{"type":418,"value":4441},"disabled",{"type":413,"tag":448,"props":4443,"children":4444},{"style":461},[4445],{"type":418,"value":1183},{"type":413,"tag":448,"props":4447,"children":4448},{"style":461},[4449],{"type":418,"value":4378},{"type":413,"tag":448,"props":4451,"children":4452},{"class":450,"line":542},[4453,4457,4461,4466,4470,4474,4478,4482,4487,4491],{"type":413,"tag":448,"props":4454,"children":4455},{"style":461},[4456],{"type":418,"value":4410},{"type":413,"tag":448,"props":4458,"children":4459},{"style":461},[4460],{"type":418,"value":1183},{"type":413,"tag":448,"props":4462,"children":4463},{"style":467},[4464],{"type":418,"value":4465},"repositories",{"type":413,"tag":448,"props":4467,"children":4468},{"style":461},[4469],{"type":418,"value":1183},{"type":413,"tag":448,"props":4471,"children":4472},{"style":461},[4473],{"type":418,"value":4428},{"type":413,"tag":448,"props":4475,"children":4476},{"style":461},[4477],{"type":418,"value":4306},{"type":413,"tag":448,"props":4479,"children":4480},{"style":461},[4481],{"type":418,"value":995},{"type":413,"tag":448,"props":4483,"children":4484},{"style":467},[4485],{"type":418,"value":4486},"enabled",{"type":413,"tag":448,"props":4488,"children":4489},{"style":461},[4490],{"type":418,"value":1183},{"type":413,"tag":448,"props":4492,"children":4493},{"style":461},[4494],{"type":418,"value":4378},{"type":413,"tag":448,"props":4496,"children":4497},{"class":450,"line":560},[4498,4502,4506,4510,4514,4518,4522,4526,4530,4534],{"type":413,"tag":448,"props":4499,"children":4500},{"style":461},[4501],{"type":418,"value":4410},{"type":413,"tag":448,"props":4503,"children":4504},{"style":461},[4505],{"type":418,"value":1183},{"type":413,"tag":448,"props":4507,"children":4508},{"style":467},[4509],{"type":418,"value":367},{"type":413,"tag":448,"props":4511,"children":4512},{"style":461},[4513],{"type":418,"value":1183},{"type":413,"tag":448,"props":4515,"children":4516},{"style":461},[4517],{"type":418,"value":4428},{"type":413,"tag":448,"props":4519,"children":4520},{"style":461},[4521],{"type":418,"value":4306},{"type":413,"tag":448,"props":4523,"children":4524},{"style":461},[4525],{"type":418,"value":995},{"type":413,"tag":448,"props":4527,"children":4528},{"style":467},[4529],{"type":418,"value":4486},{"type":413,"tag":448,"props":4531,"children":4532},{"style":461},[4533],{"type":418,"value":1183},{"type":413,"tag":448,"props":4535,"children":4536},{"style":461},[4537],{"type":418,"value":4378},{"type":413,"tag":448,"props":4539,"children":4540},{"class":450,"line":573},[4541,4545,4549,4554,4558,4562,4566,4570,4574,4578],{"type":413,"tag":448,"props":4542,"children":4543},{"style":461},[4544],{"type":418,"value":4410},{"type":413,"tag":448,"props":4546,"children":4547},{"style":461},[4548],{"type":418,"value":1183},{"type":413,"tag":448,"props":4550,"children":4551},{"style":467},[4552],{"type":418,"value":4553},"testplans",{"type":413,"tag":448,"props":4555,"children":4556},{"style":461},[4557],{"type":418,"value":1183},{"type":413,"tag":448,"props":4559,"children":4560},{"style":461},[4561],{"type":418,"value":4428},{"type":413,"tag":448,"props":4563,"children":4564},{"style":461},[4565],{"type":418,"value":4306},{"type":413,"tag":448,"props":4567,"children":4568},{"style":461},[4569],{"type":418,"value":995},{"type":413,"tag":448,"props":4571,"children":4572},{"style":467},[4573],{"type":418,"value":4441},{"type":413,"tag":448,"props":4575,"children":4576},{"style":461},[4577],{"type":418,"value":1183},{"type":413,"tag":448,"props":4579,"children":4580},{"style":461},[4581],{"type":418,"value":4378},{"type":413,"tag":448,"props":4583,"children":4584},{"class":450,"line":586},[4585,4589,4593,4598,4602,4606,4610,4614,4618],{"type":413,"tag":448,"props":4586,"children":4587},{"style":461},[4588],{"type":418,"value":4410},{"type":413,"tag":448,"props":4590,"children":4591},{"style":461},[4592],{"type":418,"value":1183},{"type":413,"tag":448,"props":4594,"children":4595},{"style":467},[4596],{"type":418,"value":4597},"artifacts",{"type":413,"tag":448,"props":4599,"children":4600},{"style":461},[4601],{"type":418,"value":1183},{"type":413,"tag":448,"props":4603,"children":4604},{"style":461},[4605],{"type":418,"value":4428},{"type":413,"tag":448,"props":4607,"children":4608},{"style":461},[4609],{"type":418,"value":4306},{"type":413,"tag":448,"props":4611,"children":4612},{"style":461},[4613],{"type":418,"value":995},{"type":413,"tag":448,"props":4615,"children":4616},{"style":467},[4617],{"type":418,"value":4441},{"type":413,"tag":448,"props":4619,"children":4620},{"style":461},[4621],{"type":418,"value":1005},{"type":413,"tag":448,"props":4623,"children":4624},{"class":450,"line":604},[4625],{"type":413,"tag":448,"props":4626,"children":4627},{"style":461},[4628],{"type":418,"value":4629},"    },\n",{"type":413,"tag":448,"props":4631,"children":4632},{"class":450,"line":617},[4633],{"type":413,"tag":448,"props":4634,"children":4635},{"style":461},[4636],{"type":418,"value":4637},"});\n",{"type":413,"tag":414,"props":4639,"children":4640},{},[4641],{"type":418,"value":4642},"I intentionally disabled Azure Boards, Azure Test Plans, and Azure Artifacts as we only need Azure Repos and Azure Pipelines for this demo but you can enable what you need for your projects.",{"type":413,"tag":414,"props":4644,"children":4645},{},[4646,4648,4655],{"type":418,"value":4647},"By default, when we create an Azure DevOps project, a ",{"type":413,"tag":813,"props":4649,"children":4652},{"href":4650,"rel":4651},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/git/",[817],[4653],{"type":418,"value":4654},"Git repository",{"type":418,"value":4656}," is created for us with the same name as the project. This repository can be retrieved using the following code:",{"type":413,"tag":437,"props":4658,"children":4660},{"className":4283,"code":4659,"language":326,"meta":401,"style":401},"var repository = GetGitRepository.Invoke(new()\n{\n    ProjectId = project.Id,\n    Name = project.Name\n});\n",[4661],{"type":413,"tag":444,"props":4662,"children":4663},{"__ignoreMap":401},[4664,4699,4706,4735,4760],{"type":413,"tag":448,"props":4665,"children":4666},{"class":450,"line":451},[4667,4671,4676,4680,4685,4689,4694],{"type":413,"tag":448,"props":4668,"children":4669},{"style":949},[4670],{"type":418,"value":4296},{"type":413,"tag":448,"props":4672,"children":4673},{"style":949},[4674],{"type":418,"value":4675}," repository",{"type":413,"tag":448,"props":4677,"children":4678},{"style":461},[4679],{"type":418,"value":4306},{"type":413,"tag":448,"props":4681,"children":4682},{"style":1029},[4683],{"type":418,"value":4684}," GetGitRepository",{"type":413,"tag":448,"props":4686,"children":4687},{"style":461},[4688],{"type":418,"value":898},{"type":413,"tag":448,"props":4690,"children":4691},{"style":2000},[4692],{"type":418,"value":4693},"Invoke",{"type":413,"tag":448,"props":4695,"children":4696},{"style":461},[4697],{"type":418,"value":4698},"(new()\n",{"type":413,"tag":448,"props":4700,"children":4701},{"class":450,"line":473},[4702],{"type":413,"tag":448,"props":4703,"children":4704},{"style":461},[4705],{"type":418,"value":1741},{"type":413,"tag":448,"props":4707,"children":4708},{"class":450,"line":488},[4709,4714,4718,4722,4726,4731],{"type":413,"tag":448,"props":4710,"children":4711},{"style":1029},[4712],{"type":418,"value":4713},"    ProjectId ",{"type":413,"tag":448,"props":4715,"children":4716},{"style":461},[4717],{"type":418,"value":1037},{"type":413,"tag":448,"props":4719,"children":4720},{"style":1029},[4721],{"type":418,"value":4301},{"type":413,"tag":448,"props":4723,"children":4724},{"style":461},[4725],{"type":418,"value":898},{"type":413,"tag":448,"props":4727,"children":4728},{"style":1029},[4729],{"type":418,"value":4730},"Id",{"type":413,"tag":448,"props":4732,"children":4733},{"style":461},[4734],{"type":418,"value":4378},{"type":413,"tag":448,"props":4736,"children":4737},{"class":450,"line":501},[4738,4743,4747,4751,4755],{"type":413,"tag":448,"props":4739,"children":4740},{"style":1029},[4741],{"type":418,"value":4742},"    Name ",{"type":413,"tag":448,"props":4744,"children":4745},{"style":461},[4746],{"type":418,"value":1037},{"type":413,"tag":448,"props":4748,"children":4749},{"style":1029},[4750],{"type":418,"value":4301},{"type":413,"tag":448,"props":4752,"children":4753},{"style":461},[4754],{"type":418,"value":898},{"type":413,"tag":448,"props":4756,"children":4757},{"style":1029},[4758],{"type":418,"value":4759},"Name\n",{"type":413,"tag":448,"props":4761,"children":4762},{"class":450,"line":511},[4763],{"type":413,"tag":448,"props":4764,"children":4765},{"style":461},[4766],{"type":418,"value":4637},{"type":413,"tag":414,"props":4768,"children":4769},{},[4770],{"type":418,"value":4771},"We can also choose to create a new Git repository like this:",{"type":413,"tag":437,"props":4773,"children":4775},{"className":4283,"code":4774,"language":326,"meta":401,"style":401},"var repository = new Git(\"AzureReadyADORepository\", new()\n{\n    ProjectId = project.Id,\n    Initialization = new GitInitializationArgs()\n    {\n        InitType = \"Clean\",\n        SourceType = \"Git\",\n        SourceUrl = \"https://repo.com\",\n        ServiceConnectionId = \"\"\n    },\n    DefaultBranch = \"refs/heads/main\"\n});\n",[4776],{"type":413,"tag":444,"props":4777,"children":4778},{"__ignoreMap":401},[4779,4828,4835,4862,4888,4895,4924,4953,4982,4999,5006,5031],{"type":413,"tag":448,"props":4780,"children":4781},{"class":450,"line":451},[4782,4786,4790,4794,4798,4803,4807,4811,4816,4820,4824],{"type":413,"tag":448,"props":4783,"children":4784},{"style":949},[4785],{"type":418,"value":4296},{"type":413,"tag":448,"props":4787,"children":4788},{"style":949},[4789],{"type":418,"value":4675},{"type":413,"tag":448,"props":4791,"children":4792},{"style":461},[4793],{"type":418,"value":4306},{"type":413,"tag":448,"props":4795,"children":4796},{"style":461},[4797],{"type":418,"value":3943},{"type":413,"tag":448,"props":4799,"children":4800},{"style":949},[4801],{"type":418,"value":4802}," Git",{"type":413,"tag":448,"props":4804,"children":4805},{"style":461},[4806],{"type":418,"value":2041},{"type":413,"tag":448,"props":4808,"children":4809},{"style":461},[4810],{"type":418,"value":1183},{"type":413,"tag":448,"props":4812,"children":4813},{"style":467},[4814],{"type":418,"value":4815},"AzureReadyADORepository",{"type":413,"tag":448,"props":4817,"children":4818},{"style":461},[4819],{"type":418,"value":1183},{"type":413,"tag":448,"props":4821,"children":4822},{"style":461},[4823],{"type":418,"value":2059},{"type":413,"tag":448,"props":4825,"children":4826},{"style":461},[4827],{"type":418,"value":4341},{"type":413,"tag":448,"props":4829,"children":4830},{"class":450,"line":473},[4831],{"type":413,"tag":448,"props":4832,"children":4833},{"style":461},[4834],{"type":418,"value":1741},{"type":413,"tag":448,"props":4836,"children":4837},{"class":450,"line":488},[4838,4842,4846,4850,4854,4858],{"type":413,"tag":448,"props":4839,"children":4840},{"style":1029},[4841],{"type":418,"value":4713},{"type":413,"tag":448,"props":4843,"children":4844},{"style":461},[4845],{"type":418,"value":1037},{"type":413,"tag":448,"props":4847,"children":4848},{"style":1029},[4849],{"type":418,"value":4301},{"type":413,"tag":448,"props":4851,"children":4852},{"style":461},[4853],{"type":418,"value":898},{"type":413,"tag":448,"props":4855,"children":4856},{"style":1029},[4857],{"type":418,"value":4730},{"type":413,"tag":448,"props":4859,"children":4860},{"style":461},[4861],{"type":418,"value":4378},{"type":413,"tag":448,"props":4863,"children":4864},{"class":450,"line":501},[4865,4870,4874,4878,4883],{"type":413,"tag":448,"props":4866,"children":4867},{"style":1029},[4868],{"type":418,"value":4869},"    Initialization ",{"type":413,"tag":448,"props":4871,"children":4872},{"style":461},[4873],{"type":418,"value":1037},{"type":413,"tag":448,"props":4875,"children":4876},{"style":461},[4877],{"type":418,"value":3943},{"type":413,"tag":448,"props":4879,"children":4880},{"style":949},[4881],{"type":418,"value":4882}," GitInitializationArgs",{"type":413,"tag":448,"props":4884,"children":4885},{"style":461},[4886],{"type":418,"value":4887},"()\n",{"type":413,"tag":448,"props":4889,"children":4890},{"class":450,"line":511},[4891],{"type":413,"tag":448,"props":4892,"children":4893},{"style":461},[4894],{"type":418,"value":4402},{"type":413,"tag":448,"props":4896,"children":4897},{"class":450,"line":524},[4898,4903,4907,4911,4916,4920],{"type":413,"tag":448,"props":4899,"children":4900},{"style":1029},[4901],{"type":418,"value":4902},"        InitType ",{"type":413,"tag":448,"props":4904,"children":4905},{"style":461},[4906],{"type":418,"value":1037},{"type":413,"tag":448,"props":4908,"children":4909},{"style":461},[4910],{"type":418,"value":995},{"type":413,"tag":448,"props":4912,"children":4913},{"style":467},[4914],{"type":418,"value":4915},"Clean",{"type":413,"tag":448,"props":4917,"children":4918},{"style":461},[4919],{"type":418,"value":1183},{"type":413,"tag":448,"props":4921,"children":4922},{"style":461},[4923],{"type":418,"value":4378},{"type":413,"tag":448,"props":4925,"children":4926},{"class":450,"line":542},[4927,4932,4936,4940,4945,4949],{"type":413,"tag":448,"props":4928,"children":4929},{"style":1029},[4930],{"type":418,"value":4931},"        SourceType ",{"type":413,"tag":448,"props":4933,"children":4934},{"style":461},[4935],{"type":418,"value":1037},{"type":413,"tag":448,"props":4937,"children":4938},{"style":461},[4939],{"type":418,"value":995},{"type":413,"tag":448,"props":4941,"children":4942},{"style":467},[4943],{"type":418,"value":4944},"Git",{"type":413,"tag":448,"props":4946,"children":4947},{"style":461},[4948],{"type":418,"value":1183},{"type":413,"tag":448,"props":4950,"children":4951},{"style":461},[4952],{"type":418,"value":4378},{"type":413,"tag":448,"props":4954,"children":4955},{"class":450,"line":560},[4956,4961,4965,4969,4974,4978],{"type":413,"tag":448,"props":4957,"children":4958},{"style":1029},[4959],{"type":418,"value":4960},"        SourceUrl ",{"type":413,"tag":448,"props":4962,"children":4963},{"style":461},[4964],{"type":418,"value":1037},{"type":413,"tag":448,"props":4966,"children":4967},{"style":461},[4968],{"type":418,"value":995},{"type":413,"tag":448,"props":4970,"children":4971},{"style":467},[4972],{"type":418,"value":4973},"https://repo.com",{"type":413,"tag":448,"props":4975,"children":4976},{"style":461},[4977],{"type":418,"value":1183},{"type":413,"tag":448,"props":4979,"children":4980},{"style":461},[4981],{"type":418,"value":4378},{"type":413,"tag":448,"props":4983,"children":4984},{"class":450,"line":573},[4985,4990,4994],{"type":413,"tag":448,"props":4986,"children":4987},{"style":1029},[4988],{"type":418,"value":4989},"        ServiceConnectionId ",{"type":413,"tag":448,"props":4991,"children":4992},{"style":461},[4993],{"type":418,"value":1037},{"type":413,"tag":448,"props":4995,"children":4996},{"style":461},[4997],{"type":418,"value":4998}," \"\"\n",{"type":413,"tag":448,"props":5000,"children":5001},{"class":450,"line":586},[5002],{"type":413,"tag":448,"props":5003,"children":5004},{"style":461},[5005],{"type":418,"value":4629},{"type":413,"tag":448,"props":5007,"children":5008},{"class":450,"line":604},[5009,5014,5018,5022,5027],{"type":413,"tag":448,"props":5010,"children":5011},{"style":1029},[5012],{"type":418,"value":5013},"    DefaultBranch ",{"type":413,"tag":448,"props":5015,"children":5016},{"style":461},[5017],{"type":418,"value":1037},{"type":413,"tag":448,"props":5019,"children":5020},{"style":461},[5021],{"type":418,"value":995},{"type":413,"tag":448,"props":5023,"children":5024},{"style":467},[5025],{"type":418,"value":5026},"refs/heads/main",{"type":413,"tag":448,"props":5028,"children":5029},{"style":461},[5030],{"type":418,"value":1005},{"type":413,"tag":448,"props":5032,"children":5033},{"class":450,"line":617},[5034],{"type":413,"tag":448,"props":5035,"children":5036},{"style":461},[5037],{"type":418,"value":4637},{"type":413,"tag":841,"props":5039,"children":5040},{"icon":3815},[5041],{"type":413,"tag":414,"props":5042,"children":5043},{},[5044,5046,5052,5054,5060,5061,5067,5069,5076],{"type":418,"value":5045},"We should not have to set the ",{"type":413,"tag":444,"props":5047,"children":5049},{"className":5048},[],[5050],{"type":418,"value":5051},"SourceType",{"type":418,"value":5053},", ",{"type":413,"tag":444,"props":5055,"children":5057},{"className":5056},[],[5058],{"type":418,"value":5059},"SourceUrl",{"type":418,"value":3690},{"type":413,"tag":444,"props":5062,"children":5064},{"className":5063},[],[5065],{"type":418,"value":5066},"ServiceConnectionId",{"type":418,"value":5068}," properties as we are initializing a clean Git repository, not importing one, but it's a workaround because of this ",{"type":413,"tag":813,"props":5070,"children":5073},{"href":5071,"rel":5072},"https://github.com/pulumi/pulumi-azuredevops/issues/66",[817],[5074],{"type":418,"value":5075},"issue",{"type":418,"value":5077}," on the provider.",{"type":413,"tag":866,"props":5079,"children":5081},{"id":5080},"configure-the-arm-service-connection-in-azure-devops",[5082],{"type":418,"value":5083},"Configure the ARM Service Connection in Azure DevOps",{"type":413,"tag":414,"props":5085,"children":5086},{},[5087,5089,5096],{"type":418,"value":5088},"In the Azure DevOps provider, the Azure Resource Manager service connection is called a ",{"type":413,"tag":813,"props":5090,"children":5093},{"href":5091,"rel":5092},"https://www.pulumi.com/registry/packages/azuredevops/api-docs/serviceendpointazurerm/#workload-identity-federation-manual-azurerm-service-endpoint-subscription-scoped",[817],[5094],{"type":418,"value":5095},"ServiceEndpointAzureRM",{"type":418,"value":5097},". We can create such a resource like this:",{"type":413,"tag":437,"props":5099,"children":5101},{"className":4283,"code":5100,"language":326,"meta":401,"style":401},"var serviceConnection = new ServiceEndpointAzureRM(\"AzureServiceConnection\", new()\n{\n    ProjectId = project.Id,\n    ServiceEndpointName = \"azure-with-oidc\",\n    ServiceEndpointAuthenticationScheme = \"WorkloadIdentityFederation\",\n    AzurermSpnTenantid = tenantId,\n    AzurermSubscriptionId = subscriptionId,\n    AzurermSubscriptionName = subscriptionName,\n    Credentials = new ServiceEndpointAzureRMCredentialsArgs()\n    {\n        Serviceprincipalid = servicePrincipal.ApplicationId,\n    }\n});\n",[5102],{"type":413,"tag":444,"props":5103,"children":5104},{"__ignoreMap":401},[5105,5155,5162,5189,5218,5247,5268,5289,5310,5335,5342,5372,5380],{"type":413,"tag":448,"props":5106,"children":5107},{"class":450,"line":451},[5108,5112,5117,5121,5125,5130,5134,5138,5143,5147,5151],{"type":413,"tag":448,"props":5109,"children":5110},{"style":949},[5111],{"type":418,"value":4296},{"type":413,"tag":448,"props":5113,"children":5114},{"style":949},[5115],{"type":418,"value":5116}," serviceConnection",{"type":413,"tag":448,"props":5118,"children":5119},{"style":461},[5120],{"type":418,"value":4306},{"type":413,"tag":448,"props":5122,"children":5123},{"style":461},[5124],{"type":418,"value":3943},{"type":413,"tag":448,"props":5126,"children":5127},{"style":949},[5128],{"type":418,"value":5129}," ServiceEndpointAzureRM",{"type":413,"tag":448,"props":5131,"children":5132},{"style":461},[5133],{"type":418,"value":2041},{"type":413,"tag":448,"props":5135,"children":5136},{"style":461},[5137],{"type":418,"value":1183},{"type":413,"tag":448,"props":5139,"children":5140},{"style":467},[5141],{"type":418,"value":5142},"AzureServiceConnection",{"type":413,"tag":448,"props":5144,"children":5145},{"style":461},[5146],{"type":418,"value":1183},{"type":413,"tag":448,"props":5148,"children":5149},{"style":461},[5150],{"type":418,"value":2059},{"type":413,"tag":448,"props":5152,"children":5153},{"style":461},[5154],{"type":418,"value":4341},{"type":413,"tag":448,"props":5156,"children":5157},{"class":450,"line":473},[5158],{"type":413,"tag":448,"props":5159,"children":5160},{"style":461},[5161],{"type":418,"value":1741},{"type":413,"tag":448,"props":5163,"children":5164},{"class":450,"line":488},[5165,5169,5173,5177,5181,5185],{"type":413,"tag":448,"props":5166,"children":5167},{"style":1029},[5168],{"type":418,"value":4713},{"type":413,"tag":448,"props":5170,"children":5171},{"style":461},[5172],{"type":418,"value":1037},{"type":413,"tag":448,"props":5174,"children":5175},{"style":1029},[5176],{"type":418,"value":4301},{"type":413,"tag":448,"props":5178,"children":5179},{"style":461},[5180],{"type":418,"value":898},{"type":413,"tag":448,"props":5182,"children":5183},{"style":1029},[5184],{"type":418,"value":4730},{"type":413,"tag":448,"props":5186,"children":5187},{"style":461},[5188],{"type":418,"value":4378},{"type":413,"tag":448,"props":5190,"children":5191},{"class":450,"line":501},[5192,5197,5201,5205,5210,5214],{"type":413,"tag":448,"props":5193,"children":5194},{"style":1029},[5195],{"type":418,"value":5196},"    ServiceEndpointName ",{"type":413,"tag":448,"props":5198,"children":5199},{"style":461},[5200],{"type":418,"value":1037},{"type":413,"tag":448,"props":5202,"children":5203},{"style":461},[5204],{"type":418,"value":995},{"type":413,"tag":448,"props":5206,"children":5207},{"style":467},[5208],{"type":418,"value":5209},"azure-with-oidc",{"type":413,"tag":448,"props":5211,"children":5212},{"style":461},[5213],{"type":418,"value":1183},{"type":413,"tag":448,"props":5215,"children":5216},{"style":461},[5217],{"type":418,"value":4378},{"type":413,"tag":448,"props":5219,"children":5220},{"class":450,"line":511},[5221,5226,5230,5234,5239,5243],{"type":413,"tag":448,"props":5222,"children":5223},{"style":1029},[5224],{"type":418,"value":5225},"    ServiceEndpointAuthenticationScheme ",{"type":413,"tag":448,"props":5227,"children":5228},{"style":461},[5229],{"type":418,"value":1037},{"type":413,"tag":448,"props":5231,"children":5232},{"style":461},[5233],{"type":418,"value":995},{"type":413,"tag":448,"props":5235,"children":5236},{"style":467},[5237],{"type":418,"value":5238},"WorkloadIdentityFederation",{"type":413,"tag":448,"props":5240,"children":5241},{"style":461},[5242],{"type":418,"value":1183},{"type":413,"tag":448,"props":5244,"children":5245},{"style":461},[5246],{"type":418,"value":4378},{"type":413,"tag":448,"props":5248,"children":5249},{"class":450,"line":524},[5250,5255,5259,5264],{"type":413,"tag":448,"props":5251,"children":5252},{"style":1029},[5253],{"type":418,"value":5254},"    AzurermSpnTenantid ",{"type":413,"tag":448,"props":5256,"children":5257},{"style":461},[5258],{"type":418,"value":1037},{"type":413,"tag":448,"props":5260,"children":5261},{"style":1029},[5262],{"type":418,"value":5263}," tenantId",{"type":413,"tag":448,"props":5265,"children":5266},{"style":461},[5267],{"type":418,"value":4378},{"type":413,"tag":448,"props":5269,"children":5270},{"class":450,"line":542},[5271,5276,5280,5285],{"type":413,"tag":448,"props":5272,"children":5273},{"style":1029},[5274],{"type":418,"value":5275},"    AzurermSubscriptionId ",{"type":413,"tag":448,"props":5277,"children":5278},{"style":461},[5279],{"type":418,"value":1037},{"type":413,"tag":448,"props":5281,"children":5282},{"style":1029},[5283],{"type":418,"value":5284}," subscriptionId",{"type":413,"tag":448,"props":5286,"children":5287},{"style":461},[5288],{"type":418,"value":4378},{"type":413,"tag":448,"props":5290,"children":5291},{"class":450,"line":560},[5292,5297,5301,5306],{"type":413,"tag":448,"props":5293,"children":5294},{"style":1029},[5295],{"type":418,"value":5296},"    AzurermSubscriptionName ",{"type":413,"tag":448,"props":5298,"children":5299},{"style":461},[5300],{"type":418,"value":1037},{"type":413,"tag":448,"props":5302,"children":5303},{"style":1029},[5304],{"type":418,"value":5305}," subscriptionName",{"type":413,"tag":448,"props":5307,"children":5308},{"style":461},[5309],{"type":418,"value":4378},{"type":413,"tag":448,"props":5311,"children":5312},{"class":450,"line":573},[5313,5318,5322,5326,5331],{"type":413,"tag":448,"props":5314,"children":5315},{"style":1029},[5316],{"type":418,"value":5317},"    Credentials ",{"type":413,"tag":448,"props":5319,"children":5320},{"style":461},[5321],{"type":418,"value":1037},{"type":413,"tag":448,"props":5323,"children":5324},{"style":461},[5325],{"type":418,"value":3943},{"type":413,"tag":448,"props":5327,"children":5328},{"style":949},[5329],{"type":418,"value":5330}," ServiceEndpointAzureRMCredentialsArgs",{"type":413,"tag":448,"props":5332,"children":5333},{"style":461},[5334],{"type":418,"value":4887},{"type":413,"tag":448,"props":5336,"children":5337},{"class":450,"line":586},[5338],{"type":413,"tag":448,"props":5339,"children":5340},{"style":461},[5341],{"type":418,"value":4402},{"type":413,"tag":448,"props":5343,"children":5344},{"class":450,"line":604},[5345,5350,5354,5359,5363,5368],{"type":413,"tag":448,"props":5346,"children":5347},{"style":1029},[5348],{"type":418,"value":5349},"        Serviceprincipalid ",{"type":413,"tag":448,"props":5351,"children":5352},{"style":461},[5353],{"type":418,"value":1037},{"type":413,"tag":448,"props":5355,"children":5356},{"style":1029},[5357],{"type":418,"value":5358}," servicePrincipal",{"type":413,"tag":448,"props":5360,"children":5361},{"style":461},[5362],{"type":418,"value":898},{"type":413,"tag":448,"props":5364,"children":5365},{"style":1029},[5366],{"type":418,"value":5367},"ApplicationId",{"type":413,"tag":448,"props":5369,"children":5370},{"style":461},[5371],{"type":418,"value":4378},{"type":413,"tag":448,"props":5373,"children":5374},{"class":450,"line":617},[5375],{"type":413,"tag":448,"props":5376,"children":5377},{"style":461},[5378],{"type":418,"value":5379},"    }\n",{"type":413,"tag":448,"props":5381,"children":5382},{"class":450,"line":650},[5383],{"type":413,"tag":448,"props":5384,"children":5385},{"style":461},[5386],{"type":418,"value":4637},{"type":413,"tag":414,"props":5388,"children":5389},{},[5390,5392,5398],{"type":418,"value":5391},"Do not worry about the service principal, we will see in the next section how to create it. The tenant and the subscription identifiers can be retrieved from the current configuration of the Azure Native provider (using the ",{"type":413,"tag":444,"props":5393,"children":5395},{"className":5394},[],[5396],{"type":418,"value":5397},"GetClientConfig.Invoke",{"type":418,"value":5399}," function):",{"type":413,"tag":437,"props":5401,"children":5403},{"className":4283,"code":5402,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar tenantId = azureConfig.Apply(c => c.tenantId);\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\n",[5404],{"type":413,"tag":444,"props":5405,"children":5406},{"__ignoreMap":401},[5407,5441,5501],{"type":413,"tag":448,"props":5408,"children":5409},{"class":450,"line":451},[5410,5414,5419,5423,5428,5432,5436],{"type":413,"tag":448,"props":5411,"children":5412},{"style":949},[5413],{"type":418,"value":4296},{"type":413,"tag":448,"props":5415,"children":5416},{"style":949},[5417],{"type":418,"value":5418}," azureConfig",{"type":413,"tag":448,"props":5420,"children":5421},{"style":461},[5422],{"type":418,"value":4306},{"type":413,"tag":448,"props":5424,"children":5425},{"style":1029},[5426],{"type":418,"value":5427}," GetClientConfig",{"type":413,"tag":448,"props":5429,"children":5430},{"style":461},[5431],{"type":418,"value":898},{"type":413,"tag":448,"props":5433,"children":5434},{"style":2000},[5435],{"type":418,"value":4693},{"type":413,"tag":448,"props":5437,"children":5438},{"style":461},[5439],{"type":418,"value":5440},"();\n",{"type":413,"tag":448,"props":5442,"children":5443},{"class":450,"line":473},[5444,5448,5452,5456,5460,5464,5469,5473,5478,5483,5488,5492,5496],{"type":413,"tag":448,"props":5445,"children":5446},{"style":949},[5447],{"type":418,"value":4296},{"type":413,"tag":448,"props":5449,"children":5450},{"style":949},[5451],{"type":418,"value":5263},{"type":413,"tag":448,"props":5453,"children":5454},{"style":461},[5455],{"type":418,"value":4306},{"type":413,"tag":448,"props":5457,"children":5458},{"style":1029},[5459],{"type":418,"value":5418},{"type":413,"tag":448,"props":5461,"children":5462},{"style":461},[5463],{"type":418,"value":898},{"type":413,"tag":448,"props":5465,"children":5466},{"style":2000},[5467],{"type":418,"value":5468},"Apply",{"type":413,"tag":448,"props":5470,"children":5471},{"style":461},[5472],{"type":418,"value":2041},{"type":413,"tag":448,"props":5474,"children":5475},{"style":949},[5476],{"type":418,"value":5477},"c",{"type":413,"tag":448,"props":5479,"children":5480},{"style":461},[5481],{"type":418,"value":5482}," =>",{"type":413,"tag":448,"props":5484,"children":5485},{"style":1029},[5486],{"type":418,"value":5487}," c",{"type":413,"tag":448,"props":5489,"children":5490},{"style":461},[5491],{"type":418,"value":898},{"type":413,"tag":448,"props":5493,"children":5494},{"style":1029},[5495],{"type":418,"value":1315},{"type":413,"tag":448,"props":5497,"children":5498},{"style":461},[5499],{"type":418,"value":5500},");\n",{"type":413,"tag":448,"props":5502,"children":5503},{"class":450,"line":488},[5504,5508,5512,5516,5520,5524,5528,5532,5536,5540,5544,5548,5553],{"type":413,"tag":448,"props":5505,"children":5506},{"style":949},[5507],{"type":418,"value":4296},{"type":413,"tag":448,"props":5509,"children":5510},{"style":949},[5511],{"type":418,"value":5284},{"type":413,"tag":448,"props":5513,"children":5514},{"style":461},[5515],{"type":418,"value":4306},{"type":413,"tag":448,"props":5517,"children":5518},{"style":1029},[5519],{"type":418,"value":5418},{"type":413,"tag":448,"props":5521,"children":5522},{"style":461},[5523],{"type":418,"value":898},{"type":413,"tag":448,"props":5525,"children":5526},{"style":2000},[5527],{"type":418,"value":5468},{"type":413,"tag":448,"props":5529,"children":5530},{"style":461},[5531],{"type":418,"value":2041},{"type":413,"tag":448,"props":5533,"children":5534},{"style":949},[5535],{"type":418,"value":5477},{"type":413,"tag":448,"props":5537,"children":5538},{"style":461},[5539],{"type":418,"value":5482},{"type":413,"tag":448,"props":5541,"children":5542},{"style":1029},[5543],{"type":418,"value":5487},{"type":413,"tag":448,"props":5545,"children":5546},{"style":461},[5547],{"type":418,"value":898},{"type":413,"tag":448,"props":5549,"children":5550},{"style":1029},[5551],{"type":418,"value":5552},"SubscriptionId",{"type":413,"tag":448,"props":5554,"children":5555},{"style":461},[5556],{"type":418,"value":5500},{"type":413,"tag":414,"props":5558,"children":5559},{},[5560],{"type":418,"value":5561},"For the subscription name, it's more complicated as we don't have it, and no easy way to retrieve it. To be frank, I think having to provide the subscription name while we already provide the subscription identifier is completely useless but that's how the Azure DevOps provider works.",{"type":413,"tag":414,"props":5563,"children":5564},{},[5565,5567,5574,5576,5582],{"type":418,"value":5566},"The Azure Classic provider offers a ",{"type":413,"tag":813,"props":5568,"children":5571},{"href":5569,"rel":5570},"https://www.pulumi.com/registry/packages/azure/api-docs/core/getsubscription/#azure-core-getsubscription",[817],[5572],{"type":418,"value":5573},"function",{"type":418,"value":5575}," to get a subscription by its identifier but it's not available in the Azure Native provider. I don't want to add the Azure Classic provider to my project solely for this purpose. However, it's not a big deal as it allows us to experience one of the advantages of using Pulumi: when something is not available you can just implement it or use any library that can help you, such as the ",{"type":413,"tag":813,"props":5577,"children":5580},{"href":5578,"rel":5579},"https://www.nuget.org/packages/Azure.ResourceManager",[817],[5581],{"type":418,"value":302},{"type":418,"value":5583}," in this case.",{"type":413,"tag":437,"props":5585,"children":5587},{"className":4283,"code":5586,"language":326,"meta":401,"style":401},"var subscriptionName = subscriptionId.Apply(s =>\n{\n    var armClient = new ArmClient(new DefaultAzureCredential());\n    var subscription = armClient.GetSubscriptionResource(new ResourceIdentifier($\"/subscriptions/{s}\")).Get();\n    return subscription.Value.Data.DisplayName;\n});\n",[5588],{"type":413,"tag":444,"props":5589,"children":5590},{"__ignoreMap":401},[5591,5632,5639,5680,5759,5803],{"type":413,"tag":448,"props":5592,"children":5593},{"class":450,"line":451},[5594,5598,5602,5606,5610,5614,5618,5622,5627],{"type":413,"tag":448,"props":5595,"children":5596},{"style":949},[5597],{"type":418,"value":4296},{"type":413,"tag":448,"props":5599,"children":5600},{"style":949},[5601],{"type":418,"value":5305},{"type":413,"tag":448,"props":5603,"children":5604},{"style":461},[5605],{"type":418,"value":4306},{"type":413,"tag":448,"props":5607,"children":5608},{"style":1029},[5609],{"type":418,"value":5284},{"type":413,"tag":448,"props":5611,"children":5612},{"style":461},[5613],{"type":418,"value":898},{"type":413,"tag":448,"props":5615,"children":5616},{"style":2000},[5617],{"type":418,"value":5468},{"type":413,"tag":448,"props":5619,"children":5620},{"style":461},[5621],{"type":418,"value":2041},{"type":413,"tag":448,"props":5623,"children":5624},{"style":949},[5625],{"type":418,"value":5626},"s",{"type":413,"tag":448,"props":5628,"children":5629},{"style":461},[5630],{"type":418,"value":5631}," =>\n",{"type":413,"tag":448,"props":5633,"children":5634},{"class":450,"line":473},[5635],{"type":413,"tag":448,"props":5636,"children":5637},{"style":461},[5638],{"type":418,"value":1741},{"type":413,"tag":448,"props":5640,"children":5641},{"class":450,"line":488},[5642,5647,5652,5656,5660,5665,5670,5675],{"type":413,"tag":448,"props":5643,"children":5644},{"style":949},[5645],{"type":418,"value":5646},"    var",{"type":413,"tag":448,"props":5648,"children":5649},{"style":949},[5650],{"type":418,"value":5651}," armClient",{"type":413,"tag":448,"props":5653,"children":5654},{"style":461},[5655],{"type":418,"value":4306},{"type":413,"tag":448,"props":5657,"children":5658},{"style":461},[5659],{"type":418,"value":3943},{"type":413,"tag":448,"props":5661,"children":5662},{"style":949},[5663],{"type":418,"value":5664}," ArmClient",{"type":413,"tag":448,"props":5666,"children":5667},{"style":461},[5668],{"type":418,"value":5669},"(new",{"type":413,"tag":448,"props":5671,"children":5672},{"style":949},[5673],{"type":418,"value":5674}," DefaultAzureCredential",{"type":413,"tag":448,"props":5676,"children":5677},{"style":461},[5678],{"type":418,"value":5679},"());\n",{"type":413,"tag":448,"props":5681,"children":5682},{"class":450,"line":501},[5683,5687,5692,5696,5700,5704,5709,5713,5718,5722,5727,5732,5737,5741,5745,5750,5755],{"type":413,"tag":448,"props":5684,"children":5685},{"style":949},[5686],{"type":418,"value":5646},{"type":413,"tag":448,"props":5688,"children":5689},{"style":949},[5690],{"type":418,"value":5691}," subscription",{"type":413,"tag":448,"props":5693,"children":5694},{"style":461},[5695],{"type":418,"value":4306},{"type":413,"tag":448,"props":5697,"children":5698},{"style":1029},[5699],{"type":418,"value":5651},{"type":413,"tag":448,"props":5701,"children":5702},{"style":461},[5703],{"type":418,"value":898},{"type":413,"tag":448,"props":5705,"children":5706},{"style":2000},[5707],{"type":418,"value":5708},"GetSubscriptionResource",{"type":413,"tag":448,"props":5710,"children":5711},{"style":461},[5712],{"type":418,"value":5669},{"type":413,"tag":448,"props":5714,"children":5715},{"style":949},[5716],{"type":418,"value":5717}," ResourceIdentifier",{"type":413,"tag":448,"props":5719,"children":5720},{"style":461},[5721],{"type":418,"value":2041},{"type":413,"tag":448,"props":5723,"children":5724},{"style":461},[5725],{"type":418,"value":5726},"$\"",{"type":413,"tag":448,"props":5728,"children":5729},{"style":467},[5730],{"type":418,"value":5731},"/subscriptions/",{"type":413,"tag":448,"props":5733,"children":5734},{"style":461},[5735],{"type":418,"value":5736},"{",{"type":413,"tag":448,"props":5738,"children":5739},{"style":1029},[5740],{"type":418,"value":5626},{"type":413,"tag":448,"props":5742,"children":5743},{"style":461},[5744],{"type":418,"value":1461},{"type":413,"tag":448,"props":5746,"children":5747},{"style":461},[5748],{"type":418,"value":5749},")).",{"type":413,"tag":448,"props":5751,"children":5752},{"style":2000},[5753],{"type":418,"value":5754},"Get",{"type":413,"tag":448,"props":5756,"children":5757},{"style":461},[5758],{"type":418,"value":5440},{"type":413,"tag":448,"props":5760,"children":5761},{"class":450,"line":511},[5762,5767,5771,5775,5780,5784,5789,5793,5798],{"type":413,"tag":448,"props":5763,"children":5764},{"style":785},[5765],{"type":418,"value":5766},"    return",{"type":413,"tag":448,"props":5768,"children":5769},{"style":1029},[5770],{"type":418,"value":5691},{"type":413,"tag":448,"props":5772,"children":5773},{"style":461},[5774],{"type":418,"value":898},{"type":413,"tag":448,"props":5776,"children":5777},{"style":1029},[5778],{"type":418,"value":5779},"Value",{"type":413,"tag":448,"props":5781,"children":5782},{"style":461},[5783],{"type":418,"value":898},{"type":413,"tag":448,"props":5785,"children":5786},{"style":1029},[5787],{"type":418,"value":5788},"Data",{"type":413,"tag":448,"props":5790,"children":5791},{"style":461},[5792],{"type":418,"value":898},{"type":413,"tag":448,"props":5794,"children":5795},{"style":1029},[5796],{"type":418,"value":5797},"DisplayName",{"type":413,"tag":448,"props":5799,"children":5800},{"style":461},[5801],{"type":418,"value":5802},";\n",{"type":413,"tag":448,"props":5804,"children":5805},{"class":450,"line":524},[5806],{"type":413,"tag":448,"props":5807,"children":5808},{"style":461},[5809],{"type":418,"value":4637},{"type":413,"tag":866,"props":5811,"children":5813},{"id":5812},"set-up-the-necessary-microsoft-entra-id-resources",[5814],{"type":418,"value":5815},"Set up the necessary Microsoft Entra ID resources",{"type":413,"tag":414,"props":5817,"children":5818},{},[5819],{"type":418,"value":5820},"We need to set up the following resources in Microsoft Entra ID:",{"type":413,"tag":3766,"props":5822,"children":5823},{},[5824,5829,5834],{"type":413,"tag":2159,"props":5825,"children":5826},{},[5827],{"type":418,"value":5828},"an Application that represents the Azure DevOps service connection identity",{"type":413,"tag":2159,"props":5830,"children":5831},{},[5832],{"type":418,"value":5833},"a Service Principal (related to the application above) that has the contributor role on the Azure subscription",{"type":413,"tag":2159,"props":5835,"children":5836},{},[5837],{"type":418,"value":5838},"credentials for the CI/CD pipeline to authenticate to Azure on behalf of this Microsoft Entra ID application",{"type":413,"tag":414,"props":5840,"children":5841},{},[5842],{"type":418,"value":5843},"Let's take care of the first 2 points:",{"type":413,"tag":437,"props":5845,"children":5847},{"className":4283,"code":5846,"language":326,"meta":401,"style":401},"var azureConfig = GetClientConfig.Invoke();\nvar aadApplication = new Application(\"ADOAzureReadyApp\", new()\n{\n    DisplayName = \"ADO Azure Ready App\"\n});\nvar servicePrincipal  = new ServicePrincipal(\"AzureReadyServicePrincipal\", new()\n{\n    ApplicationId = aadApplication.ApplicationId,\n});\n\nvar subscriptionId = azureConfig.Apply(c => c.SubscriptionId);\nnew RoleAssignment(\"contributor\", new()\n{\n    PrincipalId= servicePrincipal.Id,\n    PrincipalType= PrincipalType.ServicePrincipal,\n    RoleDefinitionId = AzureBuiltInRoles.Contributor,\n    Scope = Output.Format($\"/subscriptions/{subscriptionId}\")\n});\n",[5848],{"type":413,"tag":444,"props":5849,"children":5850},{"__ignoreMap":401},[5851,5882,5932,5939,5964,5971,6021,6028,6056,6063,6070,6125,6164,6171,6199,6229,6259,6313],{"type":413,"tag":448,"props":5852,"children":5853},{"class":450,"line":451},[5854,5858,5862,5866,5870,5874,5878],{"type":413,"tag":448,"props":5855,"children":5856},{"style":949},[5857],{"type":418,"value":4296},{"type":413,"tag":448,"props":5859,"children":5860},{"style":949},[5861],{"type":418,"value":5418},{"type":413,"tag":448,"props":5863,"children":5864},{"style":461},[5865],{"type":418,"value":4306},{"type":413,"tag":448,"props":5867,"children":5868},{"style":1029},[5869],{"type":418,"value":5427},{"type":413,"tag":448,"props":5871,"children":5872},{"style":461},[5873],{"type":418,"value":898},{"type":413,"tag":448,"props":5875,"children":5876},{"style":2000},[5877],{"type":418,"value":4693},{"type":413,"tag":448,"props":5879,"children":5880},{"style":461},[5881],{"type":418,"value":5440},{"type":413,"tag":448,"props":5883,"children":5884},{"class":450,"line":473},[5885,5889,5894,5898,5902,5907,5911,5915,5920,5924,5928],{"type":413,"tag":448,"props":5886,"children":5887},{"style":949},[5888],{"type":418,"value":4296},{"type":413,"tag":448,"props":5890,"children":5891},{"style":949},[5892],{"type":418,"value":5893}," aadApplication",{"type":413,"tag":448,"props":5895,"children":5896},{"style":461},[5897],{"type":418,"value":4306},{"type":413,"tag":448,"props":5899,"children":5900},{"style":461},[5901],{"type":418,"value":3943},{"type":413,"tag":448,"props":5903,"children":5904},{"style":949},[5905],{"type":418,"value":5906}," Application",{"type":413,"tag":448,"props":5908,"children":5909},{"style":461},[5910],{"type":418,"value":2041},{"type":413,"tag":448,"props":5912,"children":5913},{"style":461},[5914],{"type":418,"value":1183},{"type":413,"tag":448,"props":5916,"children":5917},{"style":467},[5918],{"type":418,"value":5919},"ADOAzureReadyApp",{"type":413,"tag":448,"props":5921,"children":5922},{"style":461},[5923],{"type":418,"value":1183},{"type":413,"tag":448,"props":5925,"children":5926},{"style":461},[5927],{"type":418,"value":2059},{"type":413,"tag":448,"props":5929,"children":5930},{"style":461},[5931],{"type":418,"value":4341},{"type":413,"tag":448,"props":5933,"children":5934},{"class":450,"line":488},[5935],{"type":413,"tag":448,"props":5936,"children":5937},{"style":461},[5938],{"type":418,"value":1741},{"type":413,"tag":448,"props":5940,"children":5941},{"class":450,"line":501},[5942,5947,5951,5955,5960],{"type":413,"tag":448,"props":5943,"children":5944},{"style":1029},[5945],{"type":418,"value":5946},"    DisplayName ",{"type":413,"tag":448,"props":5948,"children":5949},{"style":461},[5950],{"type":418,"value":1037},{"type":413,"tag":448,"props":5952,"children":5953},{"style":461},[5954],{"type":418,"value":995},{"type":413,"tag":448,"props":5956,"children":5957},{"style":467},[5958],{"type":418,"value":5959},"ADO Azure Ready App",{"type":413,"tag":448,"props":5961,"children":5962},{"style":461},[5963],{"type":418,"value":1005},{"type":413,"tag":448,"props":5965,"children":5966},{"class":450,"line":511},[5967],{"type":413,"tag":448,"props":5968,"children":5969},{"style":461},[5970],{"type":418,"value":4637},{"type":413,"tag":448,"props":5972,"children":5973},{"class":450,"line":524},[5974,5978,5982,5987,5991,5996,6000,6004,6009,6013,6017],{"type":413,"tag":448,"props":5975,"children":5976},{"style":949},[5977],{"type":418,"value":4296},{"type":413,"tag":448,"props":5979,"children":5980},{"style":949},[5981],{"type":418,"value":5358},{"type":413,"tag":448,"props":5983,"children":5984},{"style":461},[5985],{"type":418,"value":5986},"  =",{"type":413,"tag":448,"props":5988,"children":5989},{"style":461},[5990],{"type":418,"value":3943},{"type":413,"tag":448,"props":5992,"children":5993},{"style":949},[5994],{"type":418,"value":5995}," ServicePrincipal",{"type":413,"tag":448,"props":5997,"children":5998},{"style":461},[5999],{"type":418,"value":2041},{"type":413,"tag":448,"props":6001,"children":6002},{"style":461},[6003],{"type":418,"value":1183},{"type":413,"tag":448,"props":6005,"children":6006},{"style":467},[6007],{"type":418,"value":6008},"AzureReadyServicePrincipal",{"type":413,"tag":448,"props":6010,"children":6011},{"style":461},[6012],{"type":418,"value":1183},{"type":413,"tag":448,"props":6014,"children":6015},{"style":461},[6016],{"type":418,"value":2059},{"type":413,"tag":448,"props":6018,"children":6019},{"style":461},[6020],{"type":418,"value":4341},{"type":413,"tag":448,"props":6022,"children":6023},{"class":450,"line":542},[6024],{"type":413,"tag":448,"props":6025,"children":6026},{"style":461},[6027],{"type":418,"value":1741},{"type":413,"tag":448,"props":6029,"children":6030},{"class":450,"line":560},[6031,6036,6040,6044,6048,6052],{"type":413,"tag":448,"props":6032,"children":6033},{"style":1029},[6034],{"type":418,"value":6035},"    ApplicationId ",{"type":413,"tag":448,"props":6037,"children":6038},{"style":461},[6039],{"type":418,"value":1037},{"type":413,"tag":448,"props":6041,"children":6042},{"style":1029},[6043],{"type":418,"value":5893},{"type":413,"tag":448,"props":6045,"children":6046},{"style":461},[6047],{"type":418,"value":898},{"type":413,"tag":448,"props":6049,"children":6050},{"style":1029},[6051],{"type":418,"value":5367},{"type":413,"tag":448,"props":6053,"children":6054},{"style":461},[6055],{"type":418,"value":4378},{"type":413,"tag":448,"props":6057,"children":6058},{"class":450,"line":573},[6059],{"type":413,"tag":448,"props":6060,"children":6061},{"style":461},[6062],{"type":418,"value":4637},{"type":413,"tag":448,"props":6064,"children":6065},{"class":450,"line":586},[6066],{"type":413,"tag":448,"props":6067,"children":6068},{"emptyLinePlaceholder":505},[6069],{"type":418,"value":508},{"type":413,"tag":448,"props":6071,"children":6072},{"class":450,"line":604},[6073,6077,6081,6085,6089,6093,6097,6101,6105,6109,6113,6117,6121],{"type":413,"tag":448,"props":6074,"children":6075},{"style":949},[6076],{"type":418,"value":4296},{"type":413,"tag":448,"props":6078,"children":6079},{"style":949},[6080],{"type":418,"value":5284},{"type":413,"tag":448,"props":6082,"children":6083},{"style":461},[6084],{"type":418,"value":4306},{"type":413,"tag":448,"props":6086,"children":6087},{"style":1029},[6088],{"type":418,"value":5418},{"type":413,"tag":448,"props":6090,"children":6091},{"style":461},[6092],{"type":418,"value":898},{"type":413,"tag":448,"props":6094,"children":6095},{"style":2000},[6096],{"type":418,"value":5468},{"type":413,"tag":448,"props":6098,"children":6099},{"style":461},[6100],{"type":418,"value":2041},{"type":413,"tag":448,"props":6102,"children":6103},{"style":949},[6104],{"type":418,"value":5477},{"type":413,"tag":448,"props":6106,"children":6107},{"style":461},[6108],{"type":418,"value":5482},{"type":413,"tag":448,"props":6110,"children":6111},{"style":1029},[6112],{"type":418,"value":5487},{"type":413,"tag":448,"props":6114,"children":6115},{"style":461},[6116],{"type":418,"value":898},{"type":413,"tag":448,"props":6118,"children":6119},{"style":1029},[6120],{"type":418,"value":5552},{"type":413,"tag":448,"props":6122,"children":6123},{"style":461},[6124],{"type":418,"value":5500},{"type":413,"tag":448,"props":6126,"children":6127},{"class":450,"line":617},[6128,6134,6139,6143,6147,6152,6156,6160],{"type":413,"tag":448,"props":6129,"children":6131},{"style":6130},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[6132],{"type":418,"value":6133},"new",{"type":413,"tag":448,"props":6135,"children":6136},{"style":2000},[6137],{"type":418,"value":6138}," RoleAssignment",{"type":413,"tag":448,"props":6140,"children":6141},{"style":461},[6142],{"type":418,"value":2041},{"type":413,"tag":448,"props":6144,"children":6145},{"style":461},[6146],{"type":418,"value":1183},{"type":413,"tag":448,"props":6148,"children":6149},{"style":467},[6150],{"type":418,"value":6151},"contributor",{"type":413,"tag":448,"props":6153,"children":6154},{"style":461},[6155],{"type":418,"value":1183},{"type":413,"tag":448,"props":6157,"children":6158},{"style":461},[6159],{"type":418,"value":2059},{"type":413,"tag":448,"props":6161,"children":6162},{"style":461},[6163],{"type":418,"value":4341},{"type":413,"tag":448,"props":6165,"children":6166},{"class":450,"line":650},[6167],{"type":413,"tag":448,"props":6168,"children":6169},{"style":461},[6170],{"type":418,"value":1741},{"type":413,"tag":448,"props":6172,"children":6173},{"class":450,"line":668},[6174,6179,6183,6187,6191,6195],{"type":413,"tag":448,"props":6175,"children":6176},{"style":1029},[6177],{"type":418,"value":6178},"    PrincipalId",{"type":413,"tag":448,"props":6180,"children":6181},{"style":461},[6182],{"type":418,"value":1037},{"type":413,"tag":448,"props":6184,"children":6185},{"style":1029},[6186],{"type":418,"value":5358},{"type":413,"tag":448,"props":6188,"children":6189},{"style":461},[6190],{"type":418,"value":898},{"type":413,"tag":448,"props":6192,"children":6193},{"style":1029},[6194],{"type":418,"value":4730},{"type":413,"tag":448,"props":6196,"children":6197},{"style":461},[6198],{"type":418,"value":4378},{"type":413,"tag":448,"props":6200,"children":6201},{"class":450,"line":681},[6202,6207,6211,6216,6220,6225],{"type":413,"tag":448,"props":6203,"children":6204},{"style":1029},[6205],{"type":418,"value":6206},"    PrincipalType",{"type":413,"tag":448,"props":6208,"children":6209},{"style":461},[6210],{"type":418,"value":1037},{"type":413,"tag":448,"props":6212,"children":6213},{"style":1029},[6214],{"type":418,"value":6215}," PrincipalType",{"type":413,"tag":448,"props":6217,"children":6218},{"style":461},[6219],{"type":418,"value":898},{"type":413,"tag":448,"props":6221,"children":6222},{"style":1029},[6223],{"type":418,"value":6224},"ServicePrincipal",{"type":413,"tag":448,"props":6226,"children":6227},{"style":461},[6228],{"type":418,"value":4378},{"type":413,"tag":448,"props":6230,"children":6231},{"class":450,"line":699},[6232,6237,6241,6246,6250,6255],{"type":413,"tag":448,"props":6233,"children":6234},{"style":1029},[6235],{"type":418,"value":6236},"    RoleDefinitionId ",{"type":413,"tag":448,"props":6238,"children":6239},{"style":461},[6240],{"type":418,"value":1037},{"type":413,"tag":448,"props":6242,"children":6243},{"style":1029},[6244],{"type":418,"value":6245}," AzureBuiltInRoles",{"type":413,"tag":448,"props":6247,"children":6248},{"style":461},[6249],{"type":418,"value":898},{"type":413,"tag":448,"props":6251,"children":6252},{"style":1029},[6253],{"type":418,"value":6254},"Contributor",{"type":413,"tag":448,"props":6256,"children":6257},{"style":461},[6258],{"type":418,"value":4378},{"type":413,"tag":448,"props":6260,"children":6261},{"class":450,"line":717},[6262,6267,6271,6276,6280,6285,6289,6293,6297,6301,6305,6309],{"type":413,"tag":448,"props":6263,"children":6264},{"style":1029},[6265],{"type":418,"value":6266},"    Scope ",{"type":413,"tag":448,"props":6268,"children":6269},{"style":461},[6270],{"type":418,"value":1037},{"type":413,"tag":448,"props":6272,"children":6273},{"style":1029},[6274],{"type":418,"value":6275}," Output",{"type":413,"tag":448,"props":6277,"children":6278},{"style":461},[6279],{"type":418,"value":898},{"type":413,"tag":448,"props":6281,"children":6282},{"style":2000},[6283],{"type":418,"value":6284},"Format",{"type":413,"tag":448,"props":6286,"children":6287},{"style":461},[6288],{"type":418,"value":2041},{"type":413,"tag":448,"props":6290,"children":6291},{"style":461},[6292],{"type":418,"value":5726},{"type":413,"tag":448,"props":6294,"children":6295},{"style":467},[6296],{"type":418,"value":5731},{"type":413,"tag":448,"props":6298,"children":6299},{"style":461},[6300],{"type":418,"value":5736},{"type":413,"tag":448,"props":6302,"children":6303},{"style":1029},[6304],{"type":418,"value":1258},{"type":413,"tag":448,"props":6306,"children":6307},{"style":461},[6308],{"type":418,"value":1461},{"type":413,"tag":448,"props":6310,"children":6311},{"style":461},[6312],{"type":418,"value":1197},{"type":413,"tag":448,"props":6314,"children":6315},{"class":450,"line":735},[6316],{"type":413,"tag":448,"props":6317,"children":6318},{"style":461},[6319],{"type":418,"value":4637},{"type":413,"tag":841,"props":6321,"children":6322},{"icon":3815},[6323],{"type":413,"tag":414,"props":6324,"children":6325},{},[6326,6328],{"type":418,"value":6327},"It's worth mentioning that using an Application and its associated Service Principal is not the only way to proceed, we could have created instead a ",{"type":413,"tag":813,"props":6329,"children":6332},{"href":6330,"rel":6331},"https://www.pulumi.com/registry/packages/azure-native/api-docs/managedidentity/userassignedidentity/",[817],[6333],{"type":418,"value":6334},"User Assigned Identity",{"type":413,"tag":414,"props":6336,"children":6337},{},[6338],{"type":418,"value":6339},"Now that everything is created, we can create the Federated identity credentials:",{"type":413,"tag":437,"props":6341,"children":6343},{"className":4283,"code":6342,"language":326,"meta":401,"style":401},"new ApplicationFederatedIdentityCredential(\"ADOAzureReadyAppFederatedIdentityCredential\", new() \n{\n    ApplicationObjectId = aadApplication.ObjectId,\n    DisplayName = \"AzureReadyDeploys\",\n    Description = \"Deployments for azure-ready-repository\",\n    Audiences = new(){\"api://AzureADTokenExchange\" },\n    Issuer = serviceConnection.WorkloadIdentityFederationIssuer,\n    Subject = Output.Format($\"sc://{organisationName}/{project.Name}/{serviceConnection.ServiceEndpointName}\")\n});\n",[6344],{"type":413,"tag":444,"props":6345,"children":6346},{"__ignoreMap":401},[6347,6389,6396,6425,6453,6481,6515,6544,6650],{"type":413,"tag":448,"props":6348,"children":6349},{"class":450,"line":451},[6350,6354,6359,6363,6367,6372,6376,6380,6385],{"type":413,"tag":448,"props":6351,"children":6352},{"style":6130},[6353],{"type":418,"value":6133},{"type":413,"tag":448,"props":6355,"children":6356},{"style":2000},[6357],{"type":418,"value":6358}," ApplicationFederatedIdentityCredential",{"type":413,"tag":448,"props":6360,"children":6361},{"style":461},[6362],{"type":418,"value":2041},{"type":413,"tag":448,"props":6364,"children":6365},{"style":461},[6366],{"type":418,"value":1183},{"type":413,"tag":448,"props":6368,"children":6369},{"style":467},[6370],{"type":418,"value":6371},"ADOAzureReadyAppFederatedIdentityCredential",{"type":413,"tag":448,"props":6373,"children":6374},{"style":461},[6375],{"type":418,"value":1183},{"type":413,"tag":448,"props":6377,"children":6378},{"style":461},[6379],{"type":418,"value":2059},{"type":413,"tag":448,"props":6381,"children":6382},{"style":461},[6383],{"type":418,"value":6384}," new()",{"type":413,"tag":448,"props":6386,"children":6387},{"style":1029},[6388],{"type":418,"value":2605},{"type":413,"tag":448,"props":6390,"children":6391},{"class":450,"line":473},[6392],{"type":413,"tag":448,"props":6393,"children":6394},{"style":461},[6395],{"type":418,"value":1741},{"type":413,"tag":448,"props":6397,"children":6398},{"class":450,"line":488},[6399,6404,6408,6412,6416,6421],{"type":413,"tag":448,"props":6400,"children":6401},{"style":1029},[6402],{"type":418,"value":6403},"    ApplicationObjectId ",{"type":413,"tag":448,"props":6405,"children":6406},{"style":461},[6407],{"type":418,"value":1037},{"type":413,"tag":448,"props":6409,"children":6410},{"style":1029},[6411],{"type":418,"value":5893},{"type":413,"tag":448,"props":6413,"children":6414},{"style":461},[6415],{"type":418,"value":898},{"type":413,"tag":448,"props":6417,"children":6418},{"style":1029},[6419],{"type":418,"value":6420},"ObjectId",{"type":413,"tag":448,"props":6422,"children":6423},{"style":461},[6424],{"type":418,"value":4378},{"type":413,"tag":448,"props":6426,"children":6427},{"class":450,"line":501},[6428,6432,6436,6440,6445,6449],{"type":413,"tag":448,"props":6429,"children":6430},{"style":1029},[6431],{"type":418,"value":5946},{"type":413,"tag":448,"props":6433,"children":6434},{"style":461},[6435],{"type":418,"value":1037},{"type":413,"tag":448,"props":6437,"children":6438},{"style":461},[6439],{"type":418,"value":995},{"type":413,"tag":448,"props":6441,"children":6442},{"style":467},[6443],{"type":418,"value":6444},"AzureReadyDeploys",{"type":413,"tag":448,"props":6446,"children":6447},{"style":461},[6448],{"type":418,"value":1183},{"type":413,"tag":448,"props":6450,"children":6451},{"style":461},[6452],{"type":418,"value":4378},{"type":413,"tag":448,"props":6454,"children":6455},{"class":450,"line":511},[6456,6460,6464,6468,6473,6477],{"type":413,"tag":448,"props":6457,"children":6458},{"style":1029},[6459],{"type":418,"value":4356},{"type":413,"tag":448,"props":6461,"children":6462},{"style":461},[6463],{"type":418,"value":1037},{"type":413,"tag":448,"props":6465,"children":6466},{"style":461},[6467],{"type":418,"value":995},{"type":413,"tag":448,"props":6469,"children":6470},{"style":467},[6471],{"type":418,"value":6472},"Deployments for azure-ready-repository",{"type":413,"tag":448,"props":6474,"children":6475},{"style":461},[6476],{"type":418,"value":1183},{"type":413,"tag":448,"props":6478,"children":6479},{"style":461},[6480],{"type":418,"value":4378},{"type":413,"tag":448,"props":6482,"children":6483},{"class":450,"line":524},[6484,6489,6493,6498,6502,6506,6510],{"type":413,"tag":448,"props":6485,"children":6486},{"style":1029},[6487],{"type":418,"value":6488},"    Audiences ",{"type":413,"tag":448,"props":6490,"children":6491},{"style":461},[6492],{"type":418,"value":1037},{"type":413,"tag":448,"props":6494,"children":6495},{"style":461},[6496],{"type":418,"value":6497}," new(){",{"type":413,"tag":448,"props":6499,"children":6500},{"style":461},[6501],{"type":418,"value":1183},{"type":413,"tag":448,"props":6503,"children":6504},{"style":467},[6505],{"type":418,"value":1902},{"type":413,"tag":448,"props":6507,"children":6508},{"style":461},[6509],{"type":418,"value":1183},{"type":413,"tag":448,"props":6511,"children":6512},{"style":461},[6513],{"type":418,"value":6514}," },\n",{"type":413,"tag":448,"props":6516,"children":6517},{"class":450,"line":542},[6518,6523,6527,6531,6535,6540],{"type":413,"tag":448,"props":6519,"children":6520},{"style":1029},[6521],{"type":418,"value":6522},"    Issuer ",{"type":413,"tag":448,"props":6524,"children":6525},{"style":461},[6526],{"type":418,"value":1037},{"type":413,"tag":448,"props":6528,"children":6529},{"style":1029},[6530],{"type":418,"value":5116},{"type":413,"tag":448,"props":6532,"children":6533},{"style":461},[6534],{"type":418,"value":898},{"type":413,"tag":448,"props":6536,"children":6537},{"style":1029},[6538],{"type":418,"value":6539},"WorkloadIdentityFederationIssuer",{"type":413,"tag":448,"props":6541,"children":6542},{"style":461},[6543],{"type":418,"value":4378},{"type":413,"tag":448,"props":6545,"children":6546},{"class":450,"line":560},[6547,6552,6556,6560,6564,6568,6572,6576,6581,6585,6590,6594,6598,6602,6607,6611,6616,6620,6624,6628,6633,6637,6642,6646],{"type":413,"tag":448,"props":6548,"children":6549},{"style":1029},[6550],{"type":418,"value":6551},"    Subject ",{"type":413,"tag":448,"props":6553,"children":6554},{"style":461},[6555],{"type":418,"value":1037},{"type":413,"tag":448,"props":6557,"children":6558},{"style":1029},[6559],{"type":418,"value":6275},{"type":413,"tag":448,"props":6561,"children":6562},{"style":461},[6563],{"type":418,"value":898},{"type":413,"tag":448,"props":6565,"children":6566},{"style":2000},[6567],{"type":418,"value":6284},{"type":413,"tag":448,"props":6569,"children":6570},{"style":461},[6571],{"type":418,"value":2041},{"type":413,"tag":448,"props":6573,"children":6574},{"style":461},[6575],{"type":418,"value":5726},{"type":413,"tag":448,"props":6577,"children":6578},{"style":467},[6579],{"type":418,"value":6580},"sc://",{"type":413,"tag":448,"props":6582,"children":6583},{"style":461},[6584],{"type":418,"value":5736},{"type":413,"tag":448,"props":6586,"children":6587},{"style":1029},[6588],{"type":418,"value":6589},"organisationName",{"type":413,"tag":448,"props":6591,"children":6592},{"style":461},[6593],{"type":418,"value":1825},{"type":413,"tag":448,"props":6595,"children":6596},{"style":467},[6597],{"type":418,"value":1687},{"type":413,"tag":448,"props":6599,"children":6600},{"style":461},[6601],{"type":418,"value":5736},{"type":413,"tag":448,"props":6603,"children":6604},{"style":1029},[6605],{"type":418,"value":6606},"project",{"type":413,"tag":448,"props":6608,"children":6609},{"style":461},[6610],{"type":418,"value":898},{"type":413,"tag":448,"props":6612,"children":6613},{"style":1029},[6614],{"type":418,"value":6615},"Name",{"type":413,"tag":448,"props":6617,"children":6618},{"style":461},[6619],{"type":418,"value":1825},{"type":413,"tag":448,"props":6621,"children":6622},{"style":467},[6623],{"type":418,"value":1687},{"type":413,"tag":448,"props":6625,"children":6626},{"style":461},[6627],{"type":418,"value":5736},{"type":413,"tag":448,"props":6629,"children":6630},{"style":1029},[6631],{"type":418,"value":6632},"serviceConnection",{"type":413,"tag":448,"props":6634,"children":6635},{"style":461},[6636],{"type":418,"value":898},{"type":413,"tag":448,"props":6638,"children":6639},{"style":1029},[6640],{"type":418,"value":6641},"ServiceEndpointName",{"type":413,"tag":448,"props":6643,"children":6644},{"style":461},[6645],{"type":418,"value":1461},{"type":413,"tag":448,"props":6647,"children":6648},{"style":461},[6649],{"type":418,"value":1197},{"type":413,"tag":448,"props":6651,"children":6652},{"class":450,"line":573},[6653],{"type":413,"tag":448,"props":6654,"children":6655},{"style":461},[6656],{"type":418,"value":4637},{"type":413,"tag":414,"props":6658,"children":6659},{},[6660,6662,6668],{"type":418,"value":6661},"You can observe that the federation subject adheres to a particular format (",{"type":413,"tag":444,"props":6663,"children":6665},{"className":6664},[],[6666],{"type":418,"value":6667},"sc://\u003Corg>/\u003Cproject>/\u003Cservice connection name>",{"type":418,"value":6669},"), which identifies the service connection authorized for authentication with Azure.",{"type":413,"tag":866,"props":6671,"children":6673},{"id":6672},"create-the-deployment-pipeline",[6674],{"type":418,"value":6675},"Create the deployment pipeline",{"type":413,"tag":414,"props":6677,"children":6678},{},[6679],{"type":418,"value":6680},"We have completed the configuration of an ARM Service Connection that employs Workload Identity Federation for authentication with Azure. While we could stop at this point, it would be nice to automate the creation of a pipeline that utilizes this service connection and seize the opportunity to ensure everything works properly.",{"type":413,"tag":414,"props":6682,"children":6683},{},[6684,6686,6692],{"type":418,"value":6685},"For this purpose, I have written a very simple YAML pipeline that runs the ",{"type":413,"tag":444,"props":6687,"children":6689},{"className":6688},[],[6690],{"type":418,"value":6691},"AzureCLI",{"type":418,"value":6693}," task to show information about the Azure subscription associated with the previously created service connection.",{"type":413,"tag":437,"props":6695,"children":6697},{"className":4283,"code":6696,"language":326,"meta":401,"style":401},"trigger:\n  - main\n\npool:\n  vmImage: ubuntu-latest\n\nsteps:\n  - task: AzureCLI@2\n    inputs:\n      azureSubscription: 'azure-with-oidc'\n      scriptType: 'pscore'\n      scriptLocation: 'inlineScript'\n      inlineScript: 'az account show --query id -o tsv'\n",[6698],{"type":413,"tag":444,"props":6699,"children":6700},{"__ignoreMap":401},[6701,6713,6726,6733,6745,6771,6778,6790,6816,6828,6852,6877,6902],{"type":413,"tag":448,"props":6702,"children":6703},{"class":450,"line":451},[6704,6709],{"type":413,"tag":448,"props":6705,"children":6706},{"style":949},[6707],{"type":418,"value":6708},"trigger",{"type":413,"tag":448,"props":6710,"children":6711},{"style":461},[6712],{"type":418,"value":485},{"type":413,"tag":448,"props":6714,"children":6715},{"class":450,"line":473},[6716,6721],{"type":413,"tag":448,"props":6717,"children":6718},{"style":461},[6719],{"type":418,"value":6720},"  -",{"type":413,"tag":448,"props":6722,"children":6723},{"style":1029},[6724],{"type":418,"value":6725}," main\n",{"type":413,"tag":448,"props":6727,"children":6728},{"class":450,"line":488},[6729],{"type":413,"tag":448,"props":6730,"children":6731},{"emptyLinePlaceholder":505},[6732],{"type":418,"value":508},{"type":413,"tag":448,"props":6734,"children":6735},{"class":450,"line":501},[6736,6741],{"type":413,"tag":448,"props":6737,"children":6738},{"style":949},[6739],{"type":418,"value":6740},"pool",{"type":413,"tag":448,"props":6742,"children":6743},{"style":461},[6744],{"type":418,"value":485},{"type":413,"tag":448,"props":6746,"children":6747},{"class":450,"line":511},[6748,6753,6757,6762,6766],{"type":413,"tag":448,"props":6749,"children":6750},{"style":949},[6751],{"type":418,"value":6752},"  vmImage",{"type":413,"tag":448,"props":6754,"children":6755},{"style":461},[6756],{"type":418,"value":464},{"type":413,"tag":448,"props":6758,"children":6759},{"style":1029},[6760],{"type":418,"value":6761}," ubuntu",{"type":413,"tag":448,"props":6763,"children":6764},{"style":461},[6765],{"type":418,"value":1173},{"type":413,"tag":448,"props":6767,"children":6768},{"style":1029},[6769],{"type":418,"value":6770},"latest\n",{"type":413,"tag":448,"props":6772,"children":6773},{"class":450,"line":524},[6774],{"type":413,"tag":448,"props":6775,"children":6776},{"emptyLinePlaceholder":505},[6777],{"type":418,"value":508},{"type":413,"tag":448,"props":6779,"children":6780},{"class":450,"line":542},[6781,6786],{"type":413,"tag":448,"props":6782,"children":6783},{"style":949},[6784],{"type":418,"value":6785},"steps",{"type":413,"tag":448,"props":6787,"children":6788},{"style":461},[6789],{"type":418,"value":485},{"type":413,"tag":448,"props":6791,"children":6792},{"class":450,"line":560},[6793,6797,6802,6806,6811],{"type":413,"tag":448,"props":6794,"children":6795},{"style":461},[6796],{"type":418,"value":6720},{"type":413,"tag":448,"props":6798,"children":6799},{"style":949},[6800],{"type":418,"value":6801}," task",{"type":413,"tag":448,"props":6803,"children":6804},{"style":461},[6805],{"type":418,"value":464},{"type":413,"tag":448,"props":6807,"children":6808},{"style":1029},[6809],{"type":418,"value":6810}," AzureCLI@",{"type":413,"tag":448,"props":6812,"children":6813},{"style":1733},[6814],{"type":418,"value":6815},"2\n",{"type":413,"tag":448,"props":6817,"children":6818},{"class":450,"line":573},[6819,6824],{"type":413,"tag":448,"props":6820,"children":6821},{"style":949},[6822],{"type":418,"value":6823},"    inputs",{"type":413,"tag":448,"props":6825,"children":6826},{"style":461},[6827],{"type":418,"value":485},{"type":413,"tag":448,"props":6829,"children":6830},{"class":450,"line":586},[6831,6836,6840,6844,6848],{"type":413,"tag":448,"props":6832,"children":6833},{"style":949},[6834],{"type":418,"value":6835},"      azureSubscription",{"type":413,"tag":448,"props":6837,"children":6838},{"style":461},[6839],{"type":418,"value":464},{"type":413,"tag":448,"props":6841,"children":6842},{"style":461},[6843],{"type":418,"value":637},{"type":413,"tag":448,"props":6845,"children":6846},{"style":467},[6847],{"type":418,"value":5209},{"type":413,"tag":448,"props":6849,"children":6850},{"style":461},[6851],{"type":418,"value":647},{"type":413,"tag":448,"props":6853,"children":6854},{"class":450,"line":604},[6855,6860,6864,6868,6873],{"type":413,"tag":448,"props":6856,"children":6857},{"style":949},[6858],{"type":418,"value":6859},"      scriptType",{"type":413,"tag":448,"props":6861,"children":6862},{"style":461},[6863],{"type":418,"value":464},{"type":413,"tag":448,"props":6865,"children":6866},{"style":461},[6867],{"type":418,"value":637},{"type":413,"tag":448,"props":6869,"children":6870},{"style":467},[6871],{"type":418,"value":6872},"pscore",{"type":413,"tag":448,"props":6874,"children":6875},{"style":461},[6876],{"type":418,"value":647},{"type":413,"tag":448,"props":6878,"children":6879},{"class":450,"line":617},[6880,6885,6889,6893,6898],{"type":413,"tag":448,"props":6881,"children":6882},{"style":949},[6883],{"type":418,"value":6884},"      scriptLocation",{"type":413,"tag":448,"props":6886,"children":6887},{"style":461},[6888],{"type":418,"value":464},{"type":413,"tag":448,"props":6890,"children":6891},{"style":461},[6892],{"type":418,"value":637},{"type":413,"tag":448,"props":6894,"children":6895},{"style":467},[6896],{"type":418,"value":6897},"inlineScript",{"type":413,"tag":448,"props":6899,"children":6900},{"style":461},[6901],{"type":418,"value":647},{"type":413,"tag":448,"props":6903,"children":6904},{"class":450,"line":650},[6905,6910,6914,6918,6923],{"type":413,"tag":448,"props":6906,"children":6907},{"style":949},[6908],{"type":418,"value":6909},"      inlineScript",{"type":413,"tag":448,"props":6911,"children":6912},{"style":461},[6913],{"type":418,"value":464},{"type":413,"tag":448,"props":6915,"children":6916},{"style":461},[6917],{"type":418,"value":637},{"type":413,"tag":448,"props":6919,"children":6920},{"style":467},[6921],{"type":418,"value":6922},"az account show --query id -o tsv",{"type":413,"tag":448,"props":6924,"children":6925},{"style":461},[6926],{"type":418,"value":647},{"type":413,"tag":414,"props":6928,"children":6929},{},[6930],{"type":418,"value":6931},"We can add this file in the Git repository:",{"type":413,"tag":437,"props":6933,"children":6935},{"className":4283,"code":6934,"language":326,"meta":401,"style":401},"var pipelineFile = new GitRepositoryFile(\"AzurePipeline\", new()\n{\n    File = \"azure-pipelines.yaml\",\n    RepositoryId = repository.Apply(r => r.Id),\n    CommitMessage = \"Add preconfigured pipeline file\",\n    Content = File.ReadAllText(\"azure-pipelines.yml\"),\n    Branch = \"refs/heads/main\"\n});\n",[6936],{"type":413,"tag":444,"props":6937,"children":6938},{"__ignoreMap":401},[6939,6989,6996,7025,7080,7109,7156,7180],{"type":413,"tag":448,"props":6940,"children":6941},{"class":450,"line":451},[6942,6946,6951,6955,6959,6964,6968,6972,6977,6981,6985],{"type":413,"tag":448,"props":6943,"children":6944},{"style":949},[6945],{"type":418,"value":4296},{"type":413,"tag":448,"props":6947,"children":6948},{"style":949},[6949],{"type":418,"value":6950}," pipelineFile",{"type":413,"tag":448,"props":6952,"children":6953},{"style":461},[6954],{"type":418,"value":4306},{"type":413,"tag":448,"props":6956,"children":6957},{"style":461},[6958],{"type":418,"value":3943},{"type":413,"tag":448,"props":6960,"children":6961},{"style":949},[6962],{"type":418,"value":6963}," GitRepositoryFile",{"type":413,"tag":448,"props":6965,"children":6966},{"style":461},[6967],{"type":418,"value":2041},{"type":413,"tag":448,"props":6969,"children":6970},{"style":461},[6971],{"type":418,"value":1183},{"type":413,"tag":448,"props":6973,"children":6974},{"style":467},[6975],{"type":418,"value":6976},"AzurePipeline",{"type":413,"tag":448,"props":6978,"children":6979},{"style":461},[6980],{"type":418,"value":1183},{"type":413,"tag":448,"props":6982,"children":6983},{"style":461},[6984],{"type":418,"value":2059},{"type":413,"tag":448,"props":6986,"children":6987},{"style":461},[6988],{"type":418,"value":4341},{"type":413,"tag":448,"props":6990,"children":6991},{"class":450,"line":473},[6992],{"type":413,"tag":448,"props":6993,"children":6994},{"style":461},[6995],{"type":418,"value":1741},{"type":413,"tag":448,"props":6997,"children":6998},{"class":450,"line":488},[6999,7004,7008,7012,7017,7021],{"type":413,"tag":448,"props":7000,"children":7001},{"style":1029},[7002],{"type":418,"value":7003},"    File ",{"type":413,"tag":448,"props":7005,"children":7006},{"style":461},[7007],{"type":418,"value":1037},{"type":413,"tag":448,"props":7009,"children":7010},{"style":461},[7011],{"type":418,"value":995},{"type":413,"tag":448,"props":7013,"children":7014},{"style":467},[7015],{"type":418,"value":7016},"azure-pipelines.yaml",{"type":413,"tag":448,"props":7018,"children":7019},{"style":461},[7020],{"type":418,"value":1183},{"type":413,"tag":448,"props":7022,"children":7023},{"style":461},[7024],{"type":418,"value":4378},{"type":413,"tag":448,"props":7026,"children":7027},{"class":450,"line":501},[7028,7033,7037,7041,7045,7049,7053,7058,7062,7067,7071,7075],{"type":413,"tag":448,"props":7029,"children":7030},{"style":1029},[7031],{"type":418,"value":7032},"    RepositoryId ",{"type":413,"tag":448,"props":7034,"children":7035},{"style":461},[7036],{"type":418,"value":1037},{"type":413,"tag":448,"props":7038,"children":7039},{"style":1029},[7040],{"type":418,"value":4675},{"type":413,"tag":448,"props":7042,"children":7043},{"style":461},[7044],{"type":418,"value":898},{"type":413,"tag":448,"props":7046,"children":7047},{"style":2000},[7048],{"type":418,"value":5468},{"type":413,"tag":448,"props":7050,"children":7051},{"style":461},[7052],{"type":418,"value":2041},{"type":413,"tag":448,"props":7054,"children":7055},{"style":949},[7056],{"type":418,"value":7057},"r",{"type":413,"tag":448,"props":7059,"children":7060},{"style":461},[7061],{"type":418,"value":5482},{"type":413,"tag":448,"props":7063,"children":7064},{"style":1029},[7065],{"type":418,"value":7066}," r",{"type":413,"tag":448,"props":7068,"children":7069},{"style":461},[7070],{"type":418,"value":898},{"type":413,"tag":448,"props":7072,"children":7073},{"style":1029},[7074],{"type":418,"value":4730},{"type":413,"tag":448,"props":7076,"children":7077},{"style":461},[7078],{"type":418,"value":7079},"),\n",{"type":413,"tag":448,"props":7081,"children":7082},{"class":450,"line":511},[7083,7088,7092,7096,7101,7105],{"type":413,"tag":448,"props":7084,"children":7085},{"style":1029},[7086],{"type":418,"value":7087},"    CommitMessage ",{"type":413,"tag":448,"props":7089,"children":7090},{"style":461},[7091],{"type":418,"value":1037},{"type":413,"tag":448,"props":7093,"children":7094},{"style":461},[7095],{"type":418,"value":995},{"type":413,"tag":448,"props":7097,"children":7098},{"style":467},[7099],{"type":418,"value":7100},"Add preconfigured pipeline file",{"type":413,"tag":448,"props":7102,"children":7103},{"style":461},[7104],{"type":418,"value":1183},{"type":413,"tag":448,"props":7106,"children":7107},{"style":461},[7108],{"type":418,"value":4378},{"type":413,"tag":448,"props":7110,"children":7111},{"class":450,"line":524},[7112,7117,7121,7126,7130,7135,7139,7143,7148,7152],{"type":413,"tag":448,"props":7113,"children":7114},{"style":1029},[7115],{"type":418,"value":7116},"    Content ",{"type":413,"tag":448,"props":7118,"children":7119},{"style":461},[7120],{"type":418,"value":1037},{"type":413,"tag":448,"props":7122,"children":7123},{"style":1029},[7124],{"type":418,"value":7125}," File",{"type":413,"tag":448,"props":7127,"children":7128},{"style":461},[7129],{"type":418,"value":898},{"type":413,"tag":448,"props":7131,"children":7132},{"style":2000},[7133],{"type":418,"value":7134},"ReadAllText",{"type":413,"tag":448,"props":7136,"children":7137},{"style":461},[7138],{"type":418,"value":2041},{"type":413,"tag":448,"props":7140,"children":7141},{"style":461},[7142],{"type":418,"value":1183},{"type":413,"tag":448,"props":7144,"children":7145},{"style":467},[7146],{"type":418,"value":7147},"azure-pipelines.yml",{"type":413,"tag":448,"props":7149,"children":7150},{"style":461},[7151],{"type":418,"value":1183},{"type":413,"tag":448,"props":7153,"children":7154},{"style":461},[7155],{"type":418,"value":7079},{"type":413,"tag":448,"props":7157,"children":7158},{"class":450,"line":542},[7159,7164,7168,7172,7176],{"type":413,"tag":448,"props":7160,"children":7161},{"style":1029},[7162],{"type":418,"value":7163},"    Branch ",{"type":413,"tag":448,"props":7165,"children":7166},{"style":461},[7167],{"type":418,"value":1037},{"type":413,"tag":448,"props":7169,"children":7170},{"style":461},[7171],{"type":418,"value":995},{"type":413,"tag":448,"props":7173,"children":7174},{"style":467},[7175],{"type":418,"value":5026},{"type":413,"tag":448,"props":7177,"children":7178},{"style":461},[7179],{"type":418,"value":1005},{"type":413,"tag":448,"props":7181,"children":7182},{"class":450,"line":560},[7183],{"type":413,"tag":448,"props":7184,"children":7185},{"style":461},[7186],{"type":418,"value":4637},{"type":413,"tag":414,"props":7188,"children":7189},{},[7190],{"type":418,"value":7191},"Now, we have to create the pipeline itself:",{"type":413,"tag":437,"props":7193,"children":7195},{"className":4283,"code":7194,"language":326,"meta":401,"style":401},"var pipeline = new BuildDefinition(\"deployToAzure\", new()\n{\n    ProjectId = project.Id,\n    Repository = new BuildDefinitionRepositoryArgs()\n    {\n        RepoId = repository.Apply(r => r.Id),\n        BranchName = \"refs/heads/main\",\n        YmlPath = pipelineFile.File,\n        RepoType = \"TfsGit\"\n    }\n});\n",[7196],{"type":413,"tag":444,"props":7197,"children":7198},{"__ignoreMap":401},[7199,7249,7256,7283,7308,7315,7367,7395,7424,7449,7456],{"type":413,"tag":448,"props":7200,"children":7201},{"class":450,"line":451},[7202,7206,7211,7215,7219,7224,7228,7232,7237,7241,7245],{"type":413,"tag":448,"props":7203,"children":7204},{"style":949},[7205],{"type":418,"value":4296},{"type":413,"tag":448,"props":7207,"children":7208},{"style":949},[7209],{"type":418,"value":7210}," pipeline",{"type":413,"tag":448,"props":7212,"children":7213},{"style":461},[7214],{"type":418,"value":4306},{"type":413,"tag":448,"props":7216,"children":7217},{"style":461},[7218],{"type":418,"value":3943},{"type":413,"tag":448,"props":7220,"children":7221},{"style":949},[7222],{"type":418,"value":7223}," BuildDefinition",{"type":413,"tag":448,"props":7225,"children":7226},{"style":461},[7227],{"type":418,"value":2041},{"type":413,"tag":448,"props":7229,"children":7230},{"style":461},[7231],{"type":418,"value":1183},{"type":413,"tag":448,"props":7233,"children":7234},{"style":467},[7235],{"type":418,"value":7236},"deployToAzure",{"type":413,"tag":448,"props":7238,"children":7239},{"style":461},[7240],{"type":418,"value":1183},{"type":413,"tag":448,"props":7242,"children":7243},{"style":461},[7244],{"type":418,"value":2059},{"type":413,"tag":448,"props":7246,"children":7247},{"style":461},[7248],{"type":418,"value":4341},{"type":413,"tag":448,"props":7250,"children":7251},{"class":450,"line":473},[7252],{"type":413,"tag":448,"props":7253,"children":7254},{"style":461},[7255],{"type":418,"value":1741},{"type":413,"tag":448,"props":7257,"children":7258},{"class":450,"line":488},[7259,7263,7267,7271,7275,7279],{"type":413,"tag":448,"props":7260,"children":7261},{"style":1029},[7262],{"type":418,"value":4713},{"type":413,"tag":448,"props":7264,"children":7265},{"style":461},[7266],{"type":418,"value":1037},{"type":413,"tag":448,"props":7268,"children":7269},{"style":1029},[7270],{"type":418,"value":4301},{"type":413,"tag":448,"props":7272,"children":7273},{"style":461},[7274],{"type":418,"value":898},{"type":413,"tag":448,"props":7276,"children":7277},{"style":1029},[7278],{"type":418,"value":4730},{"type":413,"tag":448,"props":7280,"children":7281},{"style":461},[7282],{"type":418,"value":4378},{"type":413,"tag":448,"props":7284,"children":7285},{"class":450,"line":501},[7286,7291,7295,7299,7304],{"type":413,"tag":448,"props":7287,"children":7288},{"style":1029},[7289],{"type":418,"value":7290},"    Repository ",{"type":413,"tag":448,"props":7292,"children":7293},{"style":461},[7294],{"type":418,"value":1037},{"type":413,"tag":448,"props":7296,"children":7297},{"style":461},[7298],{"type":418,"value":3943},{"type":413,"tag":448,"props":7300,"children":7301},{"style":949},[7302],{"type":418,"value":7303}," BuildDefinitionRepositoryArgs",{"type":413,"tag":448,"props":7305,"children":7306},{"style":461},[7307],{"type":418,"value":4887},{"type":413,"tag":448,"props":7309,"children":7310},{"class":450,"line":511},[7311],{"type":413,"tag":448,"props":7312,"children":7313},{"style":461},[7314],{"type":418,"value":4402},{"type":413,"tag":448,"props":7316,"children":7317},{"class":450,"line":524},[7318,7323,7327,7331,7335,7339,7343,7347,7351,7355,7359,7363],{"type":413,"tag":448,"props":7319,"children":7320},{"style":1029},[7321],{"type":418,"value":7322},"        RepoId ",{"type":413,"tag":448,"props":7324,"children":7325},{"style":461},[7326],{"type":418,"value":1037},{"type":413,"tag":448,"props":7328,"children":7329},{"style":1029},[7330],{"type":418,"value":4675},{"type":413,"tag":448,"props":7332,"children":7333},{"style":461},[7334],{"type":418,"value":898},{"type":413,"tag":448,"props":7336,"children":7337},{"style":2000},[7338],{"type":418,"value":5468},{"type":413,"tag":448,"props":7340,"children":7341},{"style":461},[7342],{"type":418,"value":2041},{"type":413,"tag":448,"props":7344,"children":7345},{"style":949},[7346],{"type":418,"value":7057},{"type":413,"tag":448,"props":7348,"children":7349},{"style":461},[7350],{"type":418,"value":5482},{"type":413,"tag":448,"props":7352,"children":7353},{"style":1029},[7354],{"type":418,"value":7066},{"type":413,"tag":448,"props":7356,"children":7357},{"style":461},[7358],{"type":418,"value":898},{"type":413,"tag":448,"props":7360,"children":7361},{"style":1029},[7362],{"type":418,"value":4730},{"type":413,"tag":448,"props":7364,"children":7365},{"style":461},[7366],{"type":418,"value":7079},{"type":413,"tag":448,"props":7368,"children":7369},{"class":450,"line":542},[7370,7375,7379,7383,7387,7391],{"type":413,"tag":448,"props":7371,"children":7372},{"style":1029},[7373],{"type":418,"value":7374},"        BranchName ",{"type":413,"tag":448,"props":7376,"children":7377},{"style":461},[7378],{"type":418,"value":1037},{"type":413,"tag":448,"props":7380,"children":7381},{"style":461},[7382],{"type":418,"value":995},{"type":413,"tag":448,"props":7384,"children":7385},{"style":467},[7386],{"type":418,"value":5026},{"type":413,"tag":448,"props":7388,"children":7389},{"style":461},[7390],{"type":418,"value":1183},{"type":413,"tag":448,"props":7392,"children":7393},{"style":461},[7394],{"type":418,"value":4378},{"type":413,"tag":448,"props":7396,"children":7397},{"class":450,"line":560},[7398,7403,7407,7411,7415,7420],{"type":413,"tag":448,"props":7399,"children":7400},{"style":1029},[7401],{"type":418,"value":7402},"        YmlPath ",{"type":413,"tag":448,"props":7404,"children":7405},{"style":461},[7406],{"type":418,"value":1037},{"type":413,"tag":448,"props":7408,"children":7409},{"style":1029},[7410],{"type":418,"value":6950},{"type":413,"tag":448,"props":7412,"children":7413},{"style":461},[7414],{"type":418,"value":898},{"type":413,"tag":448,"props":7416,"children":7417},{"style":1029},[7418],{"type":418,"value":7419},"File",{"type":413,"tag":448,"props":7421,"children":7422},{"style":461},[7423],{"type":418,"value":4378},{"type":413,"tag":448,"props":7425,"children":7426},{"class":450,"line":573},[7427,7432,7436,7440,7445],{"type":413,"tag":448,"props":7428,"children":7429},{"style":1029},[7430],{"type":418,"value":7431},"        RepoType ",{"type":413,"tag":448,"props":7433,"children":7434},{"style":461},[7435],{"type":418,"value":1037},{"type":413,"tag":448,"props":7437,"children":7438},{"style":461},[7439],{"type":418,"value":995},{"type":413,"tag":448,"props":7441,"children":7442},{"style":467},[7443],{"type":418,"value":7444},"TfsGit",{"type":413,"tag":448,"props":7446,"children":7447},{"style":461},[7448],{"type":418,"value":1005},{"type":413,"tag":448,"props":7450,"children":7451},{"class":450,"line":586},[7452],{"type":413,"tag":448,"props":7453,"children":7454},{"style":461},[7455],{"type":418,"value":5379},{"type":413,"tag":448,"props":7457,"children":7458},{"class":450,"line":604},[7459],{"type":413,"tag":448,"props":7460,"children":7461},{"style":461},[7462],{"type":418,"value":4637},{"type":413,"tag":414,"props":7464,"children":7465},{},[7466],{"type":418,"value":7467},"To complete the automation process, we can authorize the pipeline to utilize the service connection, eliminating the need for manual intervention through the portal:",{"type":413,"tag":437,"props":7469,"children":7471},{"className":4283,"code":7470,"language":326,"meta":401,"style":401},"new PipelineAuthorization(\"azureOidcPipelineAuthorization\", new()\n{\n    ProjectId = project.Id,\n    Type = \"endpoint\",\n    PipelineId = pipeline.Id.Apply(int.Parse),\n    ResourceId = serviceConnection.Id\n});\n",[7472],{"type":413,"tag":444,"props":7473,"children":7474},{"__ignoreMap":401},[7475,7512,7519,7546,7575,7621,7646],{"type":413,"tag":448,"props":7476,"children":7477},{"class":450,"line":451},[7478,7482,7487,7491,7495,7500,7504,7508],{"type":413,"tag":448,"props":7479,"children":7480},{"style":6130},[7481],{"type":418,"value":6133},{"type":413,"tag":448,"props":7483,"children":7484},{"style":2000},[7485],{"type":418,"value":7486}," PipelineAuthorization",{"type":413,"tag":448,"props":7488,"children":7489},{"style":461},[7490],{"type":418,"value":2041},{"type":413,"tag":448,"props":7492,"children":7493},{"style":461},[7494],{"type":418,"value":1183},{"type":413,"tag":448,"props":7496,"children":7497},{"style":467},[7498],{"type":418,"value":7499},"azureOidcPipelineAuthorization",{"type":413,"tag":448,"props":7501,"children":7502},{"style":461},[7503],{"type":418,"value":1183},{"type":413,"tag":448,"props":7505,"children":7506},{"style":461},[7507],{"type":418,"value":2059},{"type":413,"tag":448,"props":7509,"children":7510},{"style":461},[7511],{"type":418,"value":4341},{"type":413,"tag":448,"props":7513,"children":7514},{"class":450,"line":473},[7515],{"type":413,"tag":448,"props":7516,"children":7517},{"style":461},[7518],{"type":418,"value":1741},{"type":413,"tag":448,"props":7520,"children":7521},{"class":450,"line":488},[7522,7526,7530,7534,7538,7542],{"type":413,"tag":448,"props":7523,"children":7524},{"style":1029},[7525],{"type":418,"value":4713},{"type":413,"tag":448,"props":7527,"children":7528},{"style":461},[7529],{"type":418,"value":1037},{"type":413,"tag":448,"props":7531,"children":7532},{"style":1029},[7533],{"type":418,"value":4301},{"type":413,"tag":448,"props":7535,"children":7536},{"style":461},[7537],{"type":418,"value":898},{"type":413,"tag":448,"props":7539,"children":7540},{"style":1029},[7541],{"type":418,"value":4730},{"type":413,"tag":448,"props":7543,"children":7544},{"style":461},[7545],{"type":418,"value":4378},{"type":413,"tag":448,"props":7547,"children":7548},{"class":450,"line":501},[7549,7554,7558,7562,7567,7571],{"type":413,"tag":448,"props":7550,"children":7551},{"style":1029},[7552],{"type":418,"value":7553},"    Type ",{"type":413,"tag":448,"props":7555,"children":7556},{"style":461},[7557],{"type":418,"value":1037},{"type":413,"tag":448,"props":7559,"children":7560},{"style":461},[7561],{"type":418,"value":995},{"type":413,"tag":448,"props":7563,"children":7564},{"style":467},[7565],{"type":418,"value":7566},"endpoint",{"type":413,"tag":448,"props":7568,"children":7569},{"style":461},[7570],{"type":418,"value":1183},{"type":413,"tag":448,"props":7572,"children":7573},{"style":461},[7574],{"type":418,"value":4378},{"type":413,"tag":448,"props":7576,"children":7577},{"class":450,"line":511},[7578,7583,7587,7591,7595,7599,7603,7607,7612,7617],{"type":413,"tag":448,"props":7579,"children":7580},{"style":1029},[7581],{"type":418,"value":7582},"    PipelineId ",{"type":413,"tag":448,"props":7584,"children":7585},{"style":461},[7586],{"type":418,"value":1037},{"type":413,"tag":448,"props":7588,"children":7589},{"style":1029},[7590],{"type":418,"value":7210},{"type":413,"tag":448,"props":7592,"children":7593},{"style":461},[7594],{"type":418,"value":898},{"type":413,"tag":448,"props":7596,"children":7597},{"style":1029},[7598],{"type":418,"value":4730},{"type":413,"tag":448,"props":7600,"children":7601},{"style":461},[7602],{"type":418,"value":898},{"type":413,"tag":448,"props":7604,"children":7605},{"style":2000},[7606],{"type":418,"value":5468},{"type":413,"tag":448,"props":7608,"children":7609},{"style":461},[7610],{"type":418,"value":7611},"(int.",{"type":413,"tag":448,"props":7613,"children":7614},{"style":1029},[7615],{"type":418,"value":7616},"Parse",{"type":413,"tag":448,"props":7618,"children":7619},{"style":461},[7620],{"type":418,"value":7079},{"type":413,"tag":448,"props":7622,"children":7623},{"class":450,"line":524},[7624,7629,7633,7637,7641],{"type":413,"tag":448,"props":7625,"children":7626},{"style":1029},[7627],{"type":418,"value":7628},"    ResourceId ",{"type":413,"tag":448,"props":7630,"children":7631},{"style":461},[7632],{"type":418,"value":1037},{"type":413,"tag":448,"props":7634,"children":7635},{"style":1029},[7636],{"type":418,"value":5116},{"type":413,"tag":448,"props":7638,"children":7639},{"style":461},[7640],{"type":418,"value":898},{"type":413,"tag":448,"props":7642,"children":7643},{"style":1029},[7644],{"type":418,"value":7645},"Id\n",{"type":413,"tag":448,"props":7647,"children":7648},{"class":450,"line":542},[7649],{"type":413,"tag":448,"props":7650,"children":7651},{"style":461},[7652],{"type":418,"value":4637},{"type":413,"tag":414,"props":7654,"children":7655},{},[7656],{"type":418,"value":7657},"The last thing we can do is create a stack output to expose the URL of the created pipeline:",{"type":413,"tag":437,"props":7659,"children":7661},{"className":4283,"code":7660,"language":326,"meta":401,"style":401},"return new Dictionary\u003Cstring, object?>\n{\n    [\"pipelineUrl\"] = Output.Format($\"{organizationUrl}{project.Name}/_build?definitionId={pipeline.Id}\")\n};\n",[7662],{"type":413,"tag":444,"props":7663,"children":7664},{"__ignoreMap":401},[7665,7701,7708,7814],{"type":413,"tag":448,"props":7666,"children":7667},{"class":450,"line":451},[7668,7673,7677,7682,7687,7692,7696],{"type":413,"tag":448,"props":7669,"children":7670},{"style":785},[7671],{"type":418,"value":7672},"return",{"type":413,"tag":448,"props":7674,"children":7675},{"style":461},[7676],{"type":418,"value":3943},{"type":413,"tag":448,"props":7678,"children":7679},{"style":949},[7680],{"type":418,"value":7681}," Dictionary",{"type":413,"tag":448,"props":7683,"children":7684},{"style":461},[7685],{"type":418,"value":7686},"\u003C",{"type":413,"tag":448,"props":7688,"children":7689},{"style":461},[7690],{"type":418,"value":7691},"string",{"type":413,"tag":448,"props":7693,"children":7694},{"style":461},[7695],{"type":418,"value":2059},{"type":413,"tag":448,"props":7697,"children":7698},{"style":461},[7699],{"type":418,"value":7700}," object?>\n",{"type":413,"tag":448,"props":7702,"children":7703},{"class":450,"line":473},[7704],{"type":413,"tag":448,"props":7705,"children":7706},{"style":461},[7707],{"type":418,"value":1741},{"type":413,"tag":448,"props":7709,"children":7710},{"class":450,"line":488},[7711,7716,7720,7725,7729,7733,7737,7741,7745,7749,7753,7758,7763,7768,7772,7776,7780,7784,7789,7793,7798,7802,7806,7810],{"type":413,"tag":448,"props":7712,"children":7713},{"style":461},[7714],{"type":418,"value":7715},"    [",{"type":413,"tag":448,"props":7717,"children":7718},{"style":461},[7719],{"type":418,"value":1183},{"type":413,"tag":448,"props":7721,"children":7722},{"style":467},[7723],{"type":418,"value":7724},"pipelineUrl",{"type":413,"tag":448,"props":7726,"children":7727},{"style":461},[7728],{"type":418,"value":1183},{"type":413,"tag":448,"props":7730,"children":7731},{"style":461},[7732],{"type":418,"value":4428},{"type":413,"tag":448,"props":7734,"children":7735},{"style":461},[7736],{"type":418,"value":4306},{"type":413,"tag":448,"props":7738,"children":7739},{"style":1029},[7740],{"type":418,"value":6275},{"type":413,"tag":448,"props":7742,"children":7743},{"style":461},[7744],{"type":418,"value":898},{"type":413,"tag":448,"props":7746,"children":7747},{"style":2000},[7748],{"type":418,"value":6284},{"type":413,"tag":448,"props":7750,"children":7751},{"style":461},[7752],{"type":418,"value":2041},{"type":413,"tag":448,"props":7754,"children":7755},{"style":461},[7756],{"type":418,"value":7757},"$\"{",{"type":413,"tag":448,"props":7759,"children":7760},{"style":1029},[7761],{"type":418,"value":7762},"organizationUrl",{"type":413,"tag":448,"props":7764,"children":7765},{"style":461},[7766],{"type":418,"value":7767},"}{",{"type":413,"tag":448,"props":7769,"children":7770},{"style":1029},[7771],{"type":418,"value":6606},{"type":413,"tag":448,"props":7773,"children":7774},{"style":461},[7775],{"type":418,"value":898},{"type":413,"tag":448,"props":7777,"children":7778},{"style":1029},[7779],{"type":418,"value":6615},{"type":413,"tag":448,"props":7781,"children":7782},{"style":461},[7783],{"type":418,"value":1825},{"type":413,"tag":448,"props":7785,"children":7786},{"style":467},[7787],{"type":418,"value":7788},"/_build?definitionId=",{"type":413,"tag":448,"props":7790,"children":7791},{"style":461},[7792],{"type":418,"value":5736},{"type":413,"tag":448,"props":7794,"children":7795},{"style":1029},[7796],{"type":418,"value":7797},"pipeline",{"type":413,"tag":448,"props":7799,"children":7800},{"style":461},[7801],{"type":418,"value":898},{"type":413,"tag":448,"props":7803,"children":7804},{"style":1029},[7805],{"type":418,"value":4730},{"type":413,"tag":448,"props":7807,"children":7808},{"style":461},[7809],{"type":418,"value":1461},{"type":413,"tag":448,"props":7811,"children":7812},{"style":461},[7813],{"type":418,"value":1197},{"type":413,"tag":448,"props":7815,"children":7816},{"class":450,"line":501},[7817],{"type":413,"tag":448,"props":7818,"children":7819},{"style":461},[7820],{"type":418,"value":7821},"};\n",{"type":413,"tag":414,"props":7823,"children":7824},{},[7825,7827,7833],{"type":418,"value":7826},"Now we can execute the ",{"type":413,"tag":444,"props":7828,"children":7830},{"className":7829},[],[7831],{"type":418,"value":7832},"pulumi up",{"type":418,"value":7834}," command to provision all these resources and then open the pipeline page in our browser to test the pipeline.",{"type":413,"tag":841,"props":7836,"children":7837},{"icon":1103},[7838],{"type":413,"tag":414,"props":7839,"children":7840},{},[7841,7843,7849,7851,7858,7860],{"type":418,"value":7842},"On Windows, you can use the ",{"type":413,"tag":444,"props":7844,"children":7846},{"className":7845},[],[7847],{"type":418,"value":7848},"start $(pulumi stack output pipelineUrl)",{"type":418,"value":7850}," command to directly open the browser on the pipeline page. If you are using ",{"type":413,"tag":813,"props":7852,"children":7855},{"href":7853,"rel":7854},"https://www.nushell.sh/",[817],[7856],{"type":418,"value":7857},"Nushell",{"type":418,"value":7859}," the command will be ",{"type":413,"tag":444,"props":7861,"children":7863},{"className":7862},[],[7864],{"type":418,"value":7865},"pulumi stack output pipelineUrl | start $in",{"type":413,"tag":414,"props":7867,"children":7868},{},[7869],{"type":413,"tag":832,"props":7870,"children":7874},{"alt":7871,"className":7872,"src":7873},"Results of the pipeline run in Azure DevOps",[836,837],"/posts/images/azuredevopsoidc_portal.webp",[],{"type":413,"tag":414,"props":7876,"children":7877},{},[7878],{"type":418,"value":7879},"Everything is working as expected.",{"type":413,"tag":420,"props":7881,"children":7883},{"id":7882},"to-conclude",[7884],{"type":418,"value":7885},"To conclude",{"type":413,"tag":414,"props":7887,"children":7888},{},[7889,7891,7897],{"type":418,"value":7890},"In this article, we demonstrated how to automate the configuration of an Azure DevOps project using Workload Identity Federation for secure deployments to Azure. We covered the provisioning of the Microsoft Entra ID and Azure DevOps resources necessary to make this work. It's very similar to ",{"type":413,"tag":813,"props":7892,"children":7894},{"href":852,"rel":7893},[817],[7895],{"type":418,"value":7896},"what can be done for GitHub",{"type":418,"value":7898}," but with the specificities of Azure DevOps.",{"type":413,"tag":414,"props":7900,"children":7901},{},[7902],{"type":418,"value":7903},"It was an opportunity for me to work with the Azure DevOps provider. Even if it does the job, I must admit I was somewhat disappointed with the developer experience which I found to be not very intuitive, with poorly named resources and an overreliance on strings as parameters. I assume that the Azure DevOps APIs are primarily responsible for this, as they are what the provider calls upon.",{"type":413,"tag":414,"props":7905,"children":7906},{},[7907],{"type":418,"value":7908},"One thing I find interesting with Azure DevOps is that YAML pipelines do not need to be updated to take advantage of workload identity federation as long as the Azure Pipelines tasks you are using support it and your ARM service connection has been converted to workload identity federation.",{"type":413,"tag":414,"props":7910,"children":7911},{},[7912],{"type":418,"value":7913},"Anyway, regardless of the CI/CD platform you are using, I believe that employing Workload Identity Federation to deploy code to Azure from pipelines is the right approach.",{"type":413,"tag":414,"props":7915,"children":7916},{},[7917,7919,7929],{"type":418,"value":7918},"You can find the complete source code used for this article ",{"type":413,"tag":813,"props":7920,"children":7923},{"href":7921,"rel":7922},"https://github.com/TechWatching/AzureDevOpsWorkloadIdentity",[817],[7924],{"type":413,"tag":3838,"props":7925,"children":7926},{},[7927],{"type":418,"value":7928},"in this GitHub repository",{"type":418,"value":898},{"type":413,"tag":3710,"props":7931,"children":7932},{},[7933],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":7935},[7936,7937,7939,7946],{"id":3747,"depth":473,"text":3750},{"id":3833,"depth":473,"text":7938},"How can you use Workload Identity Federation to deploy to Azure from Azure Pipelines?",{"id":3910,"depth":473,"text":3913,"children":7940},[7941,7942,7943,7944,7945],{"id":3916,"depth":488,"text":3919},{"id":4154,"depth":488,"text":4157},{"id":5080,"depth":488,"text":5083},{"id":5812,"depth":488,"text":5815},{"id":6672,"depth":488,"text":6675},{"id":7882,"depth":473,"text":7885},"content:1.posts:54.ado-workload-identity-federation.md","1.posts/54.ado-workload-identity-federation.md",{"_path":166,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":165,"description":7950,"lead":7951,"date":7952,"image":7953,"badge":7955,"tags":7956,"body":7957,"_type":3726,"_id":15330,"_source":3728,"_file":15331,"_extension":3730},"Creating an application and deploying it to Azure is not complicated. You write some code on your machine, do some clicks in the Azure portal, or run some Azure CLI commands from your terminal and that's it: your application is up and running in Azure.","Using Azure OpenID Connect with Pulumi in GitHub Actions","2023-07-20T00:00:00.000Z",{"src":7954},"/images/azureOIDC.webp",{"label":266},[228,233,307,374,312,315,376],{"type":410,"children":7958,"toc":15305},[7959,7963,7968,7980,7986,7996,8005,8011,8022,8056,8065,8071,8083,8121,8130,8148,8154,8159,8164,8172,8177,8185,8190,8211,8229,8249,8255,8263,8269,8274,8296,8301,8324,8329,8335,8341,8346,8401,8406,8456,8495,8499,8531,8544,8562,8566,8589,8613,8628,8633,8888,8909,8931,8963,8975,8980,9230,9246,9251,9537,9562,9567,9581,9590,9596,9601,9606,9905,9917,10019,10024,10113,10134,10197,10205,10211,10216,10221,10237,10242,10393,10398,10896,10913,10919,10924,10929,11241,11254,11852,11865,11890,11898,11927,11960,12053,12075,12275,12280,12669,12674,12706,12729,12735,12747,12756,12761,12770,12775,12814,12819,12824,12874,12886,12899,12916,12937,12946,12951,12955,12961,12966,12971,12977,12982,13000,13005,13011,13016,13102,13108,13113,13118,15285,15296,15301],{"type":413,"tag":414,"props":7960,"children":7961},{},[7962],{"type":418,"value":7950},{"type":413,"tag":414,"props":7964,"children":7965},{},[7966],{"type":418,"value":7967},"Yet, that's not real life, at least not what you will do when working on a professional project. Your code needs to be versioned and pushed to a location where your colleagues can work on it. The provisioning of Azure resources and deployment to Azure should be carried out using a properly configured CI/CD pipeline with the necessary authorization.",{"type":413,"tag":414,"props":7969,"children":7970},{},[7971,7973,7978],{"type":418,"value":7972},"That's a lot of work that would need to be done each time you start a new project. So let's automate that using Pulumi to simplify the process and create an \"",{"type":413,"tag":4008,"props":7974,"children":7975},{},[7976],{"type":418,"value":7977},"Azure-Ready GitHub repository",{"type":418,"value":7979},"\".",{"type":413,"tag":420,"props":7981,"children":7983},{"id":7982},"whats-an-azure-ready-github-repository",[7984],{"type":418,"value":7985},"What's an Azure-Ready GitHub repository?",{"type":413,"tag":414,"props":7987,"children":7988},{},[7989,7990,7994],{"type":418,"value":1183},{"type":413,"tag":4008,"props":7991,"children":7992},{},[7993],{"type":418,"value":7977},{"type":418,"value":7995},"\" is not an official term or concept, it's just something I've come up with to describe a Github repository that has everything correctly configured to provision Azure resources or deploy applications to Azure from a GitHub Actions CI/CD pipeline.",{"type":413,"tag":414,"props":7997,"children":7998},{},[7999],{"type":413,"tag":832,"props":8000,"children":8004},{"alt":8001,"className":8002,"src":8003},"Diagram of a GitHub repository interacting with Azure.",[836,837],"/posts/images/azurereadygithub_overview_1.webp",[],{"type":413,"tag":866,"props":8006,"children":8008},{"id":8007},"the-github-part",[8009],{"type":418,"value":8010},"The GitHub part",{"type":413,"tag":414,"props":8012,"children":8013},{},[8014,8016,8020],{"type":418,"value":8015},"On the GitHub side, to have an ",{"type":413,"tag":4008,"props":8017,"children":8018},{},[8019],{"type":418,"value":7977},{"type":418,"value":8021},", we need:",{"type":413,"tag":3766,"props":8023,"children":8024},{},[8025,8038,8043],{"type":413,"tag":2159,"props":8026,"children":8027},{},[8028,8030,8036],{"type":418,"value":8029},"the GitHub repository itself (already initialized with a ",{"type":413,"tag":444,"props":8031,"children":8033},{"className":8032},[],[8034],{"type":418,"value":8035},"main",{"type":418,"value":8037}," branch)",{"type":413,"tag":2159,"props":8039,"children":8040},{},[8041],{"type":418,"value":8042},"the necessary GitHub Actions variables/secrets to authenticate to the correct Azure subscription",{"type":413,"tag":2159,"props":8044,"children":8045},{},[8046,8048,8054],{"type":418,"value":8047},"a YAML file located in the ",{"type":413,"tag":444,"props":8049,"children":8051},{"className":8050},[],[8052],{"type":418,"value":8053},".github/workflows/",{"type":418,"value":8055}," folder that contains the CI/CD pipeline that provisions resources in Azure",{"type":413,"tag":414,"props":8057,"children":8058},{},[8059],{"type":413,"tag":832,"props":8060,"children":8064},{"alt":8061,"className":8062,"src":8063},"A diagram of the GitHub repository to create.",[836,837],"/posts/images/azurereadygithub_github_1.webp",[],{"type":413,"tag":866,"props":8066,"children":8068},{"id":8067},"the-azure-part",[8069],{"type":418,"value":8070},"The Azure part",{"type":413,"tag":414,"props":8072,"children":8073},{},[8074,8076,8081],{"type":418,"value":8075},"On the Azure side, to have an ",{"type":413,"tag":4008,"props":8077,"children":8078},{},[8079],{"type":418,"value":8080},"Azure-Ready GitHub repository,",{"type":418,"value":8082}," we need:",{"type":413,"tag":3766,"props":8084,"children":8085},{},[8086,8091],{"type":413,"tag":2159,"props":8087,"children":8088},{},[8089],{"type":418,"value":8090},"the existing Azure subscription to which resources are deployed",{"type":413,"tag":2159,"props":8092,"children":8093},{},[8094,8096,8101,8103],{"type":418,"value":8095},"an ",{"type":413,"tag":4008,"props":8097,"children":8098},{},[8099],{"type":418,"value":8100},"identity",{"type":418,"value":8102}," in the Azure Active Directory of the desired tenant so that the GitHub CI/CD pipeline can authenticate to Azure and interact with the subscription",{"type":413,"tag":3766,"props":8104,"children":8105},{},[8106,8111,8116],{"type":413,"tag":2159,"props":8107,"children":8108},{},[8109],{"type":418,"value":8110},"an Azure AD application that represents the GitHub Actions pipeline identity",{"type":413,"tag":2159,"props":8112,"children":8113},{},[8114],{"type":418,"value":8115},"a Service Principal (related to the Azure AD application) that has the contributor role on the Azure subscription",{"type":413,"tag":2159,"props":8117,"children":8118},{},[8119],{"type":418,"value":8120},"credentials for the CI/CD pipeline to authenticate to Azure on behalf of this Azure AD application",{"type":413,"tag":414,"props":8122,"children":8123},{},[8124],{"type":413,"tag":832,"props":8125,"children":8129},{"alt":8126,"className":8127,"src":8128},"A diagram of the resources to configure in Azure.",[836,837],"/posts/images/azurereadygithub_azure_1.webp",[],{"type":413,"tag":841,"props":8131,"children":8132},{"icon":3815},[8133],{"type":413,"tag":414,"props":8134,"children":8135},{},[8136,8140,8142,8146],{"type":413,"tag":4008,"props":8137,"children":8138},{},[8139],{"type":418,"value":252},{"type":418,"value":8141}," has recently been renamed ",{"type":413,"tag":4008,"props":8143,"children":8144},{},[8145],{"type":418,"value":382},{"type":418,"value":8147}," (as of the time of writing). However, I will continue to use the term Azure Active Directory throughout the rest of the article. Please note that both terms refer to the same service.",{"type":413,"tag":866,"props":8149,"children":8151},{"id":8150},"the-problem-with-secret-credentials",[8152],{"type":418,"value":8153},"The problem with secret credentials",{"type":413,"tag":414,"props":8155,"children":8156},{},[8157],{"type":418,"value":8158},"People tend to use secret credentials to authenticate their pipeline to Azure and that's not the best thing to do.",{"type":413,"tag":414,"props":8160,"children":8161},{},[8162],{"type":418,"value":8163},"From a security standpoint, depending on secrets always poses a security risk. Even if in that case the secret would be safely stored in a GitHub secret and never exposed publicly, it's still better to avoid secrets when we can.",{"type":413,"tag":841,"props":8165,"children":8166},{"icon":4254},[8167],{"type":413,"tag":414,"props":8168,"children":8169},{},[8170],{"type":418,"value":8171},"That's precisely why when hosting applications in Azure, we use Managed Identities and IAM roles instead of relying on secrets. Yet, here we can't use Managed Identities for GitHub Actions pipelines.",{"type":413,"tag":414,"props":8173,"children":8174},{},[8175],{"type":418,"value":8176},"From a practical standpoint, depending on secrets can quickly become problematic as they expire and thus require rotation. Of course, you can set up alerting or automate secret rotation but that's something you would prefer to avoid managing.",{"type":413,"tag":841,"props":8178,"children":8179},{"icon":843},[8180],{"type":413,"tag":414,"props":8181,"children":8182},{},[8183],{"type":418,"value":8184},"I recently encountered a situation in Azure DevOps where a deployment failed due to the expiration of an Azure AD Application secret associated with the Service Connection used in the pipeline, and we were not alerted about it. That's the kind of scenario that can easily happen with secrets and that you want to avoid.",{"type":413,"tag":414,"props":8186,"children":8187},{},[8188],{"type":418,"value":8189},"So what can we do about that?",{"type":413,"tag":414,"props":8191,"children":8192},{},[8193,8195,8200,8202,8209],{"type":418,"value":8194},"👉 We can stop using secret credentials and use ",{"type":413,"tag":813,"props":8196,"children":8198},{"href":3789,"rel":8197},[817],[8199],{"type":418,"value":3793},{"type":418,"value":8201}," instead. I suggest you have a look at this ",{"type":413,"tag":813,"props":8203,"children":8206},{"href":8204,"rel":8205},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect",[817],[8207],{"type":418,"value":8208},"GitHub documentation page",{"type":418,"value":8210}," as well to better understand how it works but basically, you can remember the following:",{"type":413,"tag":3766,"props":8212,"children":8213},{},[8214,8219,8224],{"type":413,"tag":2159,"props":8215,"children":8216},{},[8217],{"type":418,"value":8218},"this mechanism relies on Open ID Connect and trust between Azure and GitHub",{"type":413,"tag":2159,"props":8220,"children":8221},{},[8222],{"type":418,"value":8223},"the GitHub pipeline does not need an Azure AD application secret anymore to authenticate to Azure",{"type":413,"tag":2159,"props":8225,"children":8226},{},[8227],{"type":418,"value":8228},"it's not an Azure thing only, it's an open standard that also works with other cloud providers and other platforms than Github",{"type":413,"tag":414,"props":8230,"children":8231},{},[8232,8234,8239,8241,8247],{"type":418,"value":8233},"To establish the trust relationship between the Azure AD application and the GitHub repository, a ",{"type":413,"tag":4008,"props":8235,"children":8236},{},[8237],{"type":418,"value":8238},"Federated Identity Credential",{"type":418,"value":8240}," must be created in the Azure Active Directory. You can find how to do that manually from the portal in the ",{"type":413,"tag":813,"props":8242,"children":8245},{"href":8243,"rel":8244},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp",[817],[8246],{"type":418,"value":1945},{"type":418,"value":8248}," but we are going to directly automate that 😉.",{"type":413,"tag":866,"props":8250,"children":8252},{"id":8251},"the-complete-solution-to-implement",[8253],{"type":418,"value":8254},"The complete solution to implement",{"type":413,"tag":414,"props":8256,"children":8257},{},[8258],{"type":413,"tag":832,"props":8259,"children":8262},{"alt":834,"className":8260,"src":8261},[836,837],"/posts/images/azurereadygithub_overview_2.webp",[],{"type":413,"tag":420,"props":8264,"children":8266},{"id":8265},"why-use-pulumi-in-that-context",[8267],{"type":418,"value":8268},"Why use Pulumi in that context?",{"type":413,"tag":414,"props":8270,"children":8271},{},[8272],{"type":418,"value":8273},"You might wonder why I chose to automate this process using Pulumi instead of writing a Bash or PowerShell script that would execute commands from the GitHub CLI and the Azure CLI.",{"type":413,"tag":841,"props":8275,"children":8276},{"icon":1103},[8277],{"type":413,"tag":414,"props":8278,"children":8279},{},[8280,8282,8287,8289,8294],{"type":418,"value":8281},"By the way, you should check ",{"type":413,"tag":813,"props":8283,"children":8285},{"href":906,"rel":8284},[817],[8286],{"type":418,"value":379},{"type":418,"value":8288}," if you have not done it yet, it's very handy. And if you have read my article about ",{"type":413,"tag":813,"props":8290,"children":8292},{"href":1382,"rel":8291},[817],[8293],{"type":418,"value":225},{"type":418,"value":8295},", you know it's a very convenient tool as well.",{"type":413,"tag":414,"props":8297,"children":8298},{},[8299],{"type":418,"value":8300},"I think Pulumi is a better choice here because:",{"type":413,"tag":3766,"props":8302,"children":8303},{},[8304,8309,8314,8319],{"type":413,"tag":2159,"props":8305,"children":8306},{},[8307],{"type":418,"value":8308},"a script is imperative by nature, but declarative infrastructure seems more suitable to avoid dealing with idempotency",{"type":413,"tag":2159,"props":8310,"children":8311},{},[8312],{"type":418,"value":8313},"Pulumi can interact with both GitHub and Azure using its providers",{"type":413,"tag":2159,"props":8315,"children":8316},{},[8317],{"type":418,"value":8318},"the code will be easier to write and maintain",{"type":413,"tag":2159,"props":8320,"children":8321},{},[8322],{"type":418,"value":8323},"the code could be integrated into any application (including a future self-service infrastructure portal) using Pulumi Automation API",{"type":413,"tag":414,"props":8325,"children":8326},{},[8327],{"type":418,"value":8328},"In this article, the Pulumi code will be in TypeScript but it would work in any language supported by Pulumi.",{"type":413,"tag":420,"props":8330,"children":8332},{"id":8331},"automate-the-creation-of-the-azure-ready-github-repository",[8333],{"type":418,"value":8334},"Automate the creation of the Azure-Ready GitHub Repository",{"type":413,"tag":866,"props":8336,"children":8338},{"id":8337},"create-the-pulumi-project",[8339],{"type":418,"value":8340},"Create the Pulumi project",{"type":413,"tag":414,"props":8342,"children":8343},{},[8344],{"type":418,"value":8345},"Let's start by scaffolding a new Pulumi project using TypeScript:",{"type":413,"tag":437,"props":8347,"children":8349},{"className":1013,"code":8348,"language":248,"meta":401,"style":401},"pulumi new typescript -n AzureOIDC -s dev -d \"A program to set up an Azure-Ready GitHub repository\"\n",[8350],{"type":413,"tag":444,"props":8351,"children":8352},{"__ignoreMap":401},[8353],{"type":413,"tag":448,"props":8354,"children":8355},{"class":450,"line":451},[8356,8361,8365,8370,8374,8379,8383,8388,8392,8397],{"type":413,"tag":448,"props":8357,"children":8358},{"style":1029},[8359],{"type":418,"value":8360},"pulumi new typescript ",{"type":413,"tag":448,"props":8362,"children":8363},{"style":461},[8364],{"type":418,"value":1173},{"type":413,"tag":448,"props":8366,"children":8367},{"style":1029},[8368],{"type":418,"value":8369},"n AzureOIDC ",{"type":413,"tag":448,"props":8371,"children":8372},{"style":461},[8373],{"type":418,"value":1173},{"type":413,"tag":448,"props":8375,"children":8376},{"style":1029},[8377],{"type":418,"value":8378},"s dev ",{"type":413,"tag":448,"props":8380,"children":8381},{"style":461},[8382],{"type":418,"value":1173},{"type":413,"tag":448,"props":8384,"children":8385},{"style":1029},[8386],{"type":418,"value":8387},"d ",{"type":413,"tag":448,"props":8389,"children":8390},{"style":461},[8391],{"type":418,"value":1183},{"type":413,"tag":448,"props":8393,"children":8394},{"style":467},[8395],{"type":418,"value":8396},"A program to set up an Azure-Ready GitHub repository",{"type":413,"tag":448,"props":8398,"children":8399},{"style":461},[8400],{"type":418,"value":1005},{"type":413,"tag":414,"props":8402,"children":8403},{},[8404],{"type":418,"value":8405},"This command creates a new pulumi project and stack from the TypeScript template:",{"type":413,"tag":3766,"props":8407,"children":8408},{},[8409,8426,8441],{"type":413,"tag":2159,"props":8410,"children":8411},{},[8412,8413,8418,8420,8425],{"type":418,"value":4006},{"type":413,"tag":4008,"props":8414,"children":8415},{},[8416],{"type":418,"value":8417},"AzureOIDC\"",{"type":418,"value":8419}," is specified using the ",{"type":413,"tag":444,"props":8421,"children":8423},{"className":8422},[],[8424],{"type":418,"value":4020},{"type":418,"value":4022},{"type":413,"tag":2159,"props":8427,"children":8428},{},[8429,8430,8434,8435,8440],{"type":418,"value":4027},{"type":413,"tag":4008,"props":8431,"children":8432},{},[8433],{"type":418,"value":8396},{"type":418,"value":4014},{"type":413,"tag":444,"props":8436,"children":8438},{"className":8437},[],[8439],{"type":418,"value":4038},{"type":418,"value":4022},{"type":413,"tag":2159,"props":8442,"children":8443},{},[8444,8445,8449,8450,8455],{"type":418,"value":4044},{"type":413,"tag":4008,"props":8446,"children":8447},{},[8448],{"type":418,"value":4049},{"type":418,"value":4014},{"type":413,"tag":444,"props":8451,"children":8453},{"className":8452},[],[8454],{"type":418,"value":4056},{"type":418,"value":4022},{"type":413,"tag":841,"props":8457,"children":8458},{"icon":3815},[8459],{"type":413,"tag":414,"props":8460,"children":8461},{},[8462,8464,8470,8472,8478,8480,8485,8487,8493],{"type":418,"value":8463},"By default, the ",{"type":413,"tag":444,"props":8465,"children":8467},{"className":8466},[],[8468],{"type":418,"value":8469},"pulumi new",{"type":418,"value":8471}," command installs the dependencies when creating the project. You can prevent this by specifying the ",{"type":413,"tag":444,"props":8473,"children":8475},{"className":8474},[],[8476],{"type":418,"value":8477},"-g",{"type":418,"value":8479}," option, which is useful when you want to use another package manager than the default one (",{"type":413,"tag":444,"props":8481,"children":8483},{"className":8482},[],[8484],{"type":418,"value":362},{"type":418,"value":8486}," instead of ",{"type":413,"tag":444,"props":8488,"children":8490},{"className":8489},[],[8491],{"type":418,"value":8492},"npm",{"type":418,"value":8494}," for instance).",{"type":413,"tag":414,"props":8496,"children":8497},{},[8498],{"type":418,"value":4062},{"type":413,"tag":3766,"props":8500,"children":8501},{},[8502,8511,8520],{"type":413,"tag":2159,"props":8503,"children":8504},{},[8505,8506],{"type":418,"value":4070},{"type":413,"tag":813,"props":8507,"children":8509},{"href":4073,"rel":8508},[817],[8510],{"type":418,"value":4077},{"type":413,"tag":2159,"props":8512,"children":8513},{},[8514,8515],{"type":418,"value":4070},{"type":413,"tag":813,"props":8516,"children":8518},{"href":4084,"rel":8517},[817],[8519],{"type":418,"value":4088},{"type":413,"tag":2159,"props":8521,"children":8522},{},[8523,8524],{"type":418,"value":4070},{"type":413,"tag":813,"props":8525,"children":8528},{"href":8526,"rel":8527},"https://www.pulumi.com/registry/packages/github/",[817],[8529],{"type":418,"value":8530},"GitHub provider",{"type":413,"tag":414,"props":8532,"children":8533},{},[8534,8536,8542],{"type":418,"value":8535},"So we can add the following packages to our ",{"type":413,"tag":444,"props":8537,"children":8539},{"className":8538},[],[8540],{"type":418,"value":8541},"package.json",{"type":418,"value":8543}," file:",{"type":413,"tag":3766,"props":8545,"children":8546},{},[8547,8552,8557],{"type":413,"tag":2159,"props":8548,"children":8549},{},[8550],{"type":418,"value":8551},"@pulumi/azure-native",{"type":413,"tag":2159,"props":8553,"children":8554},{},[8555],{"type":418,"value":8556},"@pulumi/azuread",{"type":413,"tag":2159,"props":8558,"children":8559},{},[8560],{"type":418,"value":8561},"@pulumi/github",{"type":413,"tag":866,"props":8563,"children":8564},{"id":913},[8565],{"type":418,"value":916},{"type":413,"tag":414,"props":8567,"children":8568},{},[8569,8571,8578,8580,8587],{"type":418,"value":8570},"To use the GitHub provider, we have to provide GitHub credentials. For that, we can create a personal access token (I prefer to create a ",{"type":413,"tag":813,"props":8572,"children":8575},{"href":8573,"rel":8574},"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#fine-grained-personal-access-tokens",[817],[8576],{"type":418,"value":8577},"fine-grained personal access token",{"type":418,"value":8579}," although a ",{"type":413,"tag":813,"props":8581,"children":8584},{"href":8582,"rel":8583},"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic",[817],[8585],{"type":418,"value":8586},"classic personal access token",{"type":418,"value":8588}," would also work). Next, we simply set the GitHub token in our Pulumi configuration, and the GitHub provider will automatically use it:",{"type":413,"tag":437,"props":8590,"children":8592},{"className":1013,"code":8591,"language":248,"meta":401,"style":401},"pulumi config set github:token XXXXXXXXXXXXXX --secret\n",[8593],{"type":413,"tag":444,"props":8594,"children":8595},{"__ignoreMap":401},[8596],{"type":413,"tag":448,"props":8597,"children":8598},{"class":450,"line":451},[8599,8604,8608],{"type":413,"tag":448,"props":8600,"children":8601},{"style":1029},[8602],{"type":418,"value":8603},"pulumi config set github:token XXXXXXXXXXXXXX ",{"type":413,"tag":448,"props":8605,"children":8606},{"style":461},[8607],{"type":418,"value":1071},{"type":413,"tag":448,"props":8609,"children":8610},{"style":1029},[8611],{"type":418,"value":8612},"secret\n",{"type":413,"tag":841,"props":8614,"children":8615},{"icon":4254},[8616],{"type":413,"tag":414,"props":8617,"children":8618},{},[8619,8621,8626],{"type":418,"value":8620},"Don't forget to include the ",{"type":413,"tag":444,"props":8622,"children":8624},{"className":8623},[],[8625],{"type":418,"value":4266},{"type":418,"value":8627}," option when setting sensitive configurations, as this ensures that Pulumi encrypts the information. By doing so, we can safely commit the configuration files without creating security risks.",{"type":413,"tag":414,"props":8629,"children":8630},{},[8631],{"type":418,"value":8632},"Now, it's time to create our GitHub repository!",{"type":413,"tag":437,"props":8634,"children":8637},{"className":8635,"code":8636,"language":357,"meta":401,"style":401},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import * as github from \"@pulumi/github\";\n\nconst repository = new github.Repository(\"azure-ready-repository\", {\n  name: \"azure-ready-repository\",\n  visibility: \"public\",\n  autoInit: true\n});\n\nexport const repositoryCloneUrl = repository.httpCloneUrl;\n",[8638],{"type":413,"tag":444,"props":8639,"children":8640},{"__ignoreMap":401},[8641,8685,8692,8753,8781,8810,8827,8842,8849],{"type":413,"tag":448,"props":8642,"children":8643},{"class":450,"line":451},[8644,8649,8654,8659,8664,8669,8673,8677,8681],{"type":413,"tag":448,"props":8645,"children":8646},{"style":785},[8647],{"type":418,"value":8648},"import",{"type":413,"tag":448,"props":8650,"children":8651},{"style":461},[8652],{"type":418,"value":8653}," *",{"type":413,"tag":448,"props":8655,"children":8656},{"style":785},[8657],{"type":418,"value":8658}," as",{"type":413,"tag":448,"props":8660,"children":8661},{"style":1029},[8662],{"type":418,"value":8663}," github ",{"type":413,"tag":448,"props":8665,"children":8666},{"style":785},[8667],{"type":418,"value":8668},"from",{"type":413,"tag":448,"props":8670,"children":8671},{"style":461},[8672],{"type":418,"value":995},{"type":413,"tag":448,"props":8674,"children":8675},{"style":467},[8676],{"type":418,"value":8561},{"type":413,"tag":448,"props":8678,"children":8679},{"style":461},[8680],{"type":418,"value":1183},{"type":413,"tag":448,"props":8682,"children":8683},{"style":461},[8684],{"type":418,"value":5802},{"type":413,"tag":448,"props":8686,"children":8687},{"class":450,"line":473},[8688],{"type":413,"tag":448,"props":8689,"children":8690},{"emptyLinePlaceholder":505},[8691],{"type":418,"value":508},{"type":413,"tag":448,"props":8693,"children":8694},{"class":450,"line":488},[8695,8700,8705,8709,8713,8718,8722,8727,8731,8735,8740,8744,8748],{"type":413,"tag":448,"props":8696,"children":8697},{"style":6130},[8698],{"type":418,"value":8699},"const",{"type":413,"tag":448,"props":8701,"children":8702},{"style":1029},[8703],{"type":418,"value":8704}," repository ",{"type":413,"tag":448,"props":8706,"children":8707},{"style":461},[8708],{"type":418,"value":1037},{"type":413,"tag":448,"props":8710,"children":8711},{"style":461},[8712],{"type":418,"value":3943},{"type":413,"tag":448,"props":8714,"children":8715},{"style":1029},[8716],{"type":418,"value":8717}," github",{"type":413,"tag":448,"props":8719,"children":8720},{"style":461},[8721],{"type":418,"value":898},{"type":413,"tag":448,"props":8723,"children":8724},{"style":2000},[8725],{"type":418,"value":8726},"Repository",{"type":413,"tag":448,"props":8728,"children":8729},{"style":1029},[8730],{"type":418,"value":2041},{"type":413,"tag":448,"props":8732,"children":8733},{"style":461},[8734],{"type":418,"value":1183},{"type":413,"tag":448,"props":8736,"children":8737},{"style":467},[8738],{"type":418,"value":8739},"azure-ready-repository",{"type":413,"tag":448,"props":8741,"children":8742},{"style":461},[8743],{"type":418,"value":1183},{"type":413,"tag":448,"props":8745,"children":8746},{"style":461},[8747],{"type":418,"value":2059},{"type":413,"tag":448,"props":8749,"children":8750},{"style":461},[8751],{"type":418,"value":8752}," {\n",{"type":413,"tag":448,"props":8754,"children":8755},{"class":450,"line":501},[8756,8761,8765,8769,8773,8777],{"type":413,"tag":448,"props":8757,"children":8758},{"style":455},[8759],{"type":418,"value":8760},"  name",{"type":413,"tag":448,"props":8762,"children":8763},{"style":461},[8764],{"type":418,"value":464},{"type":413,"tag":448,"props":8766,"children":8767},{"style":461},[8768],{"type":418,"value":995},{"type":413,"tag":448,"props":8770,"children":8771},{"style":467},[8772],{"type":418,"value":8739},{"type":413,"tag":448,"props":8774,"children":8775},{"style":461},[8776],{"type":418,"value":1183},{"type":413,"tag":448,"props":8778,"children":8779},{"style":461},[8780],{"type":418,"value":4378},{"type":413,"tag":448,"props":8782,"children":8783},{"class":450,"line":511},[8784,8789,8793,8797,8802,8806],{"type":413,"tag":448,"props":8785,"children":8786},{"style":455},[8787],{"type":418,"value":8788},"  visibility",{"type":413,"tag":448,"props":8790,"children":8791},{"style":461},[8792],{"type":418,"value":464},{"type":413,"tag":448,"props":8794,"children":8795},{"style":461},[8796],{"type":418,"value":995},{"type":413,"tag":448,"props":8798,"children":8799},{"style":467},[8800],{"type":418,"value":8801},"public",{"type":413,"tag":448,"props":8803,"children":8804},{"style":461},[8805],{"type":418,"value":1183},{"type":413,"tag":448,"props":8807,"children":8808},{"style":461},[8809],{"type":418,"value":4378},{"type":413,"tag":448,"props":8811,"children":8812},{"class":450,"line":524},[8813,8818,8822],{"type":413,"tag":448,"props":8814,"children":8815},{"style":455},[8816],{"type":418,"value":8817},"  autoInit",{"type":413,"tag":448,"props":8819,"children":8820},{"style":461},[8821],{"type":418,"value":464},{"type":413,"tag":448,"props":8823,"children":8824},{"style":477},[8825],{"type":418,"value":8826}," true\n",{"type":413,"tag":448,"props":8828,"children":8829},{"class":450,"line":542},[8830,8834,8838],{"type":413,"tag":448,"props":8831,"children":8832},{"style":461},[8833],{"type":418,"value":1825},{"type":413,"tag":448,"props":8835,"children":8836},{"style":1029},[8837],{"type":418,"value":2031},{"type":413,"tag":448,"props":8839,"children":8840},{"style":461},[8841],{"type":418,"value":5802},{"type":413,"tag":448,"props":8843,"children":8844},{"class":450,"line":560},[8845],{"type":413,"tag":448,"props":8846,"children":8847},{"emptyLinePlaceholder":505},[8848],{"type":418,"value":508},{"type":413,"tag":448,"props":8850,"children":8851},{"class":450,"line":573},[8852,8857,8862,8867,8871,8875,8879,8884],{"type":413,"tag":448,"props":8853,"children":8854},{"style":785},[8855],{"type":418,"value":8856},"export",{"type":413,"tag":448,"props":8858,"children":8859},{"style":6130},[8860],{"type":418,"value":8861}," const",{"type":413,"tag":448,"props":8863,"children":8864},{"style":1029},[8865],{"type":418,"value":8866}," repositoryCloneUrl ",{"type":413,"tag":448,"props":8868,"children":8869},{"style":461},[8870],{"type":418,"value":1037},{"type":413,"tag":448,"props":8872,"children":8873},{"style":1029},[8874],{"type":418,"value":4675},{"type":413,"tag":448,"props":8876,"children":8877},{"style":461},[8878],{"type":418,"value":898},{"type":413,"tag":448,"props":8880,"children":8881},{"style":1029},[8882],{"type":418,"value":8883},"httpCloneUrl",{"type":413,"tag":448,"props":8885,"children":8886},{"style":461},[8887],{"type":418,"value":5802},{"type":413,"tag":414,"props":8889,"children":8890},{},[8891,8893,8900,8902,8907],{"type":418,"value":8892},"Pulumi has an ",{"type":413,"tag":813,"props":8894,"children":8897},{"href":8895,"rel":8896},"https://www.pulumi.com/docs/concepts/resources/names/#autonaming",[817],[8898],{"type":418,"value":8899},"auto-naming capability",{"type":418,"value":8901}," that is very convenient to prevent name collisions or to ensure zero-downtime resource updates. Yet, in this context, I prefer to avoid a random suffix in my GitHub repository name, that's why I am specifying the ",{"type":413,"tag":444,"props":8903,"children":8905},{"className":8904},[],[8906],{"type":418,"value":458},{"type":418,"value":8908}," property to override the auto-naming behavior.",{"type":413,"tag":414,"props":8910,"children":8911},{},[8912,8914,8921,8923,8929],{"type":418,"value":8913},"The last line creates a stack ",{"type":413,"tag":813,"props":8915,"children":8918},{"href":8916,"rel":8917},"https://www.pulumi.com/docs/concepts/stack/#outputs",[817],[8919],{"type":418,"value":8920},"output",{"type":418,"value":8922}," named ",{"type":413,"tag":444,"props":8924,"children":8926},{"className":8925},[],[8927],{"type":418,"value":8928},"repositoryCloneUrl",{"type":418,"value":8930}," so that we can easily get the URL to clone our newly created repository.",{"type":413,"tag":841,"props":8932,"children":8933},{"icon":3815},[8934],{"type":413,"tag":414,"props":8935,"children":8936},{},[8937,8939,8945,8947,8953,8955,8961],{"type":418,"value":8938},"I wanted the repository to be initialized, that's why I set the ",{"type":413,"tag":444,"props":8940,"children":8942},{"className":8941},[],[8943],{"type":418,"value":8944},"autoInit",{"type":418,"value":8946}," property to ",{"type":413,"tag":444,"props":8948,"children":8950},{"className":8949},[],[8951],{"type":418,"value":8952},"true",{"type":418,"value":8954}," but you should set it to ",{"type":413,"tag":444,"props":8956,"children":8958},{"className":8957},[],[8959],{"type":418,"value":8960},"false",{"type":418,"value":8962}," if you have an existing local git repository that you want to push on this GitHub repository.",{"type":413,"tag":866,"props":8964,"children":8966},{"id":8965},"create-the-identity-in-azure-active-directory-for-the-github-actions-workflow",[8967,8969,8973],{"type":418,"value":8968},"Create the ",{"type":413,"tag":4008,"props":8970,"children":8971},{},[8972],{"type":418,"value":8100},{"type":418,"value":8974}," in Azure Active Directory for the GitHub Actions workflow",{"type":413,"tag":414,"props":8976,"children":8977},{},[8978],{"type":418,"value":8979},"Creating an Azure AD application and its service principal is not very complicated:",{"type":413,"tag":437,"props":8981,"children":8983},{"className":8635,"code":8982,"language":357,"meta":401,"style":401},"import * as azuread from \"@pulumi/azuread\";\n\nconst aadApplication = new azuread.Application(\"AzureReadyApp\", { displayName: \"Azure Ready App\" });\nconst servicePrincipal = new azuread.ServicePrincipal(\"AzureReadServicePrincipal\", {\n  applicationId: aadApplication.applicationId,\n});\n",[8984],{"type":413,"tag":444,"props":8985,"children":8986},{"__ignoreMap":401},[8987,9027,9034,9129,9186,9215],{"type":413,"tag":448,"props":8988,"children":8989},{"class":450,"line":451},[8990,8994,8998,9002,9007,9011,9015,9019,9023],{"type":413,"tag":448,"props":8991,"children":8992},{"style":785},[8993],{"type":418,"value":8648},{"type":413,"tag":448,"props":8995,"children":8996},{"style":461},[8997],{"type":418,"value":8653},{"type":413,"tag":448,"props":8999,"children":9000},{"style":785},[9001],{"type":418,"value":8658},{"type":413,"tag":448,"props":9003,"children":9004},{"style":1029},[9005],{"type":418,"value":9006}," azuread ",{"type":413,"tag":448,"props":9008,"children":9009},{"style":785},[9010],{"type":418,"value":8668},{"type":413,"tag":448,"props":9012,"children":9013},{"style":461},[9014],{"type":418,"value":995},{"type":413,"tag":448,"props":9016,"children":9017},{"style":467},[9018],{"type":418,"value":8556},{"type":413,"tag":448,"props":9020,"children":9021},{"style":461},[9022],{"type":418,"value":1183},{"type":413,"tag":448,"props":9024,"children":9025},{"style":461},[9026],{"type":418,"value":5802},{"type":413,"tag":448,"props":9028,"children":9029},{"class":450,"line":473},[9030],{"type":413,"tag":448,"props":9031,"children":9032},{"emptyLinePlaceholder":505},[9033],{"type":418,"value":508},{"type":413,"tag":448,"props":9035,"children":9036},{"class":450,"line":488},[9037,9041,9046,9050,9054,9059,9063,9068,9072,9076,9081,9085,9089,9094,9099,9103,9107,9112,9116,9121,9125],{"type":413,"tag":448,"props":9038,"children":9039},{"style":6130},[9040],{"type":418,"value":8699},{"type":413,"tag":448,"props":9042,"children":9043},{"style":1029},[9044],{"type":418,"value":9045}," aadApplication ",{"type":413,"tag":448,"props":9047,"children":9048},{"style":461},[9049],{"type":418,"value":1037},{"type":413,"tag":448,"props":9051,"children":9052},{"style":461},[9053],{"type":418,"value":3943},{"type":413,"tag":448,"props":9055,"children":9056},{"style":1029},[9057],{"type":418,"value":9058}," azuread",{"type":413,"tag":448,"props":9060,"children":9061},{"style":461},[9062],{"type":418,"value":898},{"type":413,"tag":448,"props":9064,"children":9065},{"style":2000},[9066],{"type":418,"value":9067},"Application",{"type":413,"tag":448,"props":9069,"children":9070},{"style":1029},[9071],{"type":418,"value":2041},{"type":413,"tag":448,"props":9073,"children":9074},{"style":461},[9075],{"type":418,"value":1183},{"type":413,"tag":448,"props":9077,"children":9078},{"style":467},[9079],{"type":418,"value":9080},"AzureReadyApp",{"type":413,"tag":448,"props":9082,"children":9083},{"style":461},[9084],{"type":418,"value":1183},{"type":413,"tag":448,"props":9086,"children":9087},{"style":461},[9088],{"type":418,"value":2059},{"type":413,"tag":448,"props":9090,"children":9091},{"style":461},[9092],{"type":418,"value":9093}," {",{"type":413,"tag":448,"props":9095,"children":9096},{"style":455},[9097],{"type":418,"value":9098}," displayName",{"type":413,"tag":448,"props":9100,"children":9101},{"style":461},[9102],{"type":418,"value":464},{"type":413,"tag":448,"props":9104,"children":9105},{"style":461},[9106],{"type":418,"value":995},{"type":413,"tag":448,"props":9108,"children":9109},{"style":467},[9110],{"type":418,"value":9111},"Azure Ready App",{"type":413,"tag":448,"props":9113,"children":9114},{"style":461},[9115],{"type":418,"value":1183},{"type":413,"tag":448,"props":9117,"children":9118},{"style":461},[9119],{"type":418,"value":9120}," }",{"type":413,"tag":448,"props":9122,"children":9123},{"style":1029},[9124],{"type":418,"value":2031},{"type":413,"tag":448,"props":9126,"children":9127},{"style":461},[9128],{"type":418,"value":5802},{"type":413,"tag":448,"props":9130,"children":9131},{"class":450,"line":501},[9132,9136,9141,9145,9149,9153,9157,9161,9165,9169,9174,9178,9182],{"type":413,"tag":448,"props":9133,"children":9134},{"style":6130},[9135],{"type":418,"value":8699},{"type":413,"tag":448,"props":9137,"children":9138},{"style":1029},[9139],{"type":418,"value":9140}," servicePrincipal ",{"type":413,"tag":448,"props":9142,"children":9143},{"style":461},[9144],{"type":418,"value":1037},{"type":413,"tag":448,"props":9146,"children":9147},{"style":461},[9148],{"type":418,"value":3943},{"type":413,"tag":448,"props":9150,"children":9151},{"style":1029},[9152],{"type":418,"value":9058},{"type":413,"tag":448,"props":9154,"children":9155},{"style":461},[9156],{"type":418,"value":898},{"type":413,"tag":448,"props":9158,"children":9159},{"style":2000},[9160],{"type":418,"value":6224},{"type":413,"tag":448,"props":9162,"children":9163},{"style":1029},[9164],{"type":418,"value":2041},{"type":413,"tag":448,"props":9166,"children":9167},{"style":461},[9168],{"type":418,"value":1183},{"type":413,"tag":448,"props":9170,"children":9171},{"style":467},[9172],{"type":418,"value":9173},"AzureReadServicePrincipal",{"type":413,"tag":448,"props":9175,"children":9176},{"style":461},[9177],{"type":418,"value":1183},{"type":413,"tag":448,"props":9179,"children":9180},{"style":461},[9181],{"type":418,"value":2059},{"type":413,"tag":448,"props":9183,"children":9184},{"style":461},[9185],{"type":418,"value":8752},{"type":413,"tag":448,"props":9187,"children":9188},{"class":450,"line":511},[9189,9194,9198,9202,9206,9211],{"type":413,"tag":448,"props":9190,"children":9191},{"style":455},[9192],{"type":418,"value":9193},"  applicationId",{"type":413,"tag":448,"props":9195,"children":9196},{"style":461},[9197],{"type":418,"value":464},{"type":413,"tag":448,"props":9199,"children":9200},{"style":1029},[9201],{"type":418,"value":5893},{"type":413,"tag":448,"props":9203,"children":9204},{"style":461},[9205],{"type":418,"value":898},{"type":413,"tag":448,"props":9207,"children":9208},{"style":1029},[9209],{"type":418,"value":9210},"applicationId",{"type":413,"tag":448,"props":9212,"children":9213},{"style":461},[9214],{"type":418,"value":4378},{"type":413,"tag":448,"props":9216,"children":9217},{"class":450,"line":524},[9218,9222,9226],{"type":413,"tag":448,"props":9219,"children":9220},{"style":461},[9221],{"type":418,"value":1825},{"type":413,"tag":448,"props":9223,"children":9224},{"style":1029},[9225],{"type":418,"value":2031},{"type":413,"tag":448,"props":9227,"children":9228},{"style":461},[9229],{"type":418,"value":5802},{"type":413,"tag":414,"props":9231,"children":9232},{},[9233,9235,9244],{"type":418,"value":9234},"The OIDC trust thing is a bit more complex. Fortunately, Microsoft's documentation has a detailed page ",{"type":413,"tag":813,"props":9236,"children":9238},{"href":8243,"rel":9237},[817],[9239],{"type":413,"tag":4008,"props":9240,"children":9241},{},[9242],{"type":418,"value":9243},"Configuring an app to trust an external identity provider",{"type":418,"value":9245}," that explains everything and shows how to add a federated identity for GitHub Actions using the Azure Portal, Azure CLI, or Azure PowerShell.",{"type":413,"tag":414,"props":9247,"children":9248},{},[9249],{"type":418,"value":9250},"Let's do the same thing using TypeScript and Pulumi Azure AD provider:",{"type":413,"tag":437,"props":9252,"children":9254},{"className":8635,"code":9253,"language":357,"meta":401,"style":401},"new azuread.ApplicationFederatedIdentityCredential(\"AzureReadyAppFederatedIdentityCredential\", {\n  applicationObjectId: aadApplication.objectId,\n  displayName: \"AzureReadyDeploys\",\n  description: \"Deployments for azure-ready-repository\",\n  audiences: [\"api://AzureADTokenExchange\"],\n  issuer: \"https://token.actions.githubusercontent.com\",\n  subject: pulumi.interpolate`repo:${repository.fullName}:ref:refs/heads/main`,\n});\n",[9255],{"type":413,"tag":444,"props":9256,"children":9257},{"__ignoreMap":401},[9258,9303,9332,9360,9388,9425,9453,9522],{"type":413,"tag":448,"props":9259,"children":9260},{"class":450,"line":451},[9261,9265,9269,9273,9278,9282,9286,9291,9295,9299],{"type":413,"tag":448,"props":9262,"children":9263},{"style":461},[9264],{"type":418,"value":6133},{"type":413,"tag":448,"props":9266,"children":9267},{"style":1029},[9268],{"type":418,"value":9058},{"type":413,"tag":448,"props":9270,"children":9271},{"style":461},[9272],{"type":418,"value":898},{"type":413,"tag":448,"props":9274,"children":9275},{"style":2000},[9276],{"type":418,"value":9277},"ApplicationFederatedIdentityCredential",{"type":413,"tag":448,"props":9279,"children":9280},{"style":1029},[9281],{"type":418,"value":2041},{"type":413,"tag":448,"props":9283,"children":9284},{"style":461},[9285],{"type":418,"value":1183},{"type":413,"tag":448,"props":9287,"children":9288},{"style":467},[9289],{"type":418,"value":9290},"AzureReadyAppFederatedIdentityCredential",{"type":413,"tag":448,"props":9292,"children":9293},{"style":461},[9294],{"type":418,"value":1183},{"type":413,"tag":448,"props":9296,"children":9297},{"style":461},[9298],{"type":418,"value":2059},{"type":413,"tag":448,"props":9300,"children":9301},{"style":461},[9302],{"type":418,"value":8752},{"type":413,"tag":448,"props":9304,"children":9305},{"class":450,"line":473},[9306,9311,9315,9319,9323,9328],{"type":413,"tag":448,"props":9307,"children":9308},{"style":455},[9309],{"type":418,"value":9310},"  applicationObjectId",{"type":413,"tag":448,"props":9312,"children":9313},{"style":461},[9314],{"type":418,"value":464},{"type":413,"tag":448,"props":9316,"children":9317},{"style":1029},[9318],{"type":418,"value":5893},{"type":413,"tag":448,"props":9320,"children":9321},{"style":461},[9322],{"type":418,"value":898},{"type":413,"tag":448,"props":9324,"children":9325},{"style":1029},[9326],{"type":418,"value":9327},"objectId",{"type":413,"tag":448,"props":9329,"children":9330},{"style":461},[9331],{"type":418,"value":4378},{"type":413,"tag":448,"props":9333,"children":9334},{"class":450,"line":488},[9335,9340,9344,9348,9352,9356],{"type":413,"tag":448,"props":9336,"children":9337},{"style":455},[9338],{"type":418,"value":9339},"  displayName",{"type":413,"tag":448,"props":9341,"children":9342},{"style":461},[9343],{"type":418,"value":464},{"type":413,"tag":448,"props":9345,"children":9346},{"style":461},[9347],{"type":418,"value":995},{"type":413,"tag":448,"props":9349,"children":9350},{"style":467},[9351],{"type":418,"value":6444},{"type":413,"tag":448,"props":9353,"children":9354},{"style":461},[9355],{"type":418,"value":1183},{"type":413,"tag":448,"props":9357,"children":9358},{"style":461},[9359],{"type":418,"value":4378},{"type":413,"tag":448,"props":9361,"children":9362},{"class":450,"line":501},[9363,9368,9372,9376,9380,9384],{"type":413,"tag":448,"props":9364,"children":9365},{"style":455},[9366],{"type":418,"value":9367},"  description",{"type":413,"tag":448,"props":9369,"children":9370},{"style":461},[9371],{"type":418,"value":464},{"type":413,"tag":448,"props":9373,"children":9374},{"style":461},[9375],{"type":418,"value":995},{"type":413,"tag":448,"props":9377,"children":9378},{"style":467},[9379],{"type":418,"value":6472},{"type":413,"tag":448,"props":9381,"children":9382},{"style":461},[9383],{"type":418,"value":1183},{"type":413,"tag":448,"props":9385,"children":9386},{"style":461},[9387],{"type":418,"value":4378},{"type":413,"tag":448,"props":9389,"children":9390},{"class":450,"line":511},[9391,9396,9400,9405,9409,9413,9417,9421],{"type":413,"tag":448,"props":9392,"children":9393},{"style":455},[9394],{"type":418,"value":9395},"  audiences",{"type":413,"tag":448,"props":9397,"children":9398},{"style":461},[9399],{"type":418,"value":464},{"type":413,"tag":448,"props":9401,"children":9402},{"style":1029},[9403],{"type":418,"value":9404}," [",{"type":413,"tag":448,"props":9406,"children":9407},{"style":461},[9408],{"type":418,"value":1183},{"type":413,"tag":448,"props":9410,"children":9411},{"style":467},[9412],{"type":418,"value":1902},{"type":413,"tag":448,"props":9414,"children":9415},{"style":461},[9416],{"type":418,"value":1183},{"type":413,"tag":448,"props":9418,"children":9419},{"style":1029},[9420],{"type":418,"value":4428},{"type":413,"tag":448,"props":9422,"children":9423},{"style":461},[9424],{"type":418,"value":4378},{"type":413,"tag":448,"props":9426,"children":9427},{"class":450,"line":524},[9428,9433,9437,9441,9445,9449],{"type":413,"tag":448,"props":9429,"children":9430},{"style":455},[9431],{"type":418,"value":9432},"  issuer",{"type":413,"tag":448,"props":9434,"children":9435},{"style":461},[9436],{"type":418,"value":464},{"type":413,"tag":448,"props":9438,"children":9439},{"style":461},[9440],{"type":418,"value":995},{"type":413,"tag":448,"props":9442,"children":9443},{"style":467},[9444],{"type":418,"value":1787},{"type":413,"tag":448,"props":9446,"children":9447},{"style":461},[9448],{"type":418,"value":1183},{"type":413,"tag":448,"props":9450,"children":9451},{"style":461},[9452],{"type":418,"value":4378},{"type":413,"tag":448,"props":9454,"children":9455},{"class":450,"line":542},[9456,9461,9465,9470,9474,9479,9484,9488,9492,9497,9501,9506,9510,9514,9518],{"type":413,"tag":448,"props":9457,"children":9458},{"style":455},[9459],{"type":418,"value":9460},"  subject",{"type":413,"tag":448,"props":9462,"children":9463},{"style":461},[9464],{"type":418,"value":464},{"type":413,"tag":448,"props":9466,"children":9467},{"style":1029},[9468],{"type":418,"value":9469}," pulumi",{"type":413,"tag":448,"props":9471,"children":9472},{"style":461},[9473],{"type":418,"value":898},{"type":413,"tag":448,"props":9475,"children":9476},{"style":2000},[9477],{"type":418,"value":9478},"interpolate",{"type":413,"tag":448,"props":9480,"children":9481},{"style":461},[9482],{"type":418,"value":9483},"`",{"type":413,"tag":448,"props":9485,"children":9486},{"style":467},[9487],{"type":418,"value":1812},{"type":413,"tag":448,"props":9489,"children":9490},{"style":461},[9491],{"type":418,"value":1452},{"type":413,"tag":448,"props":9493,"children":9494},{"style":1029},[9495],{"type":418,"value":9496},"repository",{"type":413,"tag":448,"props":9498,"children":9499},{"style":461},[9500],{"type":418,"value":898},{"type":413,"tag":448,"props":9502,"children":9503},{"style":1029},[9504],{"type":418,"value":9505},"fullName",{"type":413,"tag":448,"props":9507,"children":9508},{"style":461},[9509],{"type":418,"value":1825},{"type":413,"tag":448,"props":9511,"children":9512},{"style":467},[9513],{"type":418,"value":1830},{"type":413,"tag":448,"props":9515,"children":9516},{"style":461},[9517],{"type":418,"value":9483},{"type":413,"tag":448,"props":9519,"children":9520},{"style":461},[9521],{"type":418,"value":4378},{"type":413,"tag":448,"props":9523,"children":9524},{"class":450,"line":560},[9525,9529,9533],{"type":413,"tag":448,"props":9526,"children":9527},{"style":461},[9528],{"type":418,"value":1825},{"type":413,"tag":448,"props":9530,"children":9531},{"style":1029},[9532],{"type":418,"value":2031},{"type":413,"tag":448,"props":9534,"children":9535},{"style":461},[9536],{"type":418,"value":5802},{"type":413,"tag":414,"props":9538,"children":9539},{},[9540,9541,9546,9548,9553,9555,9560],{"type":418,"value":1930},{"type":413,"tag":444,"props":9542,"children":9544},{"className":9543},[],[9545],{"type":418,"value":1936},{"type":418,"value":9547}," property is what identifies the repository where the GitHub Actions workflow will be authorized to exchange its GitHub token for an Azure access token. It's worth noting that it will only work if the GitHub Actions workflow is run on the git reference (branch or tag) or the environment you specify in ",{"type":413,"tag":444,"props":9549,"children":9551},{"className":9550},[],[9552],{"type":418,"value":1936},{"type":418,"value":9554},". You can also specify that only workflows triggered by a pull request should be authorized. Here, I have used the ",{"type":413,"tag":444,"props":9556,"children":9558},{"className":9557},[],[9559],{"type":418,"value":8035},{"type":418,"value":9561}," branch but I could create multiple Federated Identity Credentials with different subjects if needed.",{"type":413,"tag":414,"props":9563,"children":9564},{},[9565],{"type":418,"value":9566},"With this configuration, the GitHub Actions workflow we create next will be able to obtain a valid Azure access token.",{"type":413,"tag":414,"props":9568,"children":9569},{},[9570,9572,9579],{"type":418,"value":9571},"If you are interested in gaining a better understanding of how all this works, you can refer to ",{"type":413,"tag":813,"props":9573,"children":9576},{"href":9574,"rel":9575},"https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation#how-it-works",[817],[9577],{"type":418,"value":9578},"this diagram",{"type":418,"value":9580}," from Microsoft's documentation (with GitHub serving as the external identity provider in our case).",{"type":413,"tag":414,"props":9582,"children":9583},{},[9584],{"type":413,"tag":832,"props":9585,"children":9589},{"alt":9586,"className":9587,"src":9588},"Sequence diagram explaining Azure OIDC.",[836,837],"/posts/images/azurereadygithub_identityfederation.webp",[],{"type":413,"tag":866,"props":9591,"children":9593},{"id":9592},"authorize-the-service-principal-to-provision-resources-on-the-subscription",[9594],{"type":418,"value":9595},"Authorize the Service Principal to provision resources on the subscription",{"type":413,"tag":414,"props":9597,"children":9598},{},[9599],{"type":418,"value":9600},"We have created everything we need to get a valid Azure access token, but we still have not authorized the application to provision resources on our subscription.",{"type":413,"tag":414,"props":9602,"children":9603},{},[9604],{"type":418,"value":9605},"We can do that by giving the Contributor role to our service principal.",{"type":413,"tag":437,"props":9607,"children":9609},{"className":8635,"code":9608,"language":357,"meta":401,"style":401},"import * as authorization from \"@pulumi/azure-native/authorization\";\nimport { azureBuiltInRoles } from \"./builtInRoles\";\n\nnew authorization.RoleAssignment(\"contributor\", {\n  principalId: servicePrincipal.id,\n  principalType: authorization.PrincipalType.ServicePrincipal,\n  roleDefinitionId: azureBuiltInRoles.contributor,\n  scope: pulumi.interpolate`/subscriptions/${subscriptionId}`,\n});\n",[9610],{"type":413,"tag":444,"props":9611,"children":9612},{"__ignoreMap":401},[9613,9654,9696,9703,9748,9776,9813,9841,9890],{"type":413,"tag":448,"props":9614,"children":9615},{"class":450,"line":451},[9616,9620,9624,9628,9633,9637,9641,9646,9650],{"type":413,"tag":448,"props":9617,"children":9618},{"style":785},[9619],{"type":418,"value":8648},{"type":413,"tag":448,"props":9621,"children":9622},{"style":461},[9623],{"type":418,"value":8653},{"type":413,"tag":448,"props":9625,"children":9626},{"style":785},[9627],{"type":418,"value":8658},{"type":413,"tag":448,"props":9629,"children":9630},{"style":1029},[9631],{"type":418,"value":9632}," authorization ",{"type":413,"tag":448,"props":9634,"children":9635},{"style":785},[9636],{"type":418,"value":8668},{"type":413,"tag":448,"props":9638,"children":9639},{"style":461},[9640],{"type":418,"value":995},{"type":413,"tag":448,"props":9642,"children":9643},{"style":467},[9644],{"type":418,"value":9645},"@pulumi/azure-native/authorization",{"type":413,"tag":448,"props":9647,"children":9648},{"style":461},[9649],{"type":418,"value":1183},{"type":413,"tag":448,"props":9651,"children":9652},{"style":461},[9653],{"type":418,"value":5802},{"type":413,"tag":448,"props":9655,"children":9656},{"class":450,"line":473},[9657,9661,9665,9670,9674,9679,9683,9688,9692],{"type":413,"tag":448,"props":9658,"children":9659},{"style":785},[9660],{"type":418,"value":8648},{"type":413,"tag":448,"props":9662,"children":9663},{"style":461},[9664],{"type":418,"value":9093},{"type":413,"tag":448,"props":9666,"children":9667},{"style":1029},[9668],{"type":418,"value":9669}," azureBuiltInRoles",{"type":413,"tag":448,"props":9671,"children":9672},{"style":461},[9673],{"type":418,"value":9120},{"type":413,"tag":448,"props":9675,"children":9676},{"style":785},[9677],{"type":418,"value":9678}," from",{"type":413,"tag":448,"props":9680,"children":9681},{"style":461},[9682],{"type":418,"value":995},{"type":413,"tag":448,"props":9684,"children":9685},{"style":467},[9686],{"type":418,"value":9687},"./builtInRoles",{"type":413,"tag":448,"props":9689,"children":9690},{"style":461},[9691],{"type":418,"value":1183},{"type":413,"tag":448,"props":9693,"children":9694},{"style":461},[9695],{"type":418,"value":5802},{"type":413,"tag":448,"props":9697,"children":9698},{"class":450,"line":488},[9699],{"type":413,"tag":448,"props":9700,"children":9701},{"emptyLinePlaceholder":505},[9702],{"type":418,"value":508},{"type":413,"tag":448,"props":9704,"children":9705},{"class":450,"line":501},[9706,9710,9715,9719,9724,9728,9732,9736,9740,9744],{"type":413,"tag":448,"props":9707,"children":9708},{"style":461},[9709],{"type":418,"value":6133},{"type":413,"tag":448,"props":9711,"children":9712},{"style":1029},[9713],{"type":418,"value":9714}," authorization",{"type":413,"tag":448,"props":9716,"children":9717},{"style":461},[9718],{"type":418,"value":898},{"type":413,"tag":448,"props":9720,"children":9721},{"style":2000},[9722],{"type":418,"value":9723},"RoleAssignment",{"type":413,"tag":448,"props":9725,"children":9726},{"style":1029},[9727],{"type":418,"value":2041},{"type":413,"tag":448,"props":9729,"children":9730},{"style":461},[9731],{"type":418,"value":1183},{"type":413,"tag":448,"props":9733,"children":9734},{"style":467},[9735],{"type":418,"value":6151},{"type":413,"tag":448,"props":9737,"children":9738},{"style":461},[9739],{"type":418,"value":1183},{"type":413,"tag":448,"props":9741,"children":9742},{"style":461},[9743],{"type":418,"value":2059},{"type":413,"tag":448,"props":9745,"children":9746},{"style":461},[9747],{"type":418,"value":8752},{"type":413,"tag":448,"props":9749,"children":9750},{"class":450,"line":511},[9751,9756,9760,9764,9768,9772],{"type":413,"tag":448,"props":9752,"children":9753},{"style":455},[9754],{"type":418,"value":9755},"  principalId",{"type":413,"tag":448,"props":9757,"children":9758},{"style":461},[9759],{"type":418,"value":464},{"type":413,"tag":448,"props":9761,"children":9762},{"style":1029},[9763],{"type":418,"value":5358},{"type":413,"tag":448,"props":9765,"children":9766},{"style":461},[9767],{"type":418,"value":898},{"type":413,"tag":448,"props":9769,"children":9770},{"style":1029},[9771],{"type":418,"value":1285},{"type":413,"tag":448,"props":9773,"children":9774},{"style":461},[9775],{"type":418,"value":4378},{"type":413,"tag":448,"props":9777,"children":9778},{"class":450,"line":524},[9779,9784,9788,9792,9796,9801,9805,9809],{"type":413,"tag":448,"props":9780,"children":9781},{"style":455},[9782],{"type":418,"value":9783},"  principalType",{"type":413,"tag":448,"props":9785,"children":9786},{"style":461},[9787],{"type":418,"value":464},{"type":413,"tag":448,"props":9789,"children":9790},{"style":1029},[9791],{"type":418,"value":9714},{"type":413,"tag":448,"props":9793,"children":9794},{"style":461},[9795],{"type":418,"value":898},{"type":413,"tag":448,"props":9797,"children":9798},{"style":1029},[9799],{"type":418,"value":9800},"PrincipalType",{"type":413,"tag":448,"props":9802,"children":9803},{"style":461},[9804],{"type":418,"value":898},{"type":413,"tag":448,"props":9806,"children":9807},{"style":1029},[9808],{"type":418,"value":6224},{"type":413,"tag":448,"props":9810,"children":9811},{"style":461},[9812],{"type":418,"value":4378},{"type":413,"tag":448,"props":9814,"children":9815},{"class":450,"line":542},[9816,9821,9825,9829,9833,9837],{"type":413,"tag":448,"props":9817,"children":9818},{"style":455},[9819],{"type":418,"value":9820},"  roleDefinitionId",{"type":413,"tag":448,"props":9822,"children":9823},{"style":461},[9824],{"type":418,"value":464},{"type":413,"tag":448,"props":9826,"children":9827},{"style":1029},[9828],{"type":418,"value":9669},{"type":413,"tag":448,"props":9830,"children":9831},{"style":461},[9832],{"type":418,"value":898},{"type":413,"tag":448,"props":9834,"children":9835},{"style":1029},[9836],{"type":418,"value":6151},{"type":413,"tag":448,"props":9838,"children":9839},{"style":461},[9840],{"type":418,"value":4378},{"type":413,"tag":448,"props":9842,"children":9843},{"class":450,"line":560},[9844,9849,9853,9857,9861,9865,9869,9873,9877,9881,9886],{"type":413,"tag":448,"props":9845,"children":9846},{"style":455},[9847],{"type":418,"value":9848},"  scope",{"type":413,"tag":448,"props":9850,"children":9851},{"style":461},[9852],{"type":418,"value":464},{"type":413,"tag":448,"props":9854,"children":9855},{"style":1029},[9856],{"type":418,"value":9469},{"type":413,"tag":448,"props":9858,"children":9859},{"style":461},[9860],{"type":418,"value":898},{"type":413,"tag":448,"props":9862,"children":9863},{"style":2000},[9864],{"type":418,"value":9478},{"type":413,"tag":448,"props":9866,"children":9867},{"style":461},[9868],{"type":418,"value":9483},{"type":413,"tag":448,"props":9870,"children":9871},{"style":467},[9872],{"type":418,"value":5731},{"type":413,"tag":448,"props":9874,"children":9875},{"style":461},[9876],{"type":418,"value":1452},{"type":413,"tag":448,"props":9878,"children":9879},{"style":1029},[9880],{"type":418,"value":1258},{"type":413,"tag":448,"props":9882,"children":9883},{"style":461},[9884],{"type":418,"value":9885},"}`",{"type":413,"tag":448,"props":9887,"children":9888},{"style":461},[9889],{"type":418,"value":4378},{"type":413,"tag":448,"props":9891,"children":9892},{"class":450,"line":573},[9893,9897,9901],{"type":413,"tag":448,"props":9894,"children":9895},{"style":461},[9896],{"type":418,"value":1825},{"type":413,"tag":448,"props":9898,"children":9899},{"style":1029},[9900],{"type":418,"value":2031},{"type":413,"tag":448,"props":9902,"children":9903},{"style":461},[9904],{"type":418,"value":5802},{"type":413,"tag":414,"props":9906,"children":9907},{},[9908,9910,9915],{"type":418,"value":9909},"I intentionally did not declare the variable ",{"type":413,"tag":444,"props":9911,"children":9913},{"className":9912},[],[9914],{"type":418,"value":1258},{"type":418,"value":9916}," in the code above. It's because it's up to you to choose how you will provide it. You may want to set it in the configuration and retrieve it from it :",{"type":413,"tag":437,"props":9918,"children":9920},{"className":8635,"code":9919,"language":357,"meta":401,"style":401},"const config = new pulumi.Config();\nconst subscriptionId = config.get(\"subscriptionId\");\n",[9921],{"type":413,"tag":444,"props":9922,"children":9923},{"__ignoreMap":401},[9924,9966],{"type":413,"tag":448,"props":9925,"children":9926},{"class":450,"line":451},[9927,9931,9936,9940,9944,9948,9952,9957,9962],{"type":413,"tag":448,"props":9928,"children":9929},{"style":6130},[9930],{"type":418,"value":8699},{"type":413,"tag":448,"props":9932,"children":9933},{"style":1029},[9934],{"type":418,"value":9935}," config ",{"type":413,"tag":448,"props":9937,"children":9938},{"style":461},[9939],{"type":418,"value":1037},{"type":413,"tag":448,"props":9941,"children":9942},{"style":461},[9943],{"type":418,"value":3943},{"type":413,"tag":448,"props":9945,"children":9946},{"style":1029},[9947],{"type":418,"value":9469},{"type":413,"tag":448,"props":9949,"children":9950},{"style":461},[9951],{"type":418,"value":898},{"type":413,"tag":448,"props":9953,"children":9954},{"style":2000},[9955],{"type":418,"value":9956},"Config",{"type":413,"tag":448,"props":9958,"children":9959},{"style":1029},[9960],{"type":418,"value":9961},"()",{"type":413,"tag":448,"props":9963,"children":9964},{"style":461},[9965],{"type":418,"value":5802},{"type":413,"tag":448,"props":9967,"children":9968},{"class":450,"line":473},[9969,9973,9978,9982,9986,9990,9995,9999,10003,10007,10011,10015],{"type":413,"tag":448,"props":9970,"children":9971},{"style":6130},[9972],{"type":418,"value":8699},{"type":413,"tag":448,"props":9974,"children":9975},{"style":1029},[9976],{"type":418,"value":9977}," subscriptionId ",{"type":413,"tag":448,"props":9979,"children":9980},{"style":461},[9981],{"type":418,"value":1037},{"type":413,"tag":448,"props":9983,"children":9984},{"style":1029},[9985],{"type":418,"value":4181},{"type":413,"tag":448,"props":9987,"children":9988},{"style":461},[9989],{"type":418,"value":898},{"type":413,"tag":448,"props":9991,"children":9992},{"style":2000},[9993],{"type":418,"value":9994},"get",{"type":413,"tag":448,"props":9996,"children":9997},{"style":1029},[9998],{"type":418,"value":2041},{"type":413,"tag":448,"props":10000,"children":10001},{"style":461},[10002],{"type":418,"value":1183},{"type":413,"tag":448,"props":10004,"children":10005},{"style":467},[10006],{"type":418,"value":1258},{"type":413,"tag":448,"props":10008,"children":10009},{"style":461},[10010],{"type":418,"value":1183},{"type":413,"tag":448,"props":10012,"children":10013},{"style":1029},[10014],{"type":418,"value":2031},{"type":413,"tag":448,"props":10016,"children":10017},{"style":461},[10018],{"type":418,"value":5802},{"type":413,"tag":414,"props":10020,"children":10021},{},[10022],{"type":418,"value":10023},"Or your might want to retrieve it from the current configuration of the Azure native provider :",{"type":413,"tag":437,"props":10025,"children":10027},{"className":8635,"code":10026,"language":357,"meta":401,"style":401},"const azureConfig = pulumi.output(authorization.getClientConfig());\nconst subscriptionId = azureConfig.subscriptionId;\n",[10028],{"type":413,"tag":444,"props":10029,"children":10030},{"__ignoreMap":401},[10031,10082],{"type":413,"tag":448,"props":10032,"children":10033},{"class":450,"line":451},[10034,10038,10043,10047,10051,10055,10059,10064,10068,10073,10078],{"type":413,"tag":448,"props":10035,"children":10036},{"style":6130},[10037],{"type":418,"value":8699},{"type":413,"tag":448,"props":10039,"children":10040},{"style":1029},[10041],{"type":418,"value":10042}," azureConfig ",{"type":413,"tag":448,"props":10044,"children":10045},{"style":461},[10046],{"type":418,"value":1037},{"type":413,"tag":448,"props":10048,"children":10049},{"style":1029},[10050],{"type":418,"value":9469},{"type":413,"tag":448,"props":10052,"children":10053},{"style":461},[10054],{"type":418,"value":898},{"type":413,"tag":448,"props":10056,"children":10057},{"style":2000},[10058],{"type":418,"value":8920},{"type":413,"tag":448,"props":10060,"children":10061},{"style":1029},[10062],{"type":418,"value":10063},"(authorization",{"type":413,"tag":448,"props":10065,"children":10066},{"style":461},[10067],{"type":418,"value":898},{"type":413,"tag":448,"props":10069,"children":10070},{"style":2000},[10071],{"type":418,"value":10072},"getClientConfig",{"type":413,"tag":448,"props":10074,"children":10075},{"style":1029},[10076],{"type":418,"value":10077},"())",{"type":413,"tag":448,"props":10079,"children":10080},{"style":461},[10081],{"type":418,"value":5802},{"type":413,"tag":448,"props":10083,"children":10084},{"class":450,"line":473},[10085,10089,10093,10097,10101,10105,10109],{"type":413,"tag":448,"props":10086,"children":10087},{"style":6130},[10088],{"type":418,"value":8699},{"type":413,"tag":448,"props":10090,"children":10091},{"style":1029},[10092],{"type":418,"value":9977},{"type":413,"tag":448,"props":10094,"children":10095},{"style":461},[10096],{"type":418,"value":1037},{"type":413,"tag":448,"props":10098,"children":10099},{"style":1029},[10100],{"type":418,"value":5418},{"type":413,"tag":448,"props":10102,"children":10103},{"style":461},[10104],{"type":418,"value":898},{"type":413,"tag":448,"props":10106,"children":10107},{"style":1029},[10108],{"type":418,"value":1258},{"type":413,"tag":448,"props":10110,"children":10111},{"style":461},[10112],{"type":418,"value":5802},{"type":413,"tag":414,"props":10114,"children":10115},{},[10116,10118,10124,10126,10132],{"type":418,"value":10117},"Concerning, the contributor role definition identifier, I could have dynamically retrieved it using Azure APIs (like ",{"type":413,"tag":813,"props":10119,"children":10122},{"href":10120,"rel":10121},"https://github.com/pulumi/examples/blob/master/azure-ts-call-azure-sdk/index.ts",[817],[10123],{"type":418,"value":1386},{"type":418,"value":10125},"). But honestly, as these identifiers don't change it's much easier to hardcode it in a dedicated ",{"type":413,"tag":444,"props":10127,"children":10129},{"className":10128},[],[10130],{"type":418,"value":10131},"builtInRoles.ts",{"type":418,"value":10133}," file.",{"type":413,"tag":437,"props":10135,"children":10137},{"className":8635,"code":10136,"language":357,"meta":401,"style":401},"export const azureBuiltInRoles = {\n  contributor : \"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c\"\n};\n",[10138],{"type":413,"tag":444,"props":10139,"children":10140},{"__ignoreMap":401},[10141,10165,10190],{"type":413,"tag":448,"props":10142,"children":10143},{"class":450,"line":451},[10144,10148,10152,10157,10161],{"type":413,"tag":448,"props":10145,"children":10146},{"style":785},[10147],{"type":418,"value":8856},{"type":413,"tag":448,"props":10149,"children":10150},{"style":6130},[10151],{"type":418,"value":8861},{"type":413,"tag":448,"props":10153,"children":10154},{"style":1029},[10155],{"type":418,"value":10156}," azureBuiltInRoles ",{"type":413,"tag":448,"props":10158,"children":10159},{"style":461},[10160],{"type":418,"value":1037},{"type":413,"tag":448,"props":10162,"children":10163},{"style":461},[10164],{"type":418,"value":8752},{"type":413,"tag":448,"props":10166,"children":10167},{"class":450,"line":473},[10168,10173,10177,10181,10186],{"type":413,"tag":448,"props":10169,"children":10170},{"style":455},[10171],{"type":418,"value":10172},"  contributor ",{"type":413,"tag":448,"props":10174,"children":10175},{"style":461},[10176],{"type":418,"value":464},{"type":413,"tag":448,"props":10178,"children":10179},{"style":461},[10180],{"type":418,"value":995},{"type":413,"tag":448,"props":10182,"children":10183},{"style":467},[10184],{"type":418,"value":10185},"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c",{"type":413,"tag":448,"props":10187,"children":10188},{"style":461},[10189],{"type":418,"value":1005},{"type":413,"tag":448,"props":10191,"children":10192},{"class":450,"line":488},[10193],{"type":413,"tag":448,"props":10194,"children":10195},{"style":461},[10196],{"type":418,"value":7821},{"type":413,"tag":841,"props":10198,"children":10199},{"icon":1103},[10200],{"type":413,"tag":414,"props":10201,"children":10202},{},[10203],{"type":418,"value":10204},"Please note that you don't have to work on the subscription scope. If you prefer to assign the contributor role (or any other role) to an existing resource group rather than the entire subscription, you can certainly do that as well.",{"type":413,"tag":866,"props":10206,"children":10208},{"id":10207},"add-the-configuration-for-the-github-actions-workflow",[10209],{"type":418,"value":10210},"Add the configuration for the GitHub Actions workflow",{"type":413,"tag":414,"props":10212,"children":10213},{},[10214],{"type":418,"value":10215},"The next step is to correctly set the configuration for the GitHub Actions of our Azure-Ready GitHub repository.",{"type":413,"tag":414,"props":10217,"children":10218},{},[10219],{"type":418,"value":10220},"The workflow requires three pieces of information for the OIDC authentication to function properly:",{"type":413,"tag":2155,"props":10222,"children":10223},{},[10224,10228,10232],{"type":413,"tag":2159,"props":10225,"children":10226},{},[10227],{"type":418,"value":2163},{"type":413,"tag":2159,"props":10229,"children":10230},{},[10231],{"type":418,"value":2168},{"type":413,"tag":2159,"props":10233,"children":10234},{},[10235],{"type":418,"value":10236},"The application identifier (also known as client ID) of the previously created Azure AD application",{"type":413,"tag":414,"props":10238,"children":10239},{},[10240],{"type":418,"value":10241},"These identifiers are not secrets, they are just identifiers so we could directly set them as GitHub Actions variables like this:",{"type":413,"tag":437,"props":10243,"children":10245},{"className":8635,"code":10244,"language":357,"meta":401,"style":401},"new github.ActionsVariable(\"tenantId\", {\n  repository: repository.name,\n  variableName: \"ARM_TENANT_ID\",\n  value: azureConfig.tenantId,\n});\n",[10246],{"type":413,"tag":444,"props":10247,"children":10248},{"__ignoreMap":401},[10249,10293,10321,10350,10378],{"type":413,"tag":448,"props":10250,"children":10251},{"class":450,"line":451},[10252,10256,10260,10264,10269,10273,10277,10281,10285,10289],{"type":413,"tag":448,"props":10253,"children":10254},{"style":461},[10255],{"type":418,"value":6133},{"type":413,"tag":448,"props":10257,"children":10258},{"style":1029},[10259],{"type":418,"value":8717},{"type":413,"tag":448,"props":10261,"children":10262},{"style":461},[10263],{"type":418,"value":898},{"type":413,"tag":448,"props":10265,"children":10266},{"style":2000},[10267],{"type":418,"value":10268},"ActionsVariable",{"type":413,"tag":448,"props":10270,"children":10271},{"style":1029},[10272],{"type":418,"value":2041},{"type":413,"tag":448,"props":10274,"children":10275},{"style":461},[10276],{"type":418,"value":1183},{"type":413,"tag":448,"props":10278,"children":10279},{"style":467},[10280],{"type":418,"value":1315},{"type":413,"tag":448,"props":10282,"children":10283},{"style":461},[10284],{"type":418,"value":1183},{"type":413,"tag":448,"props":10286,"children":10287},{"style":461},[10288],{"type":418,"value":2059},{"type":413,"tag":448,"props":10290,"children":10291},{"style":461},[10292],{"type":418,"value":8752},{"type":413,"tag":448,"props":10294,"children":10295},{"class":450,"line":473},[10296,10301,10305,10309,10313,10317],{"type":413,"tag":448,"props":10297,"children":10298},{"style":455},[10299],{"type":418,"value":10300},"  repository",{"type":413,"tag":448,"props":10302,"children":10303},{"style":461},[10304],{"type":418,"value":464},{"type":413,"tag":448,"props":10306,"children":10307},{"style":1029},[10308],{"type":418,"value":4675},{"type":413,"tag":448,"props":10310,"children":10311},{"style":461},[10312],{"type":418,"value":898},{"type":413,"tag":448,"props":10314,"children":10315},{"style":1029},[10316],{"type":418,"value":458},{"type":413,"tag":448,"props":10318,"children":10319},{"style":461},[10320],{"type":418,"value":4378},{"type":413,"tag":448,"props":10322,"children":10323},{"class":450,"line":488},[10324,10329,10333,10337,10342,10346],{"type":413,"tag":448,"props":10325,"children":10326},{"style":455},[10327],{"type":418,"value":10328},"  variableName",{"type":413,"tag":448,"props":10330,"children":10331},{"style":461},[10332],{"type":418,"value":464},{"type":413,"tag":448,"props":10334,"children":10335},{"style":461},[10336],{"type":418,"value":995},{"type":413,"tag":448,"props":10338,"children":10339},{"style":467},[10340],{"type":418,"value":10341},"ARM_TENANT_ID",{"type":413,"tag":448,"props":10343,"children":10344},{"style":461},[10345],{"type":418,"value":1183},{"type":413,"tag":448,"props":10347,"children":10348},{"style":461},[10349],{"type":418,"value":4378},{"type":413,"tag":448,"props":10351,"children":10352},{"class":450,"line":501},[10353,10358,10362,10366,10370,10374],{"type":413,"tag":448,"props":10354,"children":10355},{"style":455},[10356],{"type":418,"value":10357},"  value",{"type":413,"tag":448,"props":10359,"children":10360},{"style":461},[10361],{"type":418,"value":464},{"type":413,"tag":448,"props":10363,"children":10364},{"style":1029},[10365],{"type":418,"value":5418},{"type":413,"tag":448,"props":10367,"children":10368},{"style":461},[10369],{"type":418,"value":898},{"type":413,"tag":448,"props":10371,"children":10372},{"style":1029},[10373],{"type":418,"value":1315},{"type":413,"tag":448,"props":10375,"children":10376},{"style":461},[10377],{"type":418,"value":4378},{"type":413,"tag":448,"props":10379,"children":10380},{"class":450,"line":511},[10381,10385,10389],{"type":413,"tag":448,"props":10382,"children":10383},{"style":461},[10384],{"type":418,"value":1825},{"type":413,"tag":448,"props":10386,"children":10387},{"style":1029},[10388],{"type":418,"value":2031},{"type":413,"tag":448,"props":10390,"children":10391},{"style":461},[10392],{"type":418,"value":5802},{"type":413,"tag":414,"props":10394,"children":10395},{},[10396],{"type":418,"value":10397},"However, I like to keep my tenant id and my subscription id private so we will store them in GitHub secrets but that's not mandatory at all.",{"type":413,"tag":437,"props":10399,"children":10401},{"className":8635,"code":10400,"language":357,"meta":401,"style":401},"const azureConfig = pulumi.output(authorization.getClientConfig());\n\nnew github.ActionsSecret(\"tenantId\", {\n  repository: repository.name,\n  secretName: \"ARM_TENANT_ID\",\n  plaintextValue: azureConfig.tenantId,\n});\n\nnew github.ActionsSecret(\"subscriptionId\", {\n  repository: repository.name,\n  secretName: \"ARM_SUBSCRIPTION_ID\",\n  plaintextValue: azureConfig.subscriptionId,\n});\n\nnew github.ActionsSecret(\"clientId\", {\n  repository: repository.name,\n  secretName: \"ARM_CLIENT_ID\",\n  plaintextValue: aadApplication.applicationId,\n});\n",[10402],{"type":413,"tag":444,"props":10403,"children":10404},{"__ignoreMap":401},[10405,10452,10459,10503,10530,10558,10586,10601,10608,10651,10678,10706,10733,10748,10755,10799,10826,10854,10881],{"type":413,"tag":448,"props":10406,"children":10407},{"class":450,"line":451},[10408,10412,10416,10420,10424,10428,10432,10436,10440,10444,10448],{"type":413,"tag":448,"props":10409,"children":10410},{"style":6130},[10411],{"type":418,"value":8699},{"type":413,"tag":448,"props":10413,"children":10414},{"style":1029},[10415],{"type":418,"value":10042},{"type":413,"tag":448,"props":10417,"children":10418},{"style":461},[10419],{"type":418,"value":1037},{"type":413,"tag":448,"props":10421,"children":10422},{"style":1029},[10423],{"type":418,"value":9469},{"type":413,"tag":448,"props":10425,"children":10426},{"style":461},[10427],{"type":418,"value":898},{"type":413,"tag":448,"props":10429,"children":10430},{"style":2000},[10431],{"type":418,"value":8920},{"type":413,"tag":448,"props":10433,"children":10434},{"style":1029},[10435],{"type":418,"value":10063},{"type":413,"tag":448,"props":10437,"children":10438},{"style":461},[10439],{"type":418,"value":898},{"type":413,"tag":448,"props":10441,"children":10442},{"style":2000},[10443],{"type":418,"value":10072},{"type":413,"tag":448,"props":10445,"children":10446},{"style":1029},[10447],{"type":418,"value":10077},{"type":413,"tag":448,"props":10449,"children":10450},{"style":461},[10451],{"type":418,"value":5802},{"type":413,"tag":448,"props":10453,"children":10454},{"class":450,"line":473},[10455],{"type":413,"tag":448,"props":10456,"children":10457},{"emptyLinePlaceholder":505},[10458],{"type":418,"value":508},{"type":413,"tag":448,"props":10460,"children":10461},{"class":450,"line":488},[10462,10466,10470,10474,10479,10483,10487,10491,10495,10499],{"type":413,"tag":448,"props":10463,"children":10464},{"style":461},[10465],{"type":418,"value":6133},{"type":413,"tag":448,"props":10467,"children":10468},{"style":1029},[10469],{"type":418,"value":8717},{"type":413,"tag":448,"props":10471,"children":10472},{"style":461},[10473],{"type":418,"value":898},{"type":413,"tag":448,"props":10475,"children":10476},{"style":2000},[10477],{"type":418,"value":10478},"ActionsSecret",{"type":413,"tag":448,"props":10480,"children":10481},{"style":1029},[10482],{"type":418,"value":2041},{"type":413,"tag":448,"props":10484,"children":10485},{"style":461},[10486],{"type":418,"value":1183},{"type":413,"tag":448,"props":10488,"children":10489},{"style":467},[10490],{"type":418,"value":1315},{"type":413,"tag":448,"props":10492,"children":10493},{"style":461},[10494],{"type":418,"value":1183},{"type":413,"tag":448,"props":10496,"children":10497},{"style":461},[10498],{"type":418,"value":2059},{"type":413,"tag":448,"props":10500,"children":10501},{"style":461},[10502],{"type":418,"value":8752},{"type":413,"tag":448,"props":10504,"children":10505},{"class":450,"line":501},[10506,10510,10514,10518,10522,10526],{"type":413,"tag":448,"props":10507,"children":10508},{"style":455},[10509],{"type":418,"value":10300},{"type":413,"tag":448,"props":10511,"children":10512},{"style":461},[10513],{"type":418,"value":464},{"type":413,"tag":448,"props":10515,"children":10516},{"style":1029},[10517],{"type":418,"value":4675},{"type":413,"tag":448,"props":10519,"children":10520},{"style":461},[10521],{"type":418,"value":898},{"type":413,"tag":448,"props":10523,"children":10524},{"style":1029},[10525],{"type":418,"value":458},{"type":413,"tag":448,"props":10527,"children":10528},{"style":461},[10529],{"type":418,"value":4378},{"type":413,"tag":448,"props":10531,"children":10532},{"class":450,"line":511},[10533,10538,10542,10546,10550,10554],{"type":413,"tag":448,"props":10534,"children":10535},{"style":455},[10536],{"type":418,"value":10537},"  secretName",{"type":413,"tag":448,"props":10539,"children":10540},{"style":461},[10541],{"type":418,"value":464},{"type":413,"tag":448,"props":10543,"children":10544},{"style":461},[10545],{"type":418,"value":995},{"type":413,"tag":448,"props":10547,"children":10548},{"style":467},[10549],{"type":418,"value":10341},{"type":413,"tag":448,"props":10551,"children":10552},{"style":461},[10553],{"type":418,"value":1183},{"type":413,"tag":448,"props":10555,"children":10556},{"style":461},[10557],{"type":418,"value":4378},{"type":413,"tag":448,"props":10559,"children":10560},{"class":450,"line":524},[10561,10566,10570,10574,10578,10582],{"type":413,"tag":448,"props":10562,"children":10563},{"style":455},[10564],{"type":418,"value":10565},"  plaintextValue",{"type":413,"tag":448,"props":10567,"children":10568},{"style":461},[10569],{"type":418,"value":464},{"type":413,"tag":448,"props":10571,"children":10572},{"style":1029},[10573],{"type":418,"value":5418},{"type":413,"tag":448,"props":10575,"children":10576},{"style":461},[10577],{"type":418,"value":898},{"type":413,"tag":448,"props":10579,"children":10580},{"style":1029},[10581],{"type":418,"value":1315},{"type":413,"tag":448,"props":10583,"children":10584},{"style":461},[10585],{"type":418,"value":4378},{"type":413,"tag":448,"props":10587,"children":10588},{"class":450,"line":542},[10589,10593,10597],{"type":413,"tag":448,"props":10590,"children":10591},{"style":461},[10592],{"type":418,"value":1825},{"type":413,"tag":448,"props":10594,"children":10595},{"style":1029},[10596],{"type":418,"value":2031},{"type":413,"tag":448,"props":10598,"children":10599},{"style":461},[10600],{"type":418,"value":5802},{"type":413,"tag":448,"props":10602,"children":10603},{"class":450,"line":560},[10604],{"type":413,"tag":448,"props":10605,"children":10606},{"emptyLinePlaceholder":505},[10607],{"type":418,"value":508},{"type":413,"tag":448,"props":10609,"children":10610},{"class":450,"line":573},[10611,10615,10619,10623,10627,10631,10635,10639,10643,10647],{"type":413,"tag":448,"props":10612,"children":10613},{"style":461},[10614],{"type":418,"value":6133},{"type":413,"tag":448,"props":10616,"children":10617},{"style":1029},[10618],{"type":418,"value":8717},{"type":413,"tag":448,"props":10620,"children":10621},{"style":461},[10622],{"type":418,"value":898},{"type":413,"tag":448,"props":10624,"children":10625},{"style":2000},[10626],{"type":418,"value":10478},{"type":413,"tag":448,"props":10628,"children":10629},{"style":1029},[10630],{"type":418,"value":2041},{"type":413,"tag":448,"props":10632,"children":10633},{"style":461},[10634],{"type":418,"value":1183},{"type":413,"tag":448,"props":10636,"children":10637},{"style":467},[10638],{"type":418,"value":1258},{"type":413,"tag":448,"props":10640,"children":10641},{"style":461},[10642],{"type":418,"value":1183},{"type":413,"tag":448,"props":10644,"children":10645},{"style":461},[10646],{"type":418,"value":2059},{"type":413,"tag":448,"props":10648,"children":10649},{"style":461},[10650],{"type":418,"value":8752},{"type":413,"tag":448,"props":10652,"children":10653},{"class":450,"line":586},[10654,10658,10662,10666,10670,10674],{"type":413,"tag":448,"props":10655,"children":10656},{"style":455},[10657],{"type":418,"value":10300},{"type":413,"tag":448,"props":10659,"children":10660},{"style":461},[10661],{"type":418,"value":464},{"type":413,"tag":448,"props":10663,"children":10664},{"style":1029},[10665],{"type":418,"value":4675},{"type":413,"tag":448,"props":10667,"children":10668},{"style":461},[10669],{"type":418,"value":898},{"type":413,"tag":448,"props":10671,"children":10672},{"style":1029},[10673],{"type":418,"value":458},{"type":413,"tag":448,"props":10675,"children":10676},{"style":461},[10677],{"type":418,"value":4378},{"type":413,"tag":448,"props":10679,"children":10680},{"class":450,"line":604},[10681,10685,10689,10693,10698,10702],{"type":413,"tag":448,"props":10682,"children":10683},{"style":455},[10684],{"type":418,"value":10537},{"type":413,"tag":448,"props":10686,"children":10687},{"style":461},[10688],{"type":418,"value":464},{"type":413,"tag":448,"props":10690,"children":10691},{"style":461},[10692],{"type":418,"value":995},{"type":413,"tag":448,"props":10694,"children":10695},{"style":467},[10696],{"type":418,"value":10697},"ARM_SUBSCRIPTION_ID",{"type":413,"tag":448,"props":10699,"children":10700},{"style":461},[10701],{"type":418,"value":1183},{"type":413,"tag":448,"props":10703,"children":10704},{"style":461},[10705],{"type":418,"value":4378},{"type":413,"tag":448,"props":10707,"children":10708},{"class":450,"line":617},[10709,10713,10717,10721,10725,10729],{"type":413,"tag":448,"props":10710,"children":10711},{"style":455},[10712],{"type":418,"value":10565},{"type":413,"tag":448,"props":10714,"children":10715},{"style":461},[10716],{"type":418,"value":464},{"type":413,"tag":448,"props":10718,"children":10719},{"style":1029},[10720],{"type":418,"value":5418},{"type":413,"tag":448,"props":10722,"children":10723},{"style":461},[10724],{"type":418,"value":898},{"type":413,"tag":448,"props":10726,"children":10727},{"style":1029},[10728],{"type":418,"value":1258},{"type":413,"tag":448,"props":10730,"children":10731},{"style":461},[10732],{"type":418,"value":4378},{"type":413,"tag":448,"props":10734,"children":10735},{"class":450,"line":650},[10736,10740,10744],{"type":413,"tag":448,"props":10737,"children":10738},{"style":461},[10739],{"type":418,"value":1825},{"type":413,"tag":448,"props":10741,"children":10742},{"style":1029},[10743],{"type":418,"value":2031},{"type":413,"tag":448,"props":10745,"children":10746},{"style":461},[10747],{"type":418,"value":5802},{"type":413,"tag":448,"props":10749,"children":10750},{"class":450,"line":668},[10751],{"type":413,"tag":448,"props":10752,"children":10753},{"emptyLinePlaceholder":505},[10754],{"type":418,"value":508},{"type":413,"tag":448,"props":10756,"children":10757},{"class":450,"line":681},[10758,10762,10766,10770,10774,10778,10782,10787,10791,10795],{"type":413,"tag":448,"props":10759,"children":10760},{"style":461},[10761],{"type":418,"value":6133},{"type":413,"tag":448,"props":10763,"children":10764},{"style":1029},[10765],{"type":418,"value":8717},{"type":413,"tag":448,"props":10767,"children":10768},{"style":461},[10769],{"type":418,"value":898},{"type":413,"tag":448,"props":10771,"children":10772},{"style":2000},[10773],{"type":418,"value":10478},{"type":413,"tag":448,"props":10775,"children":10776},{"style":1029},[10777],{"type":418,"value":2041},{"type":413,"tag":448,"props":10779,"children":10780},{"style":461},[10781],{"type":418,"value":1183},{"type":413,"tag":448,"props":10783,"children":10784},{"style":467},[10785],{"type":418,"value":10786},"clientId",{"type":413,"tag":448,"props":10788,"children":10789},{"style":461},[10790],{"type":418,"value":1183},{"type":413,"tag":448,"props":10792,"children":10793},{"style":461},[10794],{"type":418,"value":2059},{"type":413,"tag":448,"props":10796,"children":10797},{"style":461},[10798],{"type":418,"value":8752},{"type":413,"tag":448,"props":10800,"children":10801},{"class":450,"line":699},[10802,10806,10810,10814,10818,10822],{"type":413,"tag":448,"props":10803,"children":10804},{"style":455},[10805],{"type":418,"value":10300},{"type":413,"tag":448,"props":10807,"children":10808},{"style":461},[10809],{"type":418,"value":464},{"type":413,"tag":448,"props":10811,"children":10812},{"style":1029},[10813],{"type":418,"value":4675},{"type":413,"tag":448,"props":10815,"children":10816},{"style":461},[10817],{"type":418,"value":898},{"type":413,"tag":448,"props":10819,"children":10820},{"style":1029},[10821],{"type":418,"value":458},{"type":413,"tag":448,"props":10823,"children":10824},{"style":461},[10825],{"type":418,"value":4378},{"type":413,"tag":448,"props":10827,"children":10828},{"class":450,"line":717},[10829,10833,10837,10841,10846,10850],{"type":413,"tag":448,"props":10830,"children":10831},{"style":455},[10832],{"type":418,"value":10537},{"type":413,"tag":448,"props":10834,"children":10835},{"style":461},[10836],{"type":418,"value":464},{"type":413,"tag":448,"props":10838,"children":10839},{"style":461},[10840],{"type":418,"value":995},{"type":413,"tag":448,"props":10842,"children":10843},{"style":467},[10844],{"type":418,"value":10845},"ARM_CLIENT_ID",{"type":413,"tag":448,"props":10847,"children":10848},{"style":461},[10849],{"type":418,"value":1183},{"type":413,"tag":448,"props":10851,"children":10852},{"style":461},[10853],{"type":418,"value":4378},{"type":413,"tag":448,"props":10855,"children":10856},{"class":450,"line":735},[10857,10861,10865,10869,10873,10877],{"type":413,"tag":448,"props":10858,"children":10859},{"style":455},[10860],{"type":418,"value":10565},{"type":413,"tag":448,"props":10862,"children":10863},{"style":461},[10864],{"type":418,"value":464},{"type":413,"tag":448,"props":10866,"children":10867},{"style":1029},[10868],{"type":418,"value":5893},{"type":413,"tag":448,"props":10870,"children":10871},{"style":461},[10872],{"type":418,"value":898},{"type":413,"tag":448,"props":10874,"children":10875},{"style":1029},[10876],{"type":418,"value":9210},{"type":413,"tag":448,"props":10878,"children":10879},{"style":461},[10880],{"type":418,"value":4378},{"type":413,"tag":448,"props":10882,"children":10883},{"class":450,"line":743},[10884,10888,10892],{"type":413,"tag":448,"props":10885,"children":10886},{"style":461},[10887],{"type":418,"value":1825},{"type":413,"tag":448,"props":10889,"children":10890},{"style":1029},[10891],{"type":418,"value":2031},{"type":413,"tag":448,"props":10893,"children":10894},{"style":461},[10895],{"type":418,"value":5802},{"type":413,"tag":841,"props":10897,"children":10898},{"icon":3815},[10899],{"type":413,"tag":414,"props":10900,"children":10901},{},[10902,10904,10911],{"type":418,"value":10903},"Please note that could also use ",{"type":413,"tag":813,"props":10905,"children":10908},{"href":10906,"rel":10907},"https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment",[817],[10909],{"type":418,"value":10910},"environments for deployment",{"type":418,"value":10912}," and their associated secrets and variables.",{"type":413,"tag":866,"props":10914,"children":10916},{"id":10915},"create-the-github-actions-workflow",[10917],{"type":418,"value":10918},"Create the GitHub Actions workflow",{"type":413,"tag":414,"props":10920,"children":10921},{},[10922],{"type":418,"value":10923},"Everything seems to be properly configured to provision Azure resources from a GitHub Actions workflow in this new repository, except for the workflow itself. The goal here is to have a properly configured pipeline in the repository to get started provisioning Azure infrastructure.",{"type":413,"tag":414,"props":10925,"children":10926},{},[10927],{"type":418,"value":10928},"Here is such a pipeline:",{"type":413,"tag":437,"props":10930,"children":10932},{"className":439,"code":10931,"language":441,"meta":401,"style":401},"name: infra\n\non:\n  workflow_dispatch:\n\npermissions:\n      id-token: write\n      contents: read\njobs:\n  provision-infra:\n    runs-on: ubuntu-latest\n    steps:\n      - name: 'Az CLI login'\n        uses: azure/login@v1\n        with:\n          client-id: ${{ secrets.AZURE_CLIENT_ID }}\n          tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n\n      - name: 'Run az commands'\n        run: |\n          az account show\n          az group list\n",[10933],{"type":413,"tag":444,"props":10934,"children":10935},{"__ignoreMap":401},[10936,10952,10959,10970,10981,10988,10999,11015,11031,11042,11054,11069,11080,11107,11122,11133,11148,11163,11178,11185,11212,11227,11234],{"type":413,"tag":448,"props":10937,"children":10938},{"class":450,"line":451},[10939,10943,10947],{"type":413,"tag":448,"props":10940,"children":10941},{"style":455},[10942],{"type":418,"value":458},{"type":413,"tag":448,"props":10944,"children":10945},{"style":461},[10946],{"type":418,"value":464},{"type":413,"tag":448,"props":10948,"children":10949},{"style":467},[10950],{"type":418,"value":10951}," infra\n",{"type":413,"tag":448,"props":10953,"children":10954},{"class":450,"line":473},[10955],{"type":413,"tag":448,"props":10956,"children":10957},{"emptyLinePlaceholder":505},[10958],{"type":418,"value":508},{"type":413,"tag":448,"props":10960,"children":10961},{"class":450,"line":488},[10962,10966],{"type":413,"tag":448,"props":10963,"children":10964},{"style":477},[10965],{"type":418,"value":480},{"type":413,"tag":448,"props":10967,"children":10968},{"style":461},[10969],{"type":418,"value":485},{"type":413,"tag":448,"props":10971,"children":10972},{"class":450,"line":501},[10973,10977],{"type":413,"tag":448,"props":10974,"children":10975},{"style":455},[10976],{"type":418,"value":494},{"type":413,"tag":448,"props":10978,"children":10979},{"style":461},[10980],{"type":418,"value":485},{"type":413,"tag":448,"props":10982,"children":10983},{"class":450,"line":511},[10984],{"type":413,"tag":448,"props":10985,"children":10986},{"emptyLinePlaceholder":505},[10987],{"type":418,"value":508},{"type":413,"tag":448,"props":10989,"children":10990},{"class":450,"line":524},[10991,10995],{"type":413,"tag":448,"props":10992,"children":10993},{"style":455},[10994],{"type":418,"value":517},{"type":413,"tag":448,"props":10996,"children":10997},{"style":461},[10998],{"type":418,"value":485},{"type":413,"tag":448,"props":11000,"children":11001},{"class":450,"line":542},[11002,11007,11011],{"type":413,"tag":448,"props":11003,"children":11004},{"style":455},[11005],{"type":418,"value":11006},"      id-token",{"type":413,"tag":448,"props":11008,"children":11009},{"style":461},[11010],{"type":418,"value":464},{"type":413,"tag":448,"props":11012,"children":11013},{"style":467},[11014],{"type":418,"value":539},{"type":413,"tag":448,"props":11016,"children":11017},{"class":450,"line":560},[11018,11023,11027],{"type":413,"tag":448,"props":11019,"children":11020},{"style":455},[11021],{"type":418,"value":11022},"      contents",{"type":413,"tag":448,"props":11024,"children":11025},{"style":461},[11026],{"type":418,"value":464},{"type":413,"tag":448,"props":11028,"children":11029},{"style":467},[11030],{"type":418,"value":557},{"type":413,"tag":448,"props":11032,"children":11033},{"class":450,"line":573},[11034,11038],{"type":413,"tag":448,"props":11035,"children":11036},{"style":455},[11037],{"type":418,"value":566},{"type":413,"tag":448,"props":11039,"children":11040},{"style":461},[11041],{"type":418,"value":485},{"type":413,"tag":448,"props":11043,"children":11044},{"class":450,"line":586},[11045,11050],{"type":413,"tag":448,"props":11046,"children":11047},{"style":455},[11048],{"type":418,"value":11049},"  provision-infra",{"type":413,"tag":448,"props":11051,"children":11052},{"style":461},[11053],{"type":418,"value":485},{"type":413,"tag":448,"props":11055,"children":11056},{"class":450,"line":604},[11057,11061,11065],{"type":413,"tag":448,"props":11058,"children":11059},{"style":455},[11060],{"type":418,"value":592},{"type":413,"tag":448,"props":11062,"children":11063},{"style":461},[11064],{"type":418,"value":464},{"type":413,"tag":448,"props":11066,"children":11067},{"style":467},[11068],{"type":418,"value":601},{"type":413,"tag":448,"props":11070,"children":11071},{"class":450,"line":617},[11072,11076],{"type":413,"tag":448,"props":11073,"children":11074},{"style":455},[11075],{"type":418,"value":610},{"type":413,"tag":448,"props":11077,"children":11078},{"style":461},[11079],{"type":418,"value":485},{"type":413,"tag":448,"props":11081,"children":11082},{"class":450,"line":650},[11083,11087,11091,11095,11099,11103],{"type":413,"tag":448,"props":11084,"children":11085},{"style":461},[11086],{"type":418,"value":623},{"type":413,"tag":448,"props":11088,"children":11089},{"style":455},[11090],{"type":418,"value":628},{"type":413,"tag":448,"props":11092,"children":11093},{"style":461},[11094],{"type":418,"value":464},{"type":413,"tag":448,"props":11096,"children":11097},{"style":461},[11098],{"type":418,"value":637},{"type":413,"tag":448,"props":11100,"children":11101},{"style":467},[11102],{"type":418,"value":642},{"type":413,"tag":448,"props":11104,"children":11105},{"style":461},[11106],{"type":418,"value":647},{"type":413,"tag":448,"props":11108,"children":11109},{"class":450,"line":668},[11110,11114,11118],{"type":413,"tag":448,"props":11111,"children":11112},{"style":455},[11113],{"type":418,"value":656},{"type":413,"tag":448,"props":11115,"children":11116},{"style":461},[11117],{"type":418,"value":464},{"type":413,"tag":448,"props":11119,"children":11120},{"style":467},[11121],{"type":418,"value":665},{"type":413,"tag":448,"props":11123,"children":11124},{"class":450,"line":681},[11125,11129],{"type":413,"tag":448,"props":11126,"children":11127},{"style":455},[11128],{"type":418,"value":674},{"type":413,"tag":448,"props":11130,"children":11131},{"style":461},[11132],{"type":418,"value":485},{"type":413,"tag":448,"props":11134,"children":11135},{"class":450,"line":699},[11136,11140,11144],{"type":413,"tag":448,"props":11137,"children":11138},{"style":455},[11139],{"type":418,"value":687},{"type":413,"tag":448,"props":11141,"children":11142},{"style":461},[11143],{"type":418,"value":464},{"type":413,"tag":448,"props":11145,"children":11146},{"style":467},[11147],{"type":418,"value":696},{"type":413,"tag":448,"props":11149,"children":11150},{"class":450,"line":717},[11151,11155,11159],{"type":413,"tag":448,"props":11152,"children":11153},{"style":455},[11154],{"type":418,"value":705},{"type":413,"tag":448,"props":11156,"children":11157},{"style":461},[11158],{"type":418,"value":464},{"type":413,"tag":448,"props":11160,"children":11161},{"style":467},[11162],{"type":418,"value":714},{"type":413,"tag":448,"props":11164,"children":11165},{"class":450,"line":735},[11166,11170,11174],{"type":413,"tag":448,"props":11167,"children":11168},{"style":455},[11169],{"type":418,"value":723},{"type":413,"tag":448,"props":11171,"children":11172},{"style":461},[11173],{"type":418,"value":464},{"type":413,"tag":448,"props":11175,"children":11176},{"style":467},[11177],{"type":418,"value":732},{"type":413,"tag":448,"props":11179,"children":11180},{"class":450,"line":743},[11181],{"type":413,"tag":448,"props":11182,"children":11183},{"emptyLinePlaceholder":505},[11184],{"type":418,"value":508},{"type":413,"tag":448,"props":11186,"children":11187},{"class":450,"line":772},[11188,11192,11196,11200,11204,11208],{"type":413,"tag":448,"props":11189,"children":11190},{"style":461},[11191],{"type":418,"value":623},{"type":413,"tag":448,"props":11193,"children":11194},{"style":455},[11195],{"type":418,"value":628},{"type":413,"tag":448,"props":11197,"children":11198},{"style":461},[11199],{"type":418,"value":464},{"type":413,"tag":448,"props":11201,"children":11202},{"style":461},[11203],{"type":418,"value":637},{"type":413,"tag":448,"props":11205,"children":11206},{"style":467},[11207],{"type":418,"value":765},{"type":413,"tag":448,"props":11209,"children":11210},{"style":461},[11211],{"type":418,"value":647},{"type":413,"tag":448,"props":11213,"children":11214},{"class":450,"line":791},[11215,11219,11223],{"type":413,"tag":448,"props":11216,"children":11217},{"style":455},[11218],{"type":418,"value":778},{"type":413,"tag":448,"props":11220,"children":11221},{"style":461},[11222],{"type":418,"value":464},{"type":413,"tag":448,"props":11224,"children":11225},{"style":785},[11226],{"type":418,"value":788},{"type":413,"tag":448,"props":11228,"children":11229},{"class":450,"line":800},[11230],{"type":413,"tag":448,"props":11231,"children":11232},{"style":467},[11233],{"type":418,"value":797},{"type":413,"tag":448,"props":11235,"children":11236},{"class":450,"line":2909},[11237],{"type":413,"tag":448,"props":11238,"children":11239},{"style":467},[11240],{"type":418,"value":806},{"type":413,"tag":414,"props":11242,"children":11243},{},[11244,11246,11252],{"type":418,"value":11245},"This workflow first authenticates to Azure using OIDC with the ",{"type":413,"tag":444,"props":11247,"children":11249},{"className":11248},[],[11250],{"type":418,"value":11251},"azure/login",{"type":418,"value":11253}," action and then performs some Azure CLI commands to interact with Azure resources. That's fine and probably enough to get you started but you surely want to provision your infrastructure using a more declarative solution than an Azure CLI script. So let's see a more interesting pipeline still authenticating via Azure OIDC but using Pulumi to provision the Azure resources.",{"type":413,"tag":437,"props":11255,"children":11257},{"className":439,"code":11256,"language":441,"meta":401,"style":401},"name: infra\n\non:\n  workflow_dispatch:\n\npermissions:\n  id-token: write   # required for OIDC auth\n  contents: read    # required to perform a checkout\n\njobs:\n  provision-infra:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Install pnpm\n        uses: pnpm/action-setup@v2\n        with:\n          version: latest\n\n      - name: Set node version to 18\n        uses: actions/setup-node@v3\n        with:\n          node-version: 18\n          cache: 'pnpm'\n      \n      - name: Install dependencies\n        run: pnpm install\n      \n      - name: Provision infrastructure\n        uses: pulumi/actions@v4.4.0\n        id: pulumi\n        with:\n          command: up\n          stack-name: dev\n        env:\n          ARM_USE_OIDC: true\n          PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}\n          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}\n          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}\n          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} \n",[11258],{"type":413,"tag":444,"props":11259,"children":11260},{"__ignoreMap":401},[11261,11276,11283,11294,11305,11312,11323,11344,11365,11372,11383,11394,11409,11420,11441,11448,11468,11484,11495,11512,11519,11539,11555,11566,11583,11607,11615,11635,11651,11658,11678,11694,11711,11722,11739,11756,11768,11784,11801,11818,11835],{"type":413,"tag":448,"props":11262,"children":11263},{"class":450,"line":451},[11264,11268,11272],{"type":413,"tag":448,"props":11265,"children":11266},{"style":455},[11267],{"type":418,"value":458},{"type":413,"tag":448,"props":11269,"children":11270},{"style":461},[11271],{"type":418,"value":464},{"type":413,"tag":448,"props":11273,"children":11274},{"style":467},[11275],{"type":418,"value":10951},{"type":413,"tag":448,"props":11277,"children":11278},{"class":450,"line":473},[11279],{"type":413,"tag":448,"props":11280,"children":11281},{"emptyLinePlaceholder":505},[11282],{"type":418,"value":508},{"type":413,"tag":448,"props":11284,"children":11285},{"class":450,"line":488},[11286,11290],{"type":413,"tag":448,"props":11287,"children":11288},{"style":477},[11289],{"type":418,"value":480},{"type":413,"tag":448,"props":11291,"children":11292},{"style":461},[11293],{"type":418,"value":485},{"type":413,"tag":448,"props":11295,"children":11296},{"class":450,"line":501},[11297,11301],{"type":413,"tag":448,"props":11298,"children":11299},{"style":455},[11300],{"type":418,"value":494},{"type":413,"tag":448,"props":11302,"children":11303},{"style":461},[11304],{"type":418,"value":485},{"type":413,"tag":448,"props":11306,"children":11307},{"class":450,"line":511},[11308],{"type":413,"tag":448,"props":11309,"children":11310},{"emptyLinePlaceholder":505},[11311],{"type":418,"value":508},{"type":413,"tag":448,"props":11313,"children":11314},{"class":450,"line":524},[11315,11319],{"type":413,"tag":448,"props":11316,"children":11317},{"style":455},[11318],{"type":418,"value":517},{"type":413,"tag":448,"props":11320,"children":11321},{"style":461},[11322],{"type":418,"value":485},{"type":413,"tag":448,"props":11324,"children":11325},{"class":450,"line":542},[11326,11330,11334,11339],{"type":413,"tag":448,"props":11327,"children":11328},{"style":455},[11329],{"type":418,"value":530},{"type":413,"tag":448,"props":11331,"children":11332},{"style":461},[11333],{"type":418,"value":464},{"type":413,"tag":448,"props":11335,"children":11336},{"style":467},[11337],{"type":418,"value":11338}," write",{"type":413,"tag":448,"props":11340,"children":11341},{"style":2393},[11342],{"type":418,"value":11343},"   # required for OIDC auth\n",{"type":413,"tag":448,"props":11345,"children":11346},{"class":450,"line":560},[11347,11351,11355,11360],{"type":413,"tag":448,"props":11348,"children":11349},{"style":455},[11350],{"type":418,"value":548},{"type":413,"tag":448,"props":11352,"children":11353},{"style":461},[11354],{"type":418,"value":464},{"type":413,"tag":448,"props":11356,"children":11357},{"style":467},[11358],{"type":418,"value":11359}," read",{"type":413,"tag":448,"props":11361,"children":11362},{"style":2393},[11363],{"type":418,"value":11364},"    # required to perform a checkout\n",{"type":413,"tag":448,"props":11366,"children":11367},{"class":450,"line":573},[11368],{"type":413,"tag":448,"props":11369,"children":11370},{"emptyLinePlaceholder":505},[11371],{"type":418,"value":508},{"type":413,"tag":448,"props":11373,"children":11374},{"class":450,"line":586},[11375,11379],{"type":413,"tag":448,"props":11376,"children":11377},{"style":455},[11378],{"type":418,"value":566},{"type":413,"tag":448,"props":11380,"children":11381},{"style":461},[11382],{"type":418,"value":485},{"type":413,"tag":448,"props":11384,"children":11385},{"class":450,"line":604},[11386,11390],{"type":413,"tag":448,"props":11387,"children":11388},{"style":455},[11389],{"type":418,"value":11049},{"type":413,"tag":448,"props":11391,"children":11392},{"style":461},[11393],{"type":418,"value":485},{"type":413,"tag":448,"props":11395,"children":11396},{"class":450,"line":617},[11397,11401,11405],{"type":413,"tag":448,"props":11398,"children":11399},{"style":455},[11400],{"type":418,"value":592},{"type":413,"tag":448,"props":11402,"children":11403},{"style":461},[11404],{"type":418,"value":464},{"type":413,"tag":448,"props":11406,"children":11407},{"style":467},[11408],{"type":418,"value":601},{"type":413,"tag":448,"props":11410,"children":11411},{"class":450,"line":650},[11412,11416],{"type":413,"tag":448,"props":11413,"children":11414},{"style":455},[11415],{"type":418,"value":610},{"type":413,"tag":448,"props":11417,"children":11418},{"style":461},[11419],{"type":418,"value":485},{"type":413,"tag":448,"props":11421,"children":11422},{"class":450,"line":668},[11423,11427,11432,11436],{"type":413,"tag":448,"props":11424,"children":11425},{"style":461},[11426],{"type":418,"value":623},{"type":413,"tag":448,"props":11428,"children":11429},{"style":455},[11430],{"type":418,"value":11431}," uses",{"type":413,"tag":448,"props":11433,"children":11434},{"style":461},[11435],{"type":418,"value":464},{"type":413,"tag":448,"props":11437,"children":11438},{"style":467},[11439],{"type":418,"value":11440}," actions/checkout@v3\n",{"type":413,"tag":448,"props":11442,"children":11443},{"class":450,"line":681},[11444],{"type":413,"tag":448,"props":11445,"children":11446},{"emptyLinePlaceholder":505},[11447],{"type":418,"value":508},{"type":413,"tag":448,"props":11449,"children":11450},{"class":450,"line":699},[11451,11455,11459,11463],{"type":413,"tag":448,"props":11452,"children":11453},{"style":461},[11454],{"type":418,"value":623},{"type":413,"tag":448,"props":11456,"children":11457},{"style":455},[11458],{"type":418,"value":628},{"type":413,"tag":448,"props":11460,"children":11461},{"style":461},[11462],{"type":418,"value":464},{"type":413,"tag":448,"props":11464,"children":11465},{"style":467},[11466],{"type":418,"value":11467}," Install pnpm\n",{"type":413,"tag":448,"props":11469,"children":11470},{"class":450,"line":717},[11471,11475,11479],{"type":413,"tag":448,"props":11472,"children":11473},{"style":455},[11474],{"type":418,"value":656},{"type":413,"tag":448,"props":11476,"children":11477},{"style":461},[11478],{"type":418,"value":464},{"type":413,"tag":448,"props":11480,"children":11481},{"style":467},[11482],{"type":418,"value":11483}," pnpm/action-setup@v2\n",{"type":413,"tag":448,"props":11485,"children":11486},{"class":450,"line":735},[11487,11491],{"type":413,"tag":448,"props":11488,"children":11489},{"style":455},[11490],{"type":418,"value":674},{"type":413,"tag":448,"props":11492,"children":11493},{"style":461},[11494],{"type":418,"value":485},{"type":413,"tag":448,"props":11496,"children":11497},{"class":450,"line":743},[11498,11503,11507],{"type":413,"tag":448,"props":11499,"children":11500},{"style":455},[11501],{"type":418,"value":11502},"          version",{"type":413,"tag":448,"props":11504,"children":11505},{"style":461},[11506],{"type":418,"value":464},{"type":413,"tag":448,"props":11508,"children":11509},{"style":467},[11510],{"type":418,"value":11511}," latest\n",{"type":413,"tag":448,"props":11513,"children":11514},{"class":450,"line":772},[11515],{"type":413,"tag":448,"props":11516,"children":11517},{"emptyLinePlaceholder":505},[11518],{"type":418,"value":508},{"type":413,"tag":448,"props":11520,"children":11521},{"class":450,"line":791},[11522,11526,11530,11534],{"type":413,"tag":448,"props":11523,"children":11524},{"style":461},[11525],{"type":418,"value":623},{"type":413,"tag":448,"props":11527,"children":11528},{"style":455},[11529],{"type":418,"value":628},{"type":413,"tag":448,"props":11531,"children":11532},{"style":461},[11533],{"type":418,"value":464},{"type":413,"tag":448,"props":11535,"children":11536},{"style":467},[11537],{"type":418,"value":11538}," Set node version to 18\n",{"type":413,"tag":448,"props":11540,"children":11541},{"class":450,"line":800},[11542,11546,11550],{"type":413,"tag":448,"props":11543,"children":11544},{"style":455},[11545],{"type":418,"value":656},{"type":413,"tag":448,"props":11547,"children":11548},{"style":461},[11549],{"type":418,"value":464},{"type":413,"tag":448,"props":11551,"children":11552},{"style":467},[11553],{"type":418,"value":11554}," actions/setup-node@v3\n",{"type":413,"tag":448,"props":11556,"children":11557},{"class":450,"line":2909},[11558,11562],{"type":413,"tag":448,"props":11559,"children":11560},{"style":455},[11561],{"type":418,"value":674},{"type":413,"tag":448,"props":11563,"children":11564},{"style":461},[11565],{"type":418,"value":485},{"type":413,"tag":448,"props":11567,"children":11568},{"class":450,"line":3021},[11569,11574,11578],{"type":413,"tag":448,"props":11570,"children":11571},{"style":455},[11572],{"type":418,"value":11573},"          node-version",{"type":413,"tag":448,"props":11575,"children":11576},{"style":461},[11577],{"type":418,"value":464},{"type":413,"tag":448,"props":11579,"children":11580},{"style":1733},[11581],{"type":418,"value":11582}," 18\n",{"type":413,"tag":448,"props":11584,"children":11585},{"class":450,"line":3029},[11586,11591,11595,11599,11603],{"type":413,"tag":448,"props":11587,"children":11588},{"style":455},[11589],{"type":418,"value":11590},"          cache",{"type":413,"tag":448,"props":11592,"children":11593},{"style":461},[11594],{"type":418,"value":464},{"type":413,"tag":448,"props":11596,"children":11597},{"style":461},[11598],{"type":418,"value":637},{"type":413,"tag":448,"props":11600,"children":11601},{"style":467},[11602],{"type":418,"value":362},{"type":413,"tag":448,"props":11604,"children":11605},{"style":461},[11606],{"type":418,"value":647},{"type":413,"tag":448,"props":11608,"children":11609},{"class":450,"line":3038},[11610],{"type":413,"tag":448,"props":11611,"children":11612},{"style":1029},[11613],{"type":418,"value":11614},"      \n",{"type":413,"tag":448,"props":11616,"children":11617},{"class":450,"line":3062},[11618,11622,11626,11630],{"type":413,"tag":448,"props":11619,"children":11620},{"style":461},[11621],{"type":418,"value":623},{"type":413,"tag":448,"props":11623,"children":11624},{"style":455},[11625],{"type":418,"value":628},{"type":413,"tag":448,"props":11627,"children":11628},{"style":461},[11629],{"type":418,"value":464},{"type":413,"tag":448,"props":11631,"children":11632},{"style":467},[11633],{"type":418,"value":11634}," Install dependencies\n",{"type":413,"tag":448,"props":11636,"children":11637},{"class":450,"line":3086},[11638,11642,11646],{"type":413,"tag":448,"props":11639,"children":11640},{"style":455},[11641],{"type":418,"value":778},{"type":413,"tag":448,"props":11643,"children":11644},{"style":461},[11645],{"type":418,"value":464},{"type":413,"tag":448,"props":11647,"children":11648},{"style":467},[11649],{"type":418,"value":11650}," pnpm install\n",{"type":413,"tag":448,"props":11652,"children":11653},{"class":450,"line":3110},[11654],{"type":413,"tag":448,"props":11655,"children":11656},{"style":1029},[11657],{"type":418,"value":11614},{"type":413,"tag":448,"props":11659,"children":11660},{"class":450,"line":3150},[11661,11665,11669,11673],{"type":413,"tag":448,"props":11662,"children":11663},{"style":461},[11664],{"type":418,"value":623},{"type":413,"tag":448,"props":11666,"children":11667},{"style":455},[11668],{"type":418,"value":628},{"type":413,"tag":448,"props":11670,"children":11671},{"style":461},[11672],{"type":418,"value":464},{"type":413,"tag":448,"props":11674,"children":11675},{"style":467},[11676],{"type":418,"value":11677}," Provision infrastructure\n",{"type":413,"tag":448,"props":11679,"children":11680},{"class":450,"line":3182},[11681,11685,11689],{"type":413,"tag":448,"props":11682,"children":11683},{"style":455},[11684],{"type":418,"value":656},{"type":413,"tag":448,"props":11686,"children":11687},{"style":461},[11688],{"type":418,"value":464},{"type":413,"tag":448,"props":11690,"children":11691},{"style":467},[11692],{"type":418,"value":11693}," pulumi/actions@v4.4.0\n",{"type":413,"tag":448,"props":11695,"children":11696},{"class":450,"line":3202},[11697,11702,11706],{"type":413,"tag":448,"props":11698,"children":11699},{"style":455},[11700],{"type":418,"value":11701},"        id",{"type":413,"tag":448,"props":11703,"children":11704},{"style":461},[11705],{"type":418,"value":464},{"type":413,"tag":448,"props":11707,"children":11708},{"style":467},[11709],{"type":418,"value":11710}," pulumi\n",{"type":413,"tag":448,"props":11712,"children":11713},{"class":450,"line":3218},[11714,11718],{"type":413,"tag":448,"props":11715,"children":11716},{"style":455},[11717],{"type":418,"value":674},{"type":413,"tag":448,"props":11719,"children":11720},{"style":461},[11721],{"type":418,"value":485},{"type":413,"tag":448,"props":11723,"children":11724},{"class":450,"line":3226},[11725,11730,11734],{"type":413,"tag":448,"props":11726,"children":11727},{"style":455},[11728],{"type":418,"value":11729},"          command",{"type":413,"tag":448,"props":11731,"children":11732},{"style":461},[11733],{"type":418,"value":464},{"type":413,"tag":448,"props":11735,"children":11736},{"style":467},[11737],{"type":418,"value":11738}," up\n",{"type":413,"tag":448,"props":11740,"children":11741},{"class":450,"line":3234},[11742,11747,11751],{"type":413,"tag":448,"props":11743,"children":11744},{"style":455},[11745],{"type":418,"value":11746},"          stack-name",{"type":413,"tag":448,"props":11748,"children":11749},{"style":461},[11750],{"type":418,"value":464},{"type":413,"tag":448,"props":11752,"children":11753},{"style":467},[11754],{"type":418,"value":11755}," dev\n",{"type":413,"tag":448,"props":11757,"children":11758},{"class":450,"line":3242},[11759,11764],{"type":413,"tag":448,"props":11760,"children":11761},{"style":455},[11762],{"type":418,"value":11763},"        env",{"type":413,"tag":448,"props":11765,"children":11766},{"style":461},[11767],{"type":418,"value":485},{"type":413,"tag":448,"props":11769,"children":11770},{"class":450,"line":3251},[11771,11776,11780],{"type":413,"tag":448,"props":11772,"children":11773},{"style":455},[11774],{"type":418,"value":11775},"          ARM_USE_OIDC",{"type":413,"tag":448,"props":11777,"children":11778},{"style":461},[11779],{"type":418,"value":464},{"type":413,"tag":448,"props":11781,"children":11782},{"style":477},[11783],{"type":418,"value":8826},{"type":413,"tag":448,"props":11785,"children":11786},{"class":450,"line":3260},[11787,11792,11796],{"type":413,"tag":448,"props":11788,"children":11789},{"style":455},[11790],{"type":418,"value":11791},"          PULUMI_ACCESS_TOKEN",{"type":413,"tag":448,"props":11793,"children":11794},{"style":461},[11795],{"type":418,"value":464},{"type":413,"tag":448,"props":11797,"children":11798},{"style":467},[11799],{"type":418,"value":11800}," ${{ secrets.PULUMI_ACCESS_TOKEN }}\n",{"type":413,"tag":448,"props":11802,"children":11803},{"class":450,"line":3360},[11804,11809,11813],{"type":413,"tag":448,"props":11805,"children":11806},{"style":455},[11807],{"type":418,"value":11808},"          ARM_CLIENT_ID",{"type":413,"tag":448,"props":11810,"children":11811},{"style":461},[11812],{"type":418,"value":464},{"type":413,"tag":448,"props":11814,"children":11815},{"style":467},[11816],{"type":418,"value":11817}," ${{ secrets.ARM_CLIENT_ID }}\n",{"type":413,"tag":448,"props":11819,"children":11820},{"class":450,"line":3368},[11821,11826,11830],{"type":413,"tag":448,"props":11822,"children":11823},{"style":455},[11824],{"type":418,"value":11825},"          ARM_TENANT_ID",{"type":413,"tag":448,"props":11827,"children":11828},{"style":461},[11829],{"type":418,"value":464},{"type":413,"tag":448,"props":11831,"children":11832},{"style":467},[11833],{"type":418,"value":11834}," ${{ secrets.ARM_TENANT_ID }}\n",{"type":413,"tag":448,"props":11836,"children":11837},{"class":450,"line":3377},[11838,11843,11847],{"type":413,"tag":448,"props":11839,"children":11840},{"style":455},[11841],{"type":418,"value":11842},"          ARM_SUBSCRIPTION_ID",{"type":413,"tag":448,"props":11844,"children":11845},{"style":461},[11846],{"type":418,"value":464},{"type":413,"tag":448,"props":11848,"children":11849},{"style":467},[11850],{"type":418,"value":11851}," ${{ secrets.ARM_SUBSCRIPTION_ID }}\n",{"type":413,"tag":414,"props":11853,"children":11854},{},[11855,11857,11863],{"type":418,"value":11856},"A permission section is required with 2 settings (more details ",{"type":413,"tag":813,"props":11858,"children":11861},{"href":11859,"rel":11860},"https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#adding-permissions-settings",[817],[11862],{"type":418,"value":1386},{"type":418,"value":11864},"):",{"type":413,"tag":3766,"props":11866,"children":11867},{},[11868,11879],{"type":413,"tag":2159,"props":11869,"children":11870},{},[11871,11877],{"type":413,"tag":444,"props":11872,"children":11874},{"className":11873},[],[11875],{"type":418,"value":11876},"id-token: write",{"type":418,"value":11878}," ➡️ needed to request the OIDC token",{"type":413,"tag":2159,"props":11880,"children":11881},{},[11882,11888],{"type":413,"tag":444,"props":11883,"children":11885},{"className":11884},[],[11886],{"type":418,"value":11887},"contents: read",{"type":418,"value":11889}," ➡️ needed to perform checkout action",{"type":413,"tag":841,"props":11891,"children":11892},{"icon":3815},[11893],{"type":413,"tag":414,"props":11894,"children":11895},{},[11896],{"type":418,"value":11897},"When you start to specify specific permissions, you have to specify all the permissions you need for the job because the default permissions won't apply anymore.",{"type":413,"tag":414,"props":11899,"children":11900},{},[11901,11903,11909,11911,11917,11919,11925],{"type":418,"value":11902},"The 3 steps following the checkout step are actions to specify the Node.js version to use, install and correctly configure ",{"type":413,"tag":813,"props":11904,"children":11907},{"href":11905,"rel":11906},"https://bordeauxcoders.com/series/pnpm-101",[817],[11908],{"type":418,"value":362},{"type":418,"value":11910},". We assume here the infrastructure will be provisioned using TypeScript (and Pulumi of course) but there would have been similar steps with other runtimes/languages (a ",{"type":413,"tag":444,"props":11912,"children":11914},{"className":11913},[],[11915],{"type":418,"value":11916},"setup-dotnet",{"type":418,"value":11918}," and a ",{"type":413,"tag":444,"props":11920,"children":11922},{"className":11921},[],[11923],{"type":418,"value":11924},"dotnet retore",{"type":418,"value":11926}," action for .NET for instance).",{"type":413,"tag":414,"props":11928,"children":11929},{},[11930,11932,11937,11939,11944,11946,11952,11954,11959],{"type":418,"value":11931},"The last action is the Pulumi action to provision the infrastructure by running the ",{"type":413,"tag":444,"props":11933,"children":11935},{"className":11934},[],[11936],{"type":418,"value":7832},{"type":418,"value":11938}," on the ",{"type":413,"tag":444,"props":11940,"children":11942},{"className":11941},[],[11943],{"type":418,"value":4049},{"type":418,"value":11945}," stack. We can see that this action uses environment variables whose values are based on the GitHub Actions secrets we defined earlier. To tell Pulumi to use OIDC, we just have to set the ",{"type":413,"tag":444,"props":11947,"children":11949},{"className":11948},[],[11950],{"type":418,"value":11951},"ARM_USE_OIDC",{"type":418,"value":11953}," environment variable to ",{"type":413,"tag":444,"props":11955,"children":11957},{"className":11956},[],[11958],{"type":418,"value":8952},{"type":418,"value":898},{"type":413,"tag":437,"props":11961,"children":11963},{"className":439,"code":11962,"language":441,"meta":401,"style":401},"        env:\n          ARM_USE_OIDC: true\n          PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}\n          ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}\n          ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}\n          ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }} \n",[11964],{"type":413,"tag":444,"props":11965,"children":11966},{"__ignoreMap":401},[11967,11978,11993,12008,12023,12038],{"type":413,"tag":448,"props":11968,"children":11969},{"class":450,"line":451},[11970,11974],{"type":413,"tag":448,"props":11971,"children":11972},{"style":455},[11973],{"type":418,"value":11763},{"type":413,"tag":448,"props":11975,"children":11976},{"style":461},[11977],{"type":418,"value":485},{"type":413,"tag":448,"props":11979,"children":11980},{"class":450,"line":473},[11981,11985,11989],{"type":413,"tag":448,"props":11982,"children":11983},{"style":455},[11984],{"type":418,"value":11775},{"type":413,"tag":448,"props":11986,"children":11987},{"style":461},[11988],{"type":418,"value":464},{"type":413,"tag":448,"props":11990,"children":11991},{"style":477},[11992],{"type":418,"value":8826},{"type":413,"tag":448,"props":11994,"children":11995},{"class":450,"line":488},[11996,12000,12004],{"type":413,"tag":448,"props":11997,"children":11998},{"style":455},[11999],{"type":418,"value":11791},{"type":413,"tag":448,"props":12001,"children":12002},{"style":461},[12003],{"type":418,"value":464},{"type":413,"tag":448,"props":12005,"children":12006},{"style":467},[12007],{"type":418,"value":11800},{"type":413,"tag":448,"props":12009,"children":12010},{"class":450,"line":501},[12011,12015,12019],{"type":413,"tag":448,"props":12012,"children":12013},{"style":455},[12014],{"type":418,"value":11808},{"type":413,"tag":448,"props":12016,"children":12017},{"style":461},[12018],{"type":418,"value":464},{"type":413,"tag":448,"props":12020,"children":12021},{"style":467},[12022],{"type":418,"value":11817},{"type":413,"tag":448,"props":12024,"children":12025},{"class":450,"line":511},[12026,12030,12034],{"type":413,"tag":448,"props":12027,"children":12028},{"style":455},[12029],{"type":418,"value":11825},{"type":413,"tag":448,"props":12031,"children":12032},{"style":461},[12033],{"type":418,"value":464},{"type":413,"tag":448,"props":12035,"children":12036},{"style":467},[12037],{"type":418,"value":11834},{"type":413,"tag":448,"props":12039,"children":12040},{"class":450,"line":524},[12041,12045,12049],{"type":413,"tag":448,"props":12042,"children":12043},{"style":455},[12044],{"type":418,"value":11842},{"type":413,"tag":448,"props":12046,"children":12047},{"style":461},[12048],{"type":418,"value":464},{"type":413,"tag":448,"props":12050,"children":12051},{"style":467},[12052],{"type":418,"value":11851},{"type":413,"tag":414,"props":12054,"children":12055},{},[12056,12058,12064,12066,12073],{"type":418,"value":12057},"A GitHub Actions secret we did not talk about is ",{"type":413,"tag":444,"props":12059,"children":12061},{"className":12060},[],[12062],{"type":418,"value":12063},"PULUMI_ACCESS_TOKEN",{"type":418,"value":12065}," that is a ",{"type":413,"tag":813,"props":12067,"children":12070},{"href":12068,"rel":12069},"https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/",[817],[12071],{"type":418,"value":12072},"Pulumi access token",{"type":418,"value":12074}," to use Pulumi Cloud as our backend to store the infrastructure state and encrypt secrets. This token should be:",{"type":413,"tag":2155,"props":12076,"children":12077},{},[12078,12090,12101],{"type":413,"tag":2159,"props":12079,"children":12080},{},[12081,12083,12089],{"type":418,"value":12082},"Created from Pulumi Cloud (following the documentation ",{"type":413,"tag":813,"props":12084,"children":12087},{"href":12085,"rel":12086},"https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/#personal-access-tokens",[817],[12088],{"type":418,"value":1386},{"type":418,"value":2031},{"type":413,"tag":2159,"props":12091,"children":12092},{},[12093,12095],{"type":418,"value":12094},"Stored in the stack configuration using the following command ",{"type":413,"tag":444,"props":12096,"children":12098},{"className":12097},[],[12099],{"type":418,"value":12100},"pulumi config set pulumiTokenForRepository ******* --secret",{"type":413,"tag":2159,"props":12102,"children":12103},{},[12104,12106],{"type":418,"value":12105},"Stored in a GitHub Actions secret using this code",{"type":413,"tag":437,"props":12107,"children":12109},{"className":8635,"code":12108,"language":357,"meta":401,"style":401},"new github.ActionsSecret(\"pulumiAccessToken\", {\n  repository: repository.name,\n  secretName: \"PULUMI_ACCESS_TOKEN\",\n  plaintextValue: config.requireSecret(\"pulumiTokenForRepository\"),\n});\n",[12110],{"type":413,"tag":444,"props":12111,"children":12112},{"__ignoreMap":401},[12113,12157,12184,12211,12260],{"type":413,"tag":448,"props":12114,"children":12115},{"class":450,"line":451},[12116,12120,12124,12128,12132,12136,12140,12145,12149,12153],{"type":413,"tag":448,"props":12117,"children":12118},{"style":461},[12119],{"type":418,"value":6133},{"type":413,"tag":448,"props":12121,"children":12122},{"style":1029},[12123],{"type":418,"value":8717},{"type":413,"tag":448,"props":12125,"children":12126},{"style":461},[12127],{"type":418,"value":898},{"type":413,"tag":448,"props":12129,"children":12130},{"style":2000},[12131],{"type":418,"value":10478},{"type":413,"tag":448,"props":12133,"children":12134},{"style":1029},[12135],{"type":418,"value":2041},{"type":413,"tag":448,"props":12137,"children":12138},{"style":461},[12139],{"type":418,"value":1183},{"type":413,"tag":448,"props":12141,"children":12142},{"style":467},[12143],{"type":418,"value":12144},"pulumiAccessToken",{"type":413,"tag":448,"props":12146,"children":12147},{"style":461},[12148],{"type":418,"value":1183},{"type":413,"tag":448,"props":12150,"children":12151},{"style":461},[12152],{"type":418,"value":2059},{"type":413,"tag":448,"props":12154,"children":12155},{"style":461},[12156],{"type":418,"value":8752},{"type":413,"tag":448,"props":12158,"children":12159},{"class":450,"line":473},[12160,12164,12168,12172,12176,12180],{"type":413,"tag":448,"props":12161,"children":12162},{"style":455},[12163],{"type":418,"value":10300},{"type":413,"tag":448,"props":12165,"children":12166},{"style":461},[12167],{"type":418,"value":464},{"type":413,"tag":448,"props":12169,"children":12170},{"style":1029},[12171],{"type":418,"value":4675},{"type":413,"tag":448,"props":12173,"children":12174},{"style":461},[12175],{"type":418,"value":898},{"type":413,"tag":448,"props":12177,"children":12178},{"style":1029},[12179],{"type":418,"value":458},{"type":413,"tag":448,"props":12181,"children":12182},{"style":461},[12183],{"type":418,"value":4378},{"type":413,"tag":448,"props":12185,"children":12186},{"class":450,"line":488},[12187,12191,12195,12199,12203,12207],{"type":413,"tag":448,"props":12188,"children":12189},{"style":455},[12190],{"type":418,"value":10537},{"type":413,"tag":448,"props":12192,"children":12193},{"style":461},[12194],{"type":418,"value":464},{"type":413,"tag":448,"props":12196,"children":12197},{"style":461},[12198],{"type":418,"value":995},{"type":413,"tag":448,"props":12200,"children":12201},{"style":467},[12202],{"type":418,"value":12063},{"type":413,"tag":448,"props":12204,"children":12205},{"style":461},[12206],{"type":418,"value":1183},{"type":413,"tag":448,"props":12208,"children":12209},{"style":461},[12210],{"type":418,"value":4378},{"type":413,"tag":448,"props":12212,"children":12213},{"class":450,"line":501},[12214,12218,12222,12226,12230,12235,12239,12243,12248,12252,12256],{"type":413,"tag":448,"props":12215,"children":12216},{"style":455},[12217],{"type":418,"value":10565},{"type":413,"tag":448,"props":12219,"children":12220},{"style":461},[12221],{"type":418,"value":464},{"type":413,"tag":448,"props":12223,"children":12224},{"style":1029},[12225],{"type":418,"value":4181},{"type":413,"tag":448,"props":12227,"children":12228},{"style":461},[12229],{"type":418,"value":898},{"type":413,"tag":448,"props":12231,"children":12232},{"style":2000},[12233],{"type":418,"value":12234},"requireSecret",{"type":413,"tag":448,"props":12236,"children":12237},{"style":1029},[12238],{"type":418,"value":2041},{"type":413,"tag":448,"props":12240,"children":12241},{"style":461},[12242],{"type":418,"value":1183},{"type":413,"tag":448,"props":12244,"children":12245},{"style":467},[12246],{"type":418,"value":12247},"pulumiTokenForRepository",{"type":413,"tag":448,"props":12249,"children":12250},{"style":461},[12251],{"type":418,"value":1183},{"type":413,"tag":448,"props":12253,"children":12254},{"style":1029},[12255],{"type":418,"value":2031},{"type":413,"tag":448,"props":12257,"children":12258},{"style":461},[12259],{"type":418,"value":4378},{"type":413,"tag":448,"props":12261,"children":12262},{"class":450,"line":511},[12263,12267,12271],{"type":413,"tag":448,"props":12264,"children":12265},{"style":461},[12266],{"type":418,"value":1825},{"type":413,"tag":448,"props":12268,"children":12269},{"style":1029},[12270],{"type":418,"value":2031},{"type":413,"tag":448,"props":12272,"children":12273},{"style":461},[12274],{"type":418,"value":5802},{"type":413,"tag":414,"props":12276,"children":12277},{},[12278],{"type":418,"value":12279},"The last thing to do is to add this workflow file to the GitHub repository:",{"type":413,"tag":437,"props":12281,"children":12283},{"className":8635,"code":12282,"language":357,"meta":401,"style":401},"import { readFileSync } from \"fs\";\n\nconst pipelineContent = readFileSync(\"main.yml\", \"utf-8\");\nnew github.RepositoryFile(\"pipelineRepositoryFile\", {\n  repository: repository.name,\n  branch: \"main\",\n  file: \".github/workflows/main.yml\",\n  content: pipelineContent,\n  commitMessage: \"Add preconfigured pipeline file\",\n  commitAuthor: \"Alexandre Nédélec\",\n  commitEmail: \"15186176+TechWatching@users.noreply.github.com\",\n  overwriteOnCreate: true,\n});\n",[12284],{"type":413,"tag":444,"props":12285,"children":12286},{"__ignoreMap":401},[12287,12328,12335,12397,12442,12469,12497,12526,12547,12575,12604,12633,12654],{"type":413,"tag":448,"props":12288,"children":12289},{"class":450,"line":451},[12290,12294,12298,12303,12307,12311,12315,12320,12324],{"type":413,"tag":448,"props":12291,"children":12292},{"style":785},[12293],{"type":418,"value":8648},{"type":413,"tag":448,"props":12295,"children":12296},{"style":461},[12297],{"type":418,"value":9093},{"type":413,"tag":448,"props":12299,"children":12300},{"style":1029},[12301],{"type":418,"value":12302}," readFileSync",{"type":413,"tag":448,"props":12304,"children":12305},{"style":461},[12306],{"type":418,"value":9120},{"type":413,"tag":448,"props":12308,"children":12309},{"style":785},[12310],{"type":418,"value":9678},{"type":413,"tag":448,"props":12312,"children":12313},{"style":461},[12314],{"type":418,"value":995},{"type":413,"tag":448,"props":12316,"children":12317},{"style":467},[12318],{"type":418,"value":12319},"fs",{"type":413,"tag":448,"props":12321,"children":12322},{"style":461},[12323],{"type":418,"value":1183},{"type":413,"tag":448,"props":12325,"children":12326},{"style":461},[12327],{"type":418,"value":5802},{"type":413,"tag":448,"props":12329,"children":12330},{"class":450,"line":473},[12331],{"type":413,"tag":448,"props":12332,"children":12333},{"emptyLinePlaceholder":505},[12334],{"type":418,"value":508},{"type":413,"tag":448,"props":12336,"children":12337},{"class":450,"line":488},[12338,12342,12347,12351,12355,12359,12363,12368,12372,12376,12380,12385,12389,12393],{"type":413,"tag":448,"props":12339,"children":12340},{"style":6130},[12341],{"type":418,"value":8699},{"type":413,"tag":448,"props":12343,"children":12344},{"style":1029},[12345],{"type":418,"value":12346}," pipelineContent ",{"type":413,"tag":448,"props":12348,"children":12349},{"style":461},[12350],{"type":418,"value":1037},{"type":413,"tag":448,"props":12352,"children":12353},{"style":2000},[12354],{"type":418,"value":12302},{"type":413,"tag":448,"props":12356,"children":12357},{"style":1029},[12358],{"type":418,"value":2041},{"type":413,"tag":448,"props":12360,"children":12361},{"style":461},[12362],{"type":418,"value":1183},{"type":413,"tag":448,"props":12364,"children":12365},{"style":467},[12366],{"type":418,"value":12367},"main.yml",{"type":413,"tag":448,"props":12369,"children":12370},{"style":461},[12371],{"type":418,"value":1183},{"type":413,"tag":448,"props":12373,"children":12374},{"style":461},[12375],{"type":418,"value":2059},{"type":413,"tag":448,"props":12377,"children":12378},{"style":461},[12379],{"type":418,"value":995},{"type":413,"tag":448,"props":12381,"children":12382},{"style":467},[12383],{"type":418,"value":12384},"utf-8",{"type":413,"tag":448,"props":12386,"children":12387},{"style":461},[12388],{"type":418,"value":1183},{"type":413,"tag":448,"props":12390,"children":12391},{"style":1029},[12392],{"type":418,"value":2031},{"type":413,"tag":448,"props":12394,"children":12395},{"style":461},[12396],{"type":418,"value":5802},{"type":413,"tag":448,"props":12398,"children":12399},{"class":450,"line":501},[12400,12404,12408,12412,12417,12421,12425,12430,12434,12438],{"type":413,"tag":448,"props":12401,"children":12402},{"style":461},[12403],{"type":418,"value":6133},{"type":413,"tag":448,"props":12405,"children":12406},{"style":1029},[12407],{"type":418,"value":8717},{"type":413,"tag":448,"props":12409,"children":12410},{"style":461},[12411],{"type":418,"value":898},{"type":413,"tag":448,"props":12413,"children":12414},{"style":2000},[12415],{"type":418,"value":12416},"RepositoryFile",{"type":413,"tag":448,"props":12418,"children":12419},{"style":1029},[12420],{"type":418,"value":2041},{"type":413,"tag":448,"props":12422,"children":12423},{"style":461},[12424],{"type":418,"value":1183},{"type":413,"tag":448,"props":12426,"children":12427},{"style":467},[12428],{"type":418,"value":12429},"pipelineRepositoryFile",{"type":413,"tag":448,"props":12431,"children":12432},{"style":461},[12433],{"type":418,"value":1183},{"type":413,"tag":448,"props":12435,"children":12436},{"style":461},[12437],{"type":418,"value":2059},{"type":413,"tag":448,"props":12439,"children":12440},{"style":461},[12441],{"type":418,"value":8752},{"type":413,"tag":448,"props":12443,"children":12444},{"class":450,"line":511},[12445,12449,12453,12457,12461,12465],{"type":413,"tag":448,"props":12446,"children":12447},{"style":455},[12448],{"type":418,"value":10300},{"type":413,"tag":448,"props":12450,"children":12451},{"style":461},[12452],{"type":418,"value":464},{"type":413,"tag":448,"props":12454,"children":12455},{"style":1029},[12456],{"type":418,"value":4675},{"type":413,"tag":448,"props":12458,"children":12459},{"style":461},[12460],{"type":418,"value":898},{"type":413,"tag":448,"props":12462,"children":12463},{"style":1029},[12464],{"type":418,"value":458},{"type":413,"tag":448,"props":12466,"children":12467},{"style":461},[12468],{"type":418,"value":4378},{"type":413,"tag":448,"props":12470,"children":12471},{"class":450,"line":524},[12472,12477,12481,12485,12489,12493],{"type":413,"tag":448,"props":12473,"children":12474},{"style":455},[12475],{"type":418,"value":12476},"  branch",{"type":413,"tag":448,"props":12478,"children":12479},{"style":461},[12480],{"type":418,"value":464},{"type":413,"tag":448,"props":12482,"children":12483},{"style":461},[12484],{"type":418,"value":995},{"type":413,"tag":448,"props":12486,"children":12487},{"style":467},[12488],{"type":418,"value":8035},{"type":413,"tag":448,"props":12490,"children":12491},{"style":461},[12492],{"type":418,"value":1183},{"type":413,"tag":448,"props":12494,"children":12495},{"style":461},[12496],{"type":418,"value":4378},{"type":413,"tag":448,"props":12498,"children":12499},{"class":450,"line":542},[12500,12505,12509,12513,12518,12522],{"type":413,"tag":448,"props":12501,"children":12502},{"style":455},[12503],{"type":418,"value":12504},"  file",{"type":413,"tag":448,"props":12506,"children":12507},{"style":461},[12508],{"type":418,"value":464},{"type":413,"tag":448,"props":12510,"children":12511},{"style":461},[12512],{"type":418,"value":995},{"type":413,"tag":448,"props":12514,"children":12515},{"style":467},[12516],{"type":418,"value":12517},".github/workflows/main.yml",{"type":413,"tag":448,"props":12519,"children":12520},{"style":461},[12521],{"type":418,"value":1183},{"type":413,"tag":448,"props":12523,"children":12524},{"style":461},[12525],{"type":418,"value":4378},{"type":413,"tag":448,"props":12527,"children":12528},{"class":450,"line":560},[12529,12534,12538,12543],{"type":413,"tag":448,"props":12530,"children":12531},{"style":455},[12532],{"type":418,"value":12533},"  content",{"type":413,"tag":448,"props":12535,"children":12536},{"style":461},[12537],{"type":418,"value":464},{"type":413,"tag":448,"props":12539,"children":12540},{"style":1029},[12541],{"type":418,"value":12542}," pipelineContent",{"type":413,"tag":448,"props":12544,"children":12545},{"style":461},[12546],{"type":418,"value":4378},{"type":413,"tag":448,"props":12548,"children":12549},{"class":450,"line":573},[12550,12555,12559,12563,12567,12571],{"type":413,"tag":448,"props":12551,"children":12552},{"style":455},[12553],{"type":418,"value":12554},"  commitMessage",{"type":413,"tag":448,"props":12556,"children":12557},{"style":461},[12558],{"type":418,"value":464},{"type":413,"tag":448,"props":12560,"children":12561},{"style":461},[12562],{"type":418,"value":995},{"type":413,"tag":448,"props":12564,"children":12565},{"style":467},[12566],{"type":418,"value":7100},{"type":413,"tag":448,"props":12568,"children":12569},{"style":461},[12570],{"type":418,"value":1183},{"type":413,"tag":448,"props":12572,"children":12573},{"style":461},[12574],{"type":418,"value":4378},{"type":413,"tag":448,"props":12576,"children":12577},{"class":450,"line":586},[12578,12583,12587,12591,12596,12600],{"type":413,"tag":448,"props":12579,"children":12580},{"style":455},[12581],{"type":418,"value":12582},"  commitAuthor",{"type":413,"tag":448,"props":12584,"children":12585},{"style":461},[12586],{"type":418,"value":464},{"type":413,"tag":448,"props":12588,"children":12589},{"style":461},[12590],{"type":418,"value":995},{"type":413,"tag":448,"props":12592,"children":12593},{"style":467},[12594],{"type":418,"value":12595},"Alexandre Nédélec",{"type":413,"tag":448,"props":12597,"children":12598},{"style":461},[12599],{"type":418,"value":1183},{"type":413,"tag":448,"props":12601,"children":12602},{"style":461},[12603],{"type":418,"value":4378},{"type":413,"tag":448,"props":12605,"children":12606},{"class":450,"line":604},[12607,12612,12616,12620,12625,12629],{"type":413,"tag":448,"props":12608,"children":12609},{"style":455},[12610],{"type":418,"value":12611},"  commitEmail",{"type":413,"tag":448,"props":12613,"children":12614},{"style":461},[12615],{"type":418,"value":464},{"type":413,"tag":448,"props":12617,"children":12618},{"style":461},[12619],{"type":418,"value":995},{"type":413,"tag":448,"props":12621,"children":12622},{"style":467},[12623],{"type":418,"value":12624},"15186176+TechWatching@users.noreply.github.com",{"type":413,"tag":448,"props":12626,"children":12627},{"style":461},[12628],{"type":418,"value":1183},{"type":413,"tag":448,"props":12630,"children":12631},{"style":461},[12632],{"type":418,"value":4378},{"type":413,"tag":448,"props":12634,"children":12635},{"class":450,"line":617},[12636,12641,12645,12650],{"type":413,"tag":448,"props":12637,"children":12638},{"style":455},[12639],{"type":418,"value":12640},"  overwriteOnCreate",{"type":413,"tag":448,"props":12642,"children":12643},{"style":461},[12644],{"type":418,"value":464},{"type":413,"tag":448,"props":12646,"children":12647},{"style":477},[12648],{"type":418,"value":12649}," true",{"type":413,"tag":448,"props":12651,"children":12652},{"style":461},[12653],{"type":418,"value":4378},{"type":413,"tag":448,"props":12655,"children":12656},{"class":450,"line":650},[12657,12661,12665],{"type":413,"tag":448,"props":12658,"children":12659},{"style":461},[12660],{"type":418,"value":1825},{"type":413,"tag":448,"props":12662,"children":12663},{"style":1029},[12664],{"type":418,"value":2031},{"type":413,"tag":448,"props":12666,"children":12667},{"style":461},[12668],{"type":418,"value":5802},{"type":413,"tag":414,"props":12670,"children":12671},{},[12672],{"type":418,"value":12673},"This code:",{"type":413,"tag":2155,"props":12675,"children":12676},{},[12677,12689,12701],{"type":413,"tag":2159,"props":12678,"children":12679},{},[12680,12682,12687],{"type":418,"value":12681},"reads the ",{"type":413,"tag":444,"props":12683,"children":12685},{"className":12684},[],[12686],{"type":418,"value":12367},{"type":418,"value":12688}," file that contains the workflow we saw previously",{"type":413,"tag":2159,"props":12690,"children":12691},{},[12692,12694,12699],{"type":418,"value":12693},"creates a file with this content in the repository in the ",{"type":413,"tag":444,"props":12695,"children":12697},{"className":12696},[],[12698],{"type":418,"value":8053},{"type":418,"value":12700}," folder for the GitHub Actions workflows",{"type":413,"tag":2159,"props":12702,"children":12703},{},[12704],{"type":418,"value":12705},"makes a commit when creating the file (or modifying it)",{"type":413,"tag":841,"props":12707,"children":12708},{"icon":843},[12709],{"type":413,"tag":414,"props":12710,"children":12711},{},[12712,12714,12720,12722,12727],{"type":418,"value":12713},"To read the YAML file, I use the ",{"type":413,"tag":444,"props":12715,"children":12717},{"className":12716},[],[12718],{"type":418,"value":12719},"readFileSync",{"type":418,"value":12721}," method from the File System API ",{"type":413,"tag":444,"props":12723,"children":12725},{"className":12724},[],[12726],{"type":418,"value":12319},{"type":418,"value":12728},". That's one of the things I love about Pulumi: you use the things you already know and that already exist in your ecosystem. No need to look for a module or wait for someone to write one, there is probably something standard or a popular community library you can use.",{"type":413,"tag":420,"props":12730,"children":12732},{"id":12731},"test-the-azure-ready-github-repository",[12733],{"type":418,"value":12734},"Test the Azure-Ready GitHub Repository",{"type":413,"tag":414,"props":12736,"children":12737},{},[12738,12740,12745],{"type":418,"value":12739},"Now that the infrastructure code to provision the Azure-Ready GitHub repository is written, let's run it with the ",{"type":413,"tag":444,"props":12741,"children":12743},{"className":12742},[],[12744],{"type":418,"value":7832},{"type":418,"value":12746}," command and see if it works!",{"type":413,"tag":414,"props":12748,"children":12749},{},[12750],{"type":413,"tag":832,"props":12751,"children":12755},{"alt":12752,"className":12753,"src":12754,"width":3906},"Ouput of the pulumi up command with all the resources created.",[836,837],"/posts/images/azurereadygithub_pulumi_1.webp",[],{"type":413,"tag":414,"props":12757,"children":12758},{},[12759],{"type":418,"value":12760},"All the resources are correctly created and our new GitHub repository is ready to be used.",{"type":413,"tag":414,"props":12762,"children":12763},{},[12764],{"type":413,"tag":832,"props":12765,"children":12769},{"alt":12766,"className":12767,"src":12768},"Picture of the Azure Ready GitHub repository",[836,837],"/posts/images/azurereadygithub_github_2.webp",[],{"type":413,"tag":414,"props":12771,"children":12772},{},[12773],{"type":418,"value":12774},"Let's clone it.",{"type":413,"tag":437,"props":12776,"children":12778},{"className":937,"code":12777,"language":939,"meta":401,"style":401},"git clone https://github.com/TechWatching/azure-ready-repository; cd azure-ready-repository\n",[12779],{"type":413,"tag":444,"props":12780,"children":12781},{"__ignoreMap":401},[12782],{"type":413,"tag":448,"props":12783,"children":12784},{"class":450,"line":451},[12785,12789,12794,12799,12804,12809],{"type":413,"tag":448,"props":12786,"children":12787},{"style":949},[12788],{"type":418,"value":241},{"type":413,"tag":448,"props":12790,"children":12791},{"style":467},[12792],{"type":418,"value":12793}," clone",{"type":413,"tag":448,"props":12795,"children":12796},{"style":467},[12797],{"type":418,"value":12798}," https://github.com/TechWatching/azure-ready-repository",{"type":413,"tag":448,"props":12800,"children":12801},{"style":461},[12802],{"type":418,"value":12803},";",{"type":413,"tag":448,"props":12805,"children":12806},{"style":2000},[12807],{"type":418,"value":12808}," cd",{"type":413,"tag":448,"props":12810,"children":12811},{"style":467},[12812],{"type":418,"value":12813}," azure-ready-repository\n",{"type":413,"tag":414,"props":12815,"children":12816},{},[12817],{"type":418,"value":12818},"We want to verify that the GitHub project is properly configured and can provision Azure resources from its GitHub Actions workflow.",{"type":413,"tag":414,"props":12820,"children":12821},{},[12822],{"type":418,"value":12823},"Let's add some infrastructure code that provisions a few Azure resources to check that:",{"type":413,"tag":437,"props":12825,"children":12827},{"className":937,"code":12826,"language":939,"meta":401,"style":401},"pulumi new azure-typescript -n \"AzureReadyGitHuRepository\" -y --force\n",[12828],{"type":413,"tag":444,"props":12829,"children":12830},{"__ignoreMap":401},[12831],{"type":413,"tag":448,"props":12832,"children":12833},{"class":450,"line":451},[12834,12838,12842,12847,12851,12855,12860,12864,12869],{"type":413,"tag":448,"props":12835,"children":12836},{"style":949},[12837],{"type":418,"value":311},{"type":413,"tag":448,"props":12839,"children":12840},{"style":467},[12841],{"type":418,"value":3943},{"type":413,"tag":448,"props":12843,"children":12844},{"style":467},[12845],{"type":418,"value":12846}," azure-typescript",{"type":413,"tag":448,"props":12848,"children":12849},{"style":467},[12850],{"type":418,"value":3953},{"type":413,"tag":448,"props":12852,"children":12853},{"style":461},[12854],{"type":418,"value":995},{"type":413,"tag":448,"props":12856,"children":12857},{"style":467},[12858],{"type":418,"value":12859},"AzureReadyGitHuRepository",{"type":413,"tag":448,"props":12861,"children":12862},{"style":461},[12863],{"type":418,"value":1183},{"type":413,"tag":448,"props":12865,"children":12866},{"style":467},[12867],{"type":418,"value":12868}," -y",{"type":413,"tag":448,"props":12870,"children":12871},{"style":467},[12872],{"type":418,"value":12873}," --force\n",{"type":413,"tag":414,"props":12875,"children":12876},{},[12877,12878,12884],{"type":418,"value":1930},{"type":413,"tag":444,"props":12879,"children":12881},{"className":12880},[],[12882],{"type":418,"value":12883},"--force",{"type":418,"value":12885}," option allows us to create the code within a non-empty directory.",{"type":413,"tag":414,"props":12887,"children":12888},{},[12889,12891,12897],{"type":418,"value":12890},"I used the ",{"type":413,"tag":444,"props":12892,"children":12894},{"className":12893},[],[12895],{"type":418,"value":12896},"azure-typescript",{"type":418,"value":12898}," template that creates a storage account and outputs retrieve its primary access key.",{"type":413,"tag":841,"props":12900,"children":12901},{"icon":4254},[12902],{"type":413,"tag":414,"props":12903,"children":12904},{},[12905,12907,12914],{"type":418,"value":12906},"In the SDK, the outputs of the function that lists the storage access keys are not currently marked as secrets. There is currently an ",{"type":413,"tag":813,"props":12908,"children":12911},{"href":12909,"rel":12910},"https://github.com/pulumi/pulumi-azure-native/issues/2408",[817],[12912],{"type":418,"value":12913},"open issue",{"type":418,"value":12915}," to change that but in the meantime, I have just modified the code to label the stack output as secret ensuring its encryption.",{"type":413,"tag":414,"props":12917,"children":12918},{},[12919,12921,12927,12929,12935],{"type":418,"value":12920},"Let's run a ",{"type":413,"tag":444,"props":12922,"children":12924},{"className":12923},[],[12925],{"type":418,"value":12926},"pnpm install",{"type":418,"value":12928}," to install the dependencies and generate the ",{"type":413,"tag":444,"props":12930,"children":12932},{"className":12931},[],[12933],{"type":418,"value":12934},"pnpm-lock.yaml",{"type":418,"value":12936}," file. Then, we can push the code to GitHub and run the pipeline to see how it goes.",{"type":413,"tag":414,"props":12938,"children":12939},{},[12940],{"type":413,"tag":832,"props":12941,"children":12945},{"alt":12942,"className":12943,"src":12944},"Logs of the pipeline run showing that the workflow successfully created a storage account.",[836,837],"/posts/images/azurereadygithub_github_3.webp",[],{"type":413,"tag":414,"props":12947,"children":12948},{},[12949],{"type":418,"value":12950},"That's it, we succeeded to provision a storage account from our new GitHub repository whose creation and configuration were entirely automated using Pulumi.",{"type":413,"tag":420,"props":12952,"children":12953},{"id":7882},[12954],{"type":418,"value":7885},{"type":413,"tag":866,"props":12956,"children":12958},{"id":12957},"additional-information",[12959],{"type":418,"value":12960},"Additional information",{"type":413,"tag":414,"props":12962,"children":12963},{},[12964],{"type":418,"value":12965},"There are different platforms you can use to host your Git repositories: GitHub, GitLab, and Azure DevOps to name a few. We use GitHub in this article but you can easily apply the same logic with other platforms (Pulumi has providers for GitLab and Azure DevOps as well).",{"type":413,"tag":414,"props":12967,"children":12968},{},[12969],{"type":418,"value":12970},"Even though the Azure-Ready GitHub repository is provisioned using Pulumi, there's nothing stopping you from using another Infrastructure as Code solution that supports Azure OIDC (such as Azure CLI, which was mentioned in the article, Azure Bicep, or even Terraform) in the GitHub Actions workflow of the created repository. You don't even have to provision infrastructure; you can use this workflow to simply deploy an application to an existing Azure resource.",{"type":413,"tag":866,"props":12972,"children":12974},{"id":12973},"potential-enhancements",[12975],{"type":418,"value":12976},"Potential Enhancements",{"type":413,"tag":414,"props":12978,"children":12979},{},[12980],{"type":418,"value":12981},"There are many aspects that could be improved in the infrastructure code provisioning the Azure-Ready GitHub repository, but I believe the current solution serves as a good starting point. Nevertheless, here are some ideas for potential enhancements:",{"type":413,"tag":3766,"props":12983,"children":12984},{},[12985,12990,12995],{"type":413,"tag":2159,"props":12986,"children":12987},{},[12988],{"type":418,"value":12989},"make additional items, such as the commit author, configurable",{"type":413,"tag":2159,"props":12991,"children":12992},{},[12993],{"type":418,"value":12994},"authorize an environment and not only a branch to retrieve an Azure token",{"type":413,"tag":2159,"props":12996,"children":12997},{},[12998],{"type":418,"value":12999},"use environment variables/secrets instead of variable/secrets at the repository scope",{"type":413,"tag":414,"props":13001,"children":13002},{},[13003],{"type":418,"value":13004},"I think it would be interesting as well to put that code behind an API or a Web application using Pulumi Automation API to have a self-service solution to create Azure-Ready GitHub repository on the fly.",{"type":413,"tag":866,"props":13006,"children":13008},{"id":13007},"related-articles",[13009],{"type":418,"value":13010},"Related articles",{"type":413,"tag":414,"props":13012,"children":13013},{},[13014],{"type":418,"value":13015},"Here are some articles on the same topic I wanted to mention:",{"type":413,"tag":3766,"props":13017,"children":13018},{},[13019,13050,13078],{"type":413,"tag":2159,"props":13020,"children":13021},{},[13022,13032,13034,13039,13043,13048],{"type":413,"tag":813,"props":13023,"children":13026},{"href":13024,"rel":13025},"https://leebriggs.co.uk/blog/2022/01/23/gha-cloud-credentials",[817],[13027],{"type":413,"tag":3838,"props":13028,"children":13029},{},[13030],{"type":418,"value":13031},"Stop using static cloud credentials in GitHub Actions",{"type":418,"value":13033}," ",{"type":413,"tag":3838,"props":13035,"children":13036},{},[13037],{"type":418,"value":13038},"by Lee Briggs",{"type":413,"tag":13040,"props":13041,"children":13042},"br",{},[],{"type":413,"tag":3838,"props":13044,"children":13045},{},[13046],{"type":418,"value":13047},"➡️",{"type":418,"value":13049}," This post provides examples for configuring OIDC authentication with GitHub Actions for AWS, Azure, and GCP. The code for Azure is quite similar to the code I showed here. Yet, it doesn't go so far as to initialize a pipeline ready to deploy resources with Pulumi. Anyway, it's awesome to have the code for all 3 major providers.",{"type":413,"tag":2159,"props":13051,"children":13052},{},[13053,13063,13064,13069,13072,13076],{"type":413,"tag":813,"props":13054,"children":13057},{"href":13055,"rel":13056},"https://xaviergeerinck.com/2023/05/16/configuring-github-actions-to-azure-authentication-with-oidc/",[817],[13058],{"type":413,"tag":3838,"props":13059,"children":13060},{},[13061],{"type":418,"value":13062},"Configuring GitHub Actions to Azure authentication with OIDC",{"type":418,"value":13033},{"type":413,"tag":3838,"props":13065,"children":13066},{},[13067],{"type":418,"value":13068},"by Xavier Geerinck",{"type":413,"tag":13040,"props":13070,"children":13071},{},[],{"type":413,"tag":3838,"props":13073,"children":13074},{},[13075],{"type":418,"value":13047},{"type":418,"value":13077},"This post also shows how to configure OIDC authentication with GitHub Actions and Azure but using an Azure CLI script. Although the GitHub repository creation and configuration are done manually, automating the Azure part with a few lines of script is nice.",{"type":413,"tag":2159,"props":13079,"children":13080},{},[13081,13091,13092,13097,13100],{"type":413,"tag":813,"props":13082,"children":13085},{"href":13083,"rel":13084},"https://samcogan.com/getting-rid-of-passwords-for-deployment-with-pulumi-oidc-support/",[817],[13086],{"type":413,"tag":3838,"props":13087,"children":13088},{},[13089],{"type":418,"value":13090},"Getting Rid of Passwords for Deployment with Pulumi OIDC Support",{"type":418,"value":13033},{"type":413,"tag":3838,"props":13093,"children":13094},{},[13095],{"type":418,"value":13096},"by Sam Cogan",{"type":413,"tag":13040,"props":13098,"children":13099},{},[],{"type":418,"value":13101},"\n➡️ If you don't care about automating everything and simply want to configure OIDC authentication through the Azure portal, that's the post you will want to read. There is also an example of a pipeline to provision Azure infrastructure using a .NET Pulumi program.",{"type":413,"tag":866,"props":13103,"children":13105},{"id":13104},"complete-code-solution",[13106],{"type":418,"value":13107},"Complete code solution",{"type":413,"tag":414,"props":13109,"children":13110},{},[13111],{"type":418,"value":13112},"In this article, I aimed to provide a step-by-step explanation of how to automate the creation of a GitHub repository with a properly configured workflow to interact with Azure using OpenID Connect. Consequently, the article turned out to be quite lengthy. I apologize for that, but I didn't want to present the code without adequate explanation.",{"type":413,"tag":414,"props":13114,"children":13115},{},[13116],{"type":418,"value":13117},"Anyway, now that we've covered everything, here is the complete code, which is just 75 lines long:",{"type":413,"tag":437,"props":13119,"children":13121},{"className":8635,"code":13120,"language":357,"meta":401,"style":401},"import * as pulumi from \"@pulumi/pulumi\";\nimport * as github from \"@pulumi/github\";\nimport * as azuread from \"@pulumi/azuread\";\nimport * as authorization from \"@pulumi/azure-native/authorization\";\nimport { azureBuiltInRoles } from \"./builtInRoles\";\nimport { readFileSync } from \"fs\";\n\nconst config = new pulumi.Config();\n\nconst repository = new github.Repository(\"azure-ready-repository\", {\n  name: \"azure-ready-repository\",\n  visibility: \"public\",\n  autoInit: true\n});\n\nexport const repositoryCloneUrl = repository.httpCloneUrl;\n\nconst aadApplication = new azuread.Application(\"AzureReadyApp\", { displayName: \"Azure Ready App\" });\nconst servicePrincipal = new azuread.ServicePrincipal(\"AzureReadyServicePrincipal\", {\n  applicationId: aadApplication.applicationId,\n});\nnew azuread.ApplicationFederatedIdentityCredential(\"AzureReadyAppFederatedIdentityCredential\", {\n  applicationObjectId: aadApplication.objectId,\n  displayName: \"AzureReadyDeploys\",\n  description: \"Deployments for azure-ready-repository\",\n  audiences: [\"api://AzureADTokenExchange\"],\n  issuer: \"https://token.actions.githubusercontent.com\",\n  subject: pulumi.interpolate`repo:${repository.fullName}:ref:refs/heads/main`,\n});\n\nconst azureConfig = pulumi.output(authorization.getClientConfig());\nconst subscriptionId = azureConfig.subscriptionId;\n\nnew authorization.RoleAssignment(\"contributor\", {\n  principalId: servicePrincipal.id,\n  principalType: authorization.PrincipalType.ServicePrincipal,\n  roleDefinitionId: azureBuiltInRoles.contributor,\n  scope: pulumi.interpolate`/subscriptions/${subscriptionId}`,\n});\n\nnew github.ActionsSecret(\"tenantId\", {\n  repository: repository.name,\n  secretName: \"ARM_TENANT_ID\",\n  plaintextValue: azureConfig.tenantId,\n});\n\nnew github.ActionsSecret(\"subscriptionId\", {\n  repository: repository.name,\n  secretName: \"ARM_SUBSCRIPTION_ID\",\n  plaintextValue: azureConfig.subscriptionId,\n});\n\nnew github.ActionsSecret(\"clientId\", {\n  repository: repository.name,\n  secretName: \"ARM_CLIENT_ID\",\n  plaintextValue: aadApplication.applicationId,\n});\n\nnew github.ActionsSecret(\"pulumiAccessToken\", {\n  repository: repository.name,\n  secretName: \"PULUMI_ACCESS_TOKEN\",\n  plaintextValue: config.requireSecret(\"pulumiTokenForRepository\"),\n});\n\nconst pipelineContent = readFileSync(\"main.yml\", \"utf-8\");\nnew github.RepositoryFile(\"pipelineRepositoryFile\", {\n  repository: repository.name,\n  branch: \"main\",\n  file: \".github/workflows/main.yml\",\n  content: pipelineContent,\n  commitMessage: \"Add preconfigured pipeline file\",\n  commitAuthor: \"Alexandre Nédélec\",\n  commitEmail: \"15186176+TechWatching@users.noreply.github.com\",\n  overwriteOnCreate: true,\n});\n",[13122],{"type":413,"tag":444,"props":13123,"children":13124},{"__ignoreMap":401},[13125,13166,13205,13244,13283,13322,13361,13368,13407,13414,13469,13496,13523,13538,13553,13560,13595,13602,13689,13744,13771,13786,13829,13856,13883,13910,13945,13972,14035,14050,14057,14104,14135,14142,14185,14212,14247,14274,14321,14336,14343,14386,14413,14440,14467,14482,14489,14532,14559,14586,14613,14628,14635,14678,14705,14733,14761,14777,14785,14829,14857,14885,14933,14949,14957,15017,15061,15089,15117,15145,15165,15193,15221,15249,15269],{"type":413,"tag":448,"props":13126,"children":13127},{"class":450,"line":451},[13128,13132,13136,13140,13145,13149,13153,13158,13162],{"type":413,"tag":448,"props":13129,"children":13130},{"style":785},[13131],{"type":418,"value":8648},{"type":413,"tag":448,"props":13133,"children":13134},{"style":461},[13135],{"type":418,"value":8653},{"type":413,"tag":448,"props":13137,"children":13138},{"style":785},[13139],{"type":418,"value":8658},{"type":413,"tag":448,"props":13141,"children":13142},{"style":1029},[13143],{"type":418,"value":13144}," pulumi ",{"type":413,"tag":448,"props":13146,"children":13147},{"style":785},[13148],{"type":418,"value":8668},{"type":413,"tag":448,"props":13150,"children":13151},{"style":461},[13152],{"type":418,"value":995},{"type":413,"tag":448,"props":13154,"children":13155},{"style":467},[13156],{"type":418,"value":13157},"@pulumi/pulumi",{"type":413,"tag":448,"props":13159,"children":13160},{"style":461},[13161],{"type":418,"value":1183},{"type":413,"tag":448,"props":13163,"children":13164},{"style":461},[13165],{"type":418,"value":5802},{"type":413,"tag":448,"props":13167,"children":13168},{"class":450,"line":473},[13169,13173,13177,13181,13185,13189,13193,13197,13201],{"type":413,"tag":448,"props":13170,"children":13171},{"style":785},[13172],{"type":418,"value":8648},{"type":413,"tag":448,"props":13174,"children":13175},{"style":461},[13176],{"type":418,"value":8653},{"type":413,"tag":448,"props":13178,"children":13179},{"style":785},[13180],{"type":418,"value":8658},{"type":413,"tag":448,"props":13182,"children":13183},{"style":1029},[13184],{"type":418,"value":8663},{"type":413,"tag":448,"props":13186,"children":13187},{"style":785},[13188],{"type":418,"value":8668},{"type":413,"tag":448,"props":13190,"children":13191},{"style":461},[13192],{"type":418,"value":995},{"type":413,"tag":448,"props":13194,"children":13195},{"style":467},[13196],{"type":418,"value":8561},{"type":413,"tag":448,"props":13198,"children":13199},{"style":461},[13200],{"type":418,"value":1183},{"type":413,"tag":448,"props":13202,"children":13203},{"style":461},[13204],{"type":418,"value":5802},{"type":413,"tag":448,"props":13206,"children":13207},{"class":450,"line":488},[13208,13212,13216,13220,13224,13228,13232,13236,13240],{"type":413,"tag":448,"props":13209,"children":13210},{"style":785},[13211],{"type":418,"value":8648},{"type":413,"tag":448,"props":13213,"children":13214},{"style":461},[13215],{"type":418,"value":8653},{"type":413,"tag":448,"props":13217,"children":13218},{"style":785},[13219],{"type":418,"value":8658},{"type":413,"tag":448,"props":13221,"children":13222},{"style":1029},[13223],{"type":418,"value":9006},{"type":413,"tag":448,"props":13225,"children":13226},{"style":785},[13227],{"type":418,"value":8668},{"type":413,"tag":448,"props":13229,"children":13230},{"style":461},[13231],{"type":418,"value":995},{"type":413,"tag":448,"props":13233,"children":13234},{"style":467},[13235],{"type":418,"value":8556},{"type":413,"tag":448,"props":13237,"children":13238},{"style":461},[13239],{"type":418,"value":1183},{"type":413,"tag":448,"props":13241,"children":13242},{"style":461},[13243],{"type":418,"value":5802},{"type":413,"tag":448,"props":13245,"children":13246},{"class":450,"line":501},[13247,13251,13255,13259,13263,13267,13271,13275,13279],{"type":413,"tag":448,"props":13248,"children":13249},{"style":785},[13250],{"type":418,"value":8648},{"type":413,"tag":448,"props":13252,"children":13253},{"style":461},[13254],{"type":418,"value":8653},{"type":413,"tag":448,"props":13256,"children":13257},{"style":785},[13258],{"type":418,"value":8658},{"type":413,"tag":448,"props":13260,"children":13261},{"style":1029},[13262],{"type":418,"value":9632},{"type":413,"tag":448,"props":13264,"children":13265},{"style":785},[13266],{"type":418,"value":8668},{"type":413,"tag":448,"props":13268,"children":13269},{"style":461},[13270],{"type":418,"value":995},{"type":413,"tag":448,"props":13272,"children":13273},{"style":467},[13274],{"type":418,"value":9645},{"type":413,"tag":448,"props":13276,"children":13277},{"style":461},[13278],{"type":418,"value":1183},{"type":413,"tag":448,"props":13280,"children":13281},{"style":461},[13282],{"type":418,"value":5802},{"type":413,"tag":448,"props":13284,"children":13285},{"class":450,"line":511},[13286,13290,13294,13298,13302,13306,13310,13314,13318],{"type":413,"tag":448,"props":13287,"children":13288},{"style":785},[13289],{"type":418,"value":8648},{"type":413,"tag":448,"props":13291,"children":13292},{"style":461},[13293],{"type":418,"value":9093},{"type":413,"tag":448,"props":13295,"children":13296},{"style":1029},[13297],{"type":418,"value":9669},{"type":413,"tag":448,"props":13299,"children":13300},{"style":461},[13301],{"type":418,"value":9120},{"type":413,"tag":448,"props":13303,"children":13304},{"style":785},[13305],{"type":418,"value":9678},{"type":413,"tag":448,"props":13307,"children":13308},{"style":461},[13309],{"type":418,"value":995},{"type":413,"tag":448,"props":13311,"children":13312},{"style":467},[13313],{"type":418,"value":9687},{"type":413,"tag":448,"props":13315,"children":13316},{"style":461},[13317],{"type":418,"value":1183},{"type":413,"tag":448,"props":13319,"children":13320},{"style":461},[13321],{"type":418,"value":5802},{"type":413,"tag":448,"props":13323,"children":13324},{"class":450,"line":524},[13325,13329,13333,13337,13341,13345,13349,13353,13357],{"type":413,"tag":448,"props":13326,"children":13327},{"style":785},[13328],{"type":418,"value":8648},{"type":413,"tag":448,"props":13330,"children":13331},{"style":461},[13332],{"type":418,"value":9093},{"type":413,"tag":448,"props":13334,"children":13335},{"style":1029},[13336],{"type":418,"value":12302},{"type":413,"tag":448,"props":13338,"children":13339},{"style":461},[13340],{"type":418,"value":9120},{"type":413,"tag":448,"props":13342,"children":13343},{"style":785},[13344],{"type":418,"value":9678},{"type":413,"tag":448,"props":13346,"children":13347},{"style":461},[13348],{"type":418,"value":995},{"type":413,"tag":448,"props":13350,"children":13351},{"style":467},[13352],{"type":418,"value":12319},{"type":413,"tag":448,"props":13354,"children":13355},{"style":461},[13356],{"type":418,"value":1183},{"type":413,"tag":448,"props":13358,"children":13359},{"style":461},[13360],{"type":418,"value":5802},{"type":413,"tag":448,"props":13362,"children":13363},{"class":450,"line":542},[13364],{"type":413,"tag":448,"props":13365,"children":13366},{"emptyLinePlaceholder":505},[13367],{"type":418,"value":508},{"type":413,"tag":448,"props":13369,"children":13370},{"class":450,"line":560},[13371,13375,13379,13383,13387,13391,13395,13399,13403],{"type":413,"tag":448,"props":13372,"children":13373},{"style":6130},[13374],{"type":418,"value":8699},{"type":413,"tag":448,"props":13376,"children":13377},{"style":1029},[13378],{"type":418,"value":9935},{"type":413,"tag":448,"props":13380,"children":13381},{"style":461},[13382],{"type":418,"value":1037},{"type":413,"tag":448,"props":13384,"children":13385},{"style":461},[13386],{"type":418,"value":3943},{"type":413,"tag":448,"props":13388,"children":13389},{"style":1029},[13390],{"type":418,"value":9469},{"type":413,"tag":448,"props":13392,"children":13393},{"style":461},[13394],{"type":418,"value":898},{"type":413,"tag":448,"props":13396,"children":13397},{"style":2000},[13398],{"type":418,"value":9956},{"type":413,"tag":448,"props":13400,"children":13401},{"style":1029},[13402],{"type":418,"value":9961},{"type":413,"tag":448,"props":13404,"children":13405},{"style":461},[13406],{"type":418,"value":5802},{"type":413,"tag":448,"props":13408,"children":13409},{"class":450,"line":573},[13410],{"type":413,"tag":448,"props":13411,"children":13412},{"emptyLinePlaceholder":505},[13413],{"type":418,"value":508},{"type":413,"tag":448,"props":13415,"children":13416},{"class":450,"line":586},[13417,13421,13425,13429,13433,13437,13441,13445,13449,13453,13457,13461,13465],{"type":413,"tag":448,"props":13418,"children":13419},{"style":6130},[13420],{"type":418,"value":8699},{"type":413,"tag":448,"props":13422,"children":13423},{"style":1029},[13424],{"type":418,"value":8704},{"type":413,"tag":448,"props":13426,"children":13427},{"style":461},[13428],{"type":418,"value":1037},{"type":413,"tag":448,"props":13430,"children":13431},{"style":461},[13432],{"type":418,"value":3943},{"type":413,"tag":448,"props":13434,"children":13435},{"style":1029},[13436],{"type":418,"value":8717},{"type":413,"tag":448,"props":13438,"children":13439},{"style":461},[13440],{"type":418,"value":898},{"type":413,"tag":448,"props":13442,"children":13443},{"style":2000},[13444],{"type":418,"value":8726},{"type":413,"tag":448,"props":13446,"children":13447},{"style":1029},[13448],{"type":418,"value":2041},{"type":413,"tag":448,"props":13450,"children":13451},{"style":461},[13452],{"type":418,"value":1183},{"type":413,"tag":448,"props":13454,"children":13455},{"style":467},[13456],{"type":418,"value":8739},{"type":413,"tag":448,"props":13458,"children":13459},{"style":461},[13460],{"type":418,"value":1183},{"type":413,"tag":448,"props":13462,"children":13463},{"style":461},[13464],{"type":418,"value":2059},{"type":413,"tag":448,"props":13466,"children":13467},{"style":461},[13468],{"type":418,"value":8752},{"type":413,"tag":448,"props":13470,"children":13471},{"class":450,"line":604},[13472,13476,13480,13484,13488,13492],{"type":413,"tag":448,"props":13473,"children":13474},{"style":455},[13475],{"type":418,"value":8760},{"type":413,"tag":448,"props":13477,"children":13478},{"style":461},[13479],{"type":418,"value":464},{"type":413,"tag":448,"props":13481,"children":13482},{"style":461},[13483],{"type":418,"value":995},{"type":413,"tag":448,"props":13485,"children":13486},{"style":467},[13487],{"type":418,"value":8739},{"type":413,"tag":448,"props":13489,"children":13490},{"style":461},[13491],{"type":418,"value":1183},{"type":413,"tag":448,"props":13493,"children":13494},{"style":461},[13495],{"type":418,"value":4378},{"type":413,"tag":448,"props":13497,"children":13498},{"class":450,"line":617},[13499,13503,13507,13511,13515,13519],{"type":413,"tag":448,"props":13500,"children":13501},{"style":455},[13502],{"type":418,"value":8788},{"type":413,"tag":448,"props":13504,"children":13505},{"style":461},[13506],{"type":418,"value":464},{"type":413,"tag":448,"props":13508,"children":13509},{"style":461},[13510],{"type":418,"value":995},{"type":413,"tag":448,"props":13512,"children":13513},{"style":467},[13514],{"type":418,"value":8801},{"type":413,"tag":448,"props":13516,"children":13517},{"style":461},[13518],{"type":418,"value":1183},{"type":413,"tag":448,"props":13520,"children":13521},{"style":461},[13522],{"type":418,"value":4378},{"type":413,"tag":448,"props":13524,"children":13525},{"class":450,"line":650},[13526,13530,13534],{"type":413,"tag":448,"props":13527,"children":13528},{"style":455},[13529],{"type":418,"value":8817},{"type":413,"tag":448,"props":13531,"children":13532},{"style":461},[13533],{"type":418,"value":464},{"type":413,"tag":448,"props":13535,"children":13536},{"style":477},[13537],{"type":418,"value":8826},{"type":413,"tag":448,"props":13539,"children":13540},{"class":450,"line":668},[13541,13545,13549],{"type":413,"tag":448,"props":13542,"children":13543},{"style":461},[13544],{"type":418,"value":1825},{"type":413,"tag":448,"props":13546,"children":13547},{"style":1029},[13548],{"type":418,"value":2031},{"type":413,"tag":448,"props":13550,"children":13551},{"style":461},[13552],{"type":418,"value":5802},{"type":413,"tag":448,"props":13554,"children":13555},{"class":450,"line":681},[13556],{"type":413,"tag":448,"props":13557,"children":13558},{"emptyLinePlaceholder":505},[13559],{"type":418,"value":508},{"type":413,"tag":448,"props":13561,"children":13562},{"class":450,"line":699},[13563,13567,13571,13575,13579,13583,13587,13591],{"type":413,"tag":448,"props":13564,"children":13565},{"style":785},[13566],{"type":418,"value":8856},{"type":413,"tag":448,"props":13568,"children":13569},{"style":6130},[13570],{"type":418,"value":8861},{"type":413,"tag":448,"props":13572,"children":13573},{"style":1029},[13574],{"type":418,"value":8866},{"type":413,"tag":448,"props":13576,"children":13577},{"style":461},[13578],{"type":418,"value":1037},{"type":413,"tag":448,"props":13580,"children":13581},{"style":1029},[13582],{"type":418,"value":4675},{"type":413,"tag":448,"props":13584,"children":13585},{"style":461},[13586],{"type":418,"value":898},{"type":413,"tag":448,"props":13588,"children":13589},{"style":1029},[13590],{"type":418,"value":8883},{"type":413,"tag":448,"props":13592,"children":13593},{"style":461},[13594],{"type":418,"value":5802},{"type":413,"tag":448,"props":13596,"children":13597},{"class":450,"line":717},[13598],{"type":413,"tag":448,"props":13599,"children":13600},{"emptyLinePlaceholder":505},[13601],{"type":418,"value":508},{"type":413,"tag":448,"props":13603,"children":13604},{"class":450,"line":735},[13605,13609,13613,13617,13621,13625,13629,13633,13637,13641,13645,13649,13653,13657,13661,13665,13669,13673,13677,13681,13685],{"type":413,"tag":448,"props":13606,"children":13607},{"style":6130},[13608],{"type":418,"value":8699},{"type":413,"tag":448,"props":13610,"children":13611},{"style":1029},[13612],{"type":418,"value":9045},{"type":413,"tag":448,"props":13614,"children":13615},{"style":461},[13616],{"type":418,"value":1037},{"type":413,"tag":448,"props":13618,"children":13619},{"style":461},[13620],{"type":418,"value":3943},{"type":413,"tag":448,"props":13622,"children":13623},{"style":1029},[13624],{"type":418,"value":9058},{"type":413,"tag":448,"props":13626,"children":13627},{"style":461},[13628],{"type":418,"value":898},{"type":413,"tag":448,"props":13630,"children":13631},{"style":2000},[13632],{"type":418,"value":9067},{"type":413,"tag":448,"props":13634,"children":13635},{"style":1029},[13636],{"type":418,"value":2041},{"type":413,"tag":448,"props":13638,"children":13639},{"style":461},[13640],{"type":418,"value":1183},{"type":413,"tag":448,"props":13642,"children":13643},{"style":467},[13644],{"type":418,"value":9080},{"type":413,"tag":448,"props":13646,"children":13647},{"style":461},[13648],{"type":418,"value":1183},{"type":413,"tag":448,"props":13650,"children":13651},{"style":461},[13652],{"type":418,"value":2059},{"type":413,"tag":448,"props":13654,"children":13655},{"style":461},[13656],{"type":418,"value":9093},{"type":413,"tag":448,"props":13658,"children":13659},{"style":455},[13660],{"type":418,"value":9098},{"type":413,"tag":448,"props":13662,"children":13663},{"style":461},[13664],{"type":418,"value":464},{"type":413,"tag":448,"props":13666,"children":13667},{"style":461},[13668],{"type":418,"value":995},{"type":413,"tag":448,"props":13670,"children":13671},{"style":467},[13672],{"type":418,"value":9111},{"type":413,"tag":448,"props":13674,"children":13675},{"style":461},[13676],{"type":418,"value":1183},{"type":413,"tag":448,"props":13678,"children":13679},{"style":461},[13680],{"type":418,"value":9120},{"type":413,"tag":448,"props":13682,"children":13683},{"style":1029},[13684],{"type":418,"value":2031},{"type":413,"tag":448,"props":13686,"children":13687},{"style":461},[13688],{"type":418,"value":5802},{"type":413,"tag":448,"props":13690,"children":13691},{"class":450,"line":743},[13692,13696,13700,13704,13708,13712,13716,13720,13724,13728,13732,13736,13740],{"type":413,"tag":448,"props":13693,"children":13694},{"style":6130},[13695],{"type":418,"value":8699},{"type":413,"tag":448,"props":13697,"children":13698},{"style":1029},[13699],{"type":418,"value":9140},{"type":413,"tag":448,"props":13701,"children":13702},{"style":461},[13703],{"type":418,"value":1037},{"type":413,"tag":448,"props":13705,"children":13706},{"style":461},[13707],{"type":418,"value":3943},{"type":413,"tag":448,"props":13709,"children":13710},{"style":1029},[13711],{"type":418,"value":9058},{"type":413,"tag":448,"props":13713,"children":13714},{"style":461},[13715],{"type":418,"value":898},{"type":413,"tag":448,"props":13717,"children":13718},{"style":2000},[13719],{"type":418,"value":6224},{"type":413,"tag":448,"props":13721,"children":13722},{"style":1029},[13723],{"type":418,"value":2041},{"type":413,"tag":448,"props":13725,"children":13726},{"style":461},[13727],{"type":418,"value":1183},{"type":413,"tag":448,"props":13729,"children":13730},{"style":467},[13731],{"type":418,"value":6008},{"type":413,"tag":448,"props":13733,"children":13734},{"style":461},[13735],{"type":418,"value":1183},{"type":413,"tag":448,"props":13737,"children":13738},{"style":461},[13739],{"type":418,"value":2059},{"type":413,"tag":448,"props":13741,"children":13742},{"style":461},[13743],{"type":418,"value":8752},{"type":413,"tag":448,"props":13745,"children":13746},{"class":450,"line":772},[13747,13751,13755,13759,13763,13767],{"type":413,"tag":448,"props":13748,"children":13749},{"style":455},[13750],{"type":418,"value":9193},{"type":413,"tag":448,"props":13752,"children":13753},{"style":461},[13754],{"type":418,"value":464},{"type":413,"tag":448,"props":13756,"children":13757},{"style":1029},[13758],{"type":418,"value":5893},{"type":413,"tag":448,"props":13760,"children":13761},{"style":461},[13762],{"type":418,"value":898},{"type":413,"tag":448,"props":13764,"children":13765},{"style":1029},[13766],{"type":418,"value":9210},{"type":413,"tag":448,"props":13768,"children":13769},{"style":461},[13770],{"type":418,"value":4378},{"type":413,"tag":448,"props":13772,"children":13773},{"class":450,"line":791},[13774,13778,13782],{"type":413,"tag":448,"props":13775,"children":13776},{"style":461},[13777],{"type":418,"value":1825},{"type":413,"tag":448,"props":13779,"children":13780},{"style":1029},[13781],{"type":418,"value":2031},{"type":413,"tag":448,"props":13783,"children":13784},{"style":461},[13785],{"type":418,"value":5802},{"type":413,"tag":448,"props":13787,"children":13788},{"class":450,"line":800},[13789,13793,13797,13801,13805,13809,13813,13817,13821,13825],{"type":413,"tag":448,"props":13790,"children":13791},{"style":461},[13792],{"type":418,"value":6133},{"type":413,"tag":448,"props":13794,"children":13795},{"style":1029},[13796],{"type":418,"value":9058},{"type":413,"tag":448,"props":13798,"children":13799},{"style":461},[13800],{"type":418,"value":898},{"type":413,"tag":448,"props":13802,"children":13803},{"style":2000},[13804],{"type":418,"value":9277},{"type":413,"tag":448,"props":13806,"children":13807},{"style":1029},[13808],{"type":418,"value":2041},{"type":413,"tag":448,"props":13810,"children":13811},{"style":461},[13812],{"type":418,"value":1183},{"type":413,"tag":448,"props":13814,"children":13815},{"style":467},[13816],{"type":418,"value":9290},{"type":413,"tag":448,"props":13818,"children":13819},{"style":461},[13820],{"type":418,"value":1183},{"type":413,"tag":448,"props":13822,"children":13823},{"style":461},[13824],{"type":418,"value":2059},{"type":413,"tag":448,"props":13826,"children":13827},{"style":461},[13828],{"type":418,"value":8752},{"type":413,"tag":448,"props":13830,"children":13831},{"class":450,"line":2909},[13832,13836,13840,13844,13848,13852],{"type":413,"tag":448,"props":13833,"children":13834},{"style":455},[13835],{"type":418,"value":9310},{"type":413,"tag":448,"props":13837,"children":13838},{"style":461},[13839],{"type":418,"value":464},{"type":413,"tag":448,"props":13841,"children":13842},{"style":1029},[13843],{"type":418,"value":5893},{"type":413,"tag":448,"props":13845,"children":13846},{"style":461},[13847],{"type":418,"value":898},{"type":413,"tag":448,"props":13849,"children":13850},{"style":1029},[13851],{"type":418,"value":9327},{"type":413,"tag":448,"props":13853,"children":13854},{"style":461},[13855],{"type":418,"value":4378},{"type":413,"tag":448,"props":13857,"children":13858},{"class":450,"line":3021},[13859,13863,13867,13871,13875,13879],{"type":413,"tag":448,"props":13860,"children":13861},{"style":455},[13862],{"type":418,"value":9339},{"type":413,"tag":448,"props":13864,"children":13865},{"style":461},[13866],{"type":418,"value":464},{"type":413,"tag":448,"props":13868,"children":13869},{"style":461},[13870],{"type":418,"value":995},{"type":413,"tag":448,"props":13872,"children":13873},{"style":467},[13874],{"type":418,"value":6444},{"type":413,"tag":448,"props":13876,"children":13877},{"style":461},[13878],{"type":418,"value":1183},{"type":413,"tag":448,"props":13880,"children":13881},{"style":461},[13882],{"type":418,"value":4378},{"type":413,"tag":448,"props":13884,"children":13885},{"class":450,"line":3029},[13886,13890,13894,13898,13902,13906],{"type":413,"tag":448,"props":13887,"children":13888},{"style":455},[13889],{"type":418,"value":9367},{"type":413,"tag":448,"props":13891,"children":13892},{"style":461},[13893],{"type":418,"value":464},{"type":413,"tag":448,"props":13895,"children":13896},{"style":461},[13897],{"type":418,"value":995},{"type":413,"tag":448,"props":13899,"children":13900},{"style":467},[13901],{"type":418,"value":6472},{"type":413,"tag":448,"props":13903,"children":13904},{"style":461},[13905],{"type":418,"value":1183},{"type":413,"tag":448,"props":13907,"children":13908},{"style":461},[13909],{"type":418,"value":4378},{"type":413,"tag":448,"props":13911,"children":13912},{"class":450,"line":3038},[13913,13917,13921,13925,13929,13933,13937,13941],{"type":413,"tag":448,"props":13914,"children":13915},{"style":455},[13916],{"type":418,"value":9395},{"type":413,"tag":448,"props":13918,"children":13919},{"style":461},[13920],{"type":418,"value":464},{"type":413,"tag":448,"props":13922,"children":13923},{"style":1029},[13924],{"type":418,"value":9404},{"type":413,"tag":448,"props":13926,"children":13927},{"style":461},[13928],{"type":418,"value":1183},{"type":413,"tag":448,"props":13930,"children":13931},{"style":467},[13932],{"type":418,"value":1902},{"type":413,"tag":448,"props":13934,"children":13935},{"style":461},[13936],{"type":418,"value":1183},{"type":413,"tag":448,"props":13938,"children":13939},{"style":1029},[13940],{"type":418,"value":4428},{"type":413,"tag":448,"props":13942,"children":13943},{"style":461},[13944],{"type":418,"value":4378},{"type":413,"tag":448,"props":13946,"children":13947},{"class":450,"line":3062},[13948,13952,13956,13960,13964,13968],{"type":413,"tag":448,"props":13949,"children":13950},{"style":455},[13951],{"type":418,"value":9432},{"type":413,"tag":448,"props":13953,"children":13954},{"style":461},[13955],{"type":418,"value":464},{"type":413,"tag":448,"props":13957,"children":13958},{"style":461},[13959],{"type":418,"value":995},{"type":413,"tag":448,"props":13961,"children":13962},{"style":467},[13963],{"type":418,"value":1787},{"type":413,"tag":448,"props":13965,"children":13966},{"style":461},[13967],{"type":418,"value":1183},{"type":413,"tag":448,"props":13969,"children":13970},{"style":461},[13971],{"type":418,"value":4378},{"type":413,"tag":448,"props":13973,"children":13974},{"class":450,"line":3086},[13975,13979,13983,13987,13991,13995,13999,14003,14007,14011,14015,14019,14023,14027,14031],{"type":413,"tag":448,"props":13976,"children":13977},{"style":455},[13978],{"type":418,"value":9460},{"type":413,"tag":448,"props":13980,"children":13981},{"style":461},[13982],{"type":418,"value":464},{"type":413,"tag":448,"props":13984,"children":13985},{"style":1029},[13986],{"type":418,"value":9469},{"type":413,"tag":448,"props":13988,"children":13989},{"style":461},[13990],{"type":418,"value":898},{"type":413,"tag":448,"props":13992,"children":13993},{"style":2000},[13994],{"type":418,"value":9478},{"type":413,"tag":448,"props":13996,"children":13997},{"style":461},[13998],{"type":418,"value":9483},{"type":413,"tag":448,"props":14000,"children":14001},{"style":467},[14002],{"type":418,"value":1812},{"type":413,"tag":448,"props":14004,"children":14005},{"style":461},[14006],{"type":418,"value":1452},{"type":413,"tag":448,"props":14008,"children":14009},{"style":1029},[14010],{"type":418,"value":9496},{"type":413,"tag":448,"props":14012,"children":14013},{"style":461},[14014],{"type":418,"value":898},{"type":413,"tag":448,"props":14016,"children":14017},{"style":1029},[14018],{"type":418,"value":9505},{"type":413,"tag":448,"props":14020,"children":14021},{"style":461},[14022],{"type":418,"value":1825},{"type":413,"tag":448,"props":14024,"children":14025},{"style":467},[14026],{"type":418,"value":1830},{"type":413,"tag":448,"props":14028,"children":14029},{"style":461},[14030],{"type":418,"value":9483},{"type":413,"tag":448,"props":14032,"children":14033},{"style":461},[14034],{"type":418,"value":4378},{"type":413,"tag":448,"props":14036,"children":14037},{"class":450,"line":3110},[14038,14042,14046],{"type":413,"tag":448,"props":14039,"children":14040},{"style":461},[14041],{"type":418,"value":1825},{"type":413,"tag":448,"props":14043,"children":14044},{"style":1029},[14045],{"type":418,"value":2031},{"type":413,"tag":448,"props":14047,"children":14048},{"style":461},[14049],{"type":418,"value":5802},{"type":413,"tag":448,"props":14051,"children":14052},{"class":450,"line":3150},[14053],{"type":413,"tag":448,"props":14054,"children":14055},{"emptyLinePlaceholder":505},[14056],{"type":418,"value":508},{"type":413,"tag":448,"props":14058,"children":14059},{"class":450,"line":3182},[14060,14064,14068,14072,14076,14080,14084,14088,14092,14096,14100],{"type":413,"tag":448,"props":14061,"children":14062},{"style":6130},[14063],{"type":418,"value":8699},{"type":413,"tag":448,"props":14065,"children":14066},{"style":1029},[14067],{"type":418,"value":10042},{"type":413,"tag":448,"props":14069,"children":14070},{"style":461},[14071],{"type":418,"value":1037},{"type":413,"tag":448,"props":14073,"children":14074},{"style":1029},[14075],{"type":418,"value":9469},{"type":413,"tag":448,"props":14077,"children":14078},{"style":461},[14079],{"type":418,"value":898},{"type":413,"tag":448,"props":14081,"children":14082},{"style":2000},[14083],{"type":418,"value":8920},{"type":413,"tag":448,"props":14085,"children":14086},{"style":1029},[14087],{"type":418,"value":10063},{"type":413,"tag":448,"props":14089,"children":14090},{"style":461},[14091],{"type":418,"value":898},{"type":413,"tag":448,"props":14093,"children":14094},{"style":2000},[14095],{"type":418,"value":10072},{"type":413,"tag":448,"props":14097,"children":14098},{"style":1029},[14099],{"type":418,"value":10077},{"type":413,"tag":448,"props":14101,"children":14102},{"style":461},[14103],{"type":418,"value":5802},{"type":413,"tag":448,"props":14105,"children":14106},{"class":450,"line":3202},[14107,14111,14115,14119,14123,14127,14131],{"type":413,"tag":448,"props":14108,"children":14109},{"style":6130},[14110],{"type":418,"value":8699},{"type":413,"tag":448,"props":14112,"children":14113},{"style":1029},[14114],{"type":418,"value":9977},{"type":413,"tag":448,"props":14116,"children":14117},{"style":461},[14118],{"type":418,"value":1037},{"type":413,"tag":448,"props":14120,"children":14121},{"style":1029},[14122],{"type":418,"value":5418},{"type":413,"tag":448,"props":14124,"children":14125},{"style":461},[14126],{"type":418,"value":898},{"type":413,"tag":448,"props":14128,"children":14129},{"style":1029},[14130],{"type":418,"value":1258},{"type":413,"tag":448,"props":14132,"children":14133},{"style":461},[14134],{"type":418,"value":5802},{"type":413,"tag":448,"props":14136,"children":14137},{"class":450,"line":3218},[14138],{"type":413,"tag":448,"props":14139,"children":14140},{"emptyLinePlaceholder":505},[14141],{"type":418,"value":508},{"type":413,"tag":448,"props":14143,"children":14144},{"class":450,"line":3226},[14145,14149,14153,14157,14161,14165,14169,14173,14177,14181],{"type":413,"tag":448,"props":14146,"children":14147},{"style":461},[14148],{"type":418,"value":6133},{"type":413,"tag":448,"props":14150,"children":14151},{"style":1029},[14152],{"type":418,"value":9714},{"type":413,"tag":448,"props":14154,"children":14155},{"style":461},[14156],{"type":418,"value":898},{"type":413,"tag":448,"props":14158,"children":14159},{"style":2000},[14160],{"type":418,"value":9723},{"type":413,"tag":448,"props":14162,"children":14163},{"style":1029},[14164],{"type":418,"value":2041},{"type":413,"tag":448,"props":14166,"children":14167},{"style":461},[14168],{"type":418,"value":1183},{"type":413,"tag":448,"props":14170,"children":14171},{"style":467},[14172],{"type":418,"value":6151},{"type":413,"tag":448,"props":14174,"children":14175},{"style":461},[14176],{"type":418,"value":1183},{"type":413,"tag":448,"props":14178,"children":14179},{"style":461},[14180],{"type":418,"value":2059},{"type":413,"tag":448,"props":14182,"children":14183},{"style":461},[14184],{"type":418,"value":8752},{"type":413,"tag":448,"props":14186,"children":14187},{"class":450,"line":3234},[14188,14192,14196,14200,14204,14208],{"type":413,"tag":448,"props":14189,"children":14190},{"style":455},[14191],{"type":418,"value":9755},{"type":413,"tag":448,"props":14193,"children":14194},{"style":461},[14195],{"type":418,"value":464},{"type":413,"tag":448,"props":14197,"children":14198},{"style":1029},[14199],{"type":418,"value":5358},{"type":413,"tag":448,"props":14201,"children":14202},{"style":461},[14203],{"type":418,"value":898},{"type":413,"tag":448,"props":14205,"children":14206},{"style":1029},[14207],{"type":418,"value":1285},{"type":413,"tag":448,"props":14209,"children":14210},{"style":461},[14211],{"type":418,"value":4378},{"type":413,"tag":448,"props":14213,"children":14214},{"class":450,"line":3242},[14215,14219,14223,14227,14231,14235,14239,14243],{"type":413,"tag":448,"props":14216,"children":14217},{"style":455},[14218],{"type":418,"value":9783},{"type":413,"tag":448,"props":14220,"children":14221},{"style":461},[14222],{"type":418,"value":464},{"type":413,"tag":448,"props":14224,"children":14225},{"style":1029},[14226],{"type":418,"value":9714},{"type":413,"tag":448,"props":14228,"children":14229},{"style":461},[14230],{"type":418,"value":898},{"type":413,"tag":448,"props":14232,"children":14233},{"style":1029},[14234],{"type":418,"value":9800},{"type":413,"tag":448,"props":14236,"children":14237},{"style":461},[14238],{"type":418,"value":898},{"type":413,"tag":448,"props":14240,"children":14241},{"style":1029},[14242],{"type":418,"value":6224},{"type":413,"tag":448,"props":14244,"children":14245},{"style":461},[14246],{"type":418,"value":4378},{"type":413,"tag":448,"props":14248,"children":14249},{"class":450,"line":3251},[14250,14254,14258,14262,14266,14270],{"type":413,"tag":448,"props":14251,"children":14252},{"style":455},[14253],{"type":418,"value":9820},{"type":413,"tag":448,"props":14255,"children":14256},{"style":461},[14257],{"type":418,"value":464},{"type":413,"tag":448,"props":14259,"children":14260},{"style":1029},[14261],{"type":418,"value":9669},{"type":413,"tag":448,"props":14263,"children":14264},{"style":461},[14265],{"type":418,"value":898},{"type":413,"tag":448,"props":14267,"children":14268},{"style":1029},[14269],{"type":418,"value":6151},{"type":413,"tag":448,"props":14271,"children":14272},{"style":461},[14273],{"type":418,"value":4378},{"type":413,"tag":448,"props":14275,"children":14276},{"class":450,"line":3260},[14277,14281,14285,14289,14293,14297,14301,14305,14309,14313,14317],{"type":413,"tag":448,"props":14278,"children":14279},{"style":455},[14280],{"type":418,"value":9848},{"type":413,"tag":448,"props":14282,"children":14283},{"style":461},[14284],{"type":418,"value":464},{"type":413,"tag":448,"props":14286,"children":14287},{"style":1029},[14288],{"type":418,"value":9469},{"type":413,"tag":448,"props":14290,"children":14291},{"style":461},[14292],{"type":418,"value":898},{"type":413,"tag":448,"props":14294,"children":14295},{"style":2000},[14296],{"type":418,"value":9478},{"type":413,"tag":448,"props":14298,"children":14299},{"style":461},[14300],{"type":418,"value":9483},{"type":413,"tag":448,"props":14302,"children":14303},{"style":467},[14304],{"type":418,"value":5731},{"type":413,"tag":448,"props":14306,"children":14307},{"style":461},[14308],{"type":418,"value":1452},{"type":413,"tag":448,"props":14310,"children":14311},{"style":1029},[14312],{"type":418,"value":1258},{"type":413,"tag":448,"props":14314,"children":14315},{"style":461},[14316],{"type":418,"value":9885},{"type":413,"tag":448,"props":14318,"children":14319},{"style":461},[14320],{"type":418,"value":4378},{"type":413,"tag":448,"props":14322,"children":14323},{"class":450,"line":3360},[14324,14328,14332],{"type":413,"tag":448,"props":14325,"children":14326},{"style":461},[14327],{"type":418,"value":1825},{"type":413,"tag":448,"props":14329,"children":14330},{"style":1029},[14331],{"type":418,"value":2031},{"type":413,"tag":448,"props":14333,"children":14334},{"style":461},[14335],{"type":418,"value":5802},{"type":413,"tag":448,"props":14337,"children":14338},{"class":450,"line":3368},[14339],{"type":413,"tag":448,"props":14340,"children":14341},{"emptyLinePlaceholder":505},[14342],{"type":418,"value":508},{"type":413,"tag":448,"props":14344,"children":14345},{"class":450,"line":3377},[14346,14350,14354,14358,14362,14366,14370,14374,14378,14382],{"type":413,"tag":448,"props":14347,"children":14348},{"style":461},[14349],{"type":418,"value":6133},{"type":413,"tag":448,"props":14351,"children":14352},{"style":1029},[14353],{"type":418,"value":8717},{"type":413,"tag":448,"props":14355,"children":14356},{"style":461},[14357],{"type":418,"value":898},{"type":413,"tag":448,"props":14359,"children":14360},{"style":2000},[14361],{"type":418,"value":10478},{"type":413,"tag":448,"props":14363,"children":14364},{"style":1029},[14365],{"type":418,"value":2041},{"type":413,"tag":448,"props":14367,"children":14368},{"style":461},[14369],{"type":418,"value":1183},{"type":413,"tag":448,"props":14371,"children":14372},{"style":467},[14373],{"type":418,"value":1315},{"type":413,"tag":448,"props":14375,"children":14376},{"style":461},[14377],{"type":418,"value":1183},{"type":413,"tag":448,"props":14379,"children":14380},{"style":461},[14381],{"type":418,"value":2059},{"type":413,"tag":448,"props":14383,"children":14384},{"style":461},[14385],{"type":418,"value":8752},{"type":413,"tag":448,"props":14387,"children":14388},{"class":450,"line":3425},[14389,14393,14397,14401,14405,14409],{"type":413,"tag":448,"props":14390,"children":14391},{"style":455},[14392],{"type":418,"value":10300},{"type":413,"tag":448,"props":14394,"children":14395},{"style":461},[14396],{"type":418,"value":464},{"type":413,"tag":448,"props":14398,"children":14399},{"style":1029},[14400],{"type":418,"value":4675},{"type":413,"tag":448,"props":14402,"children":14403},{"style":461},[14404],{"type":418,"value":898},{"type":413,"tag":448,"props":14406,"children":14407},{"style":1029},[14408],{"type":418,"value":458},{"type":413,"tag":448,"props":14410,"children":14411},{"style":461},[14412],{"type":418,"value":4378},{"type":413,"tag":448,"props":14414,"children":14415},{"class":450,"line":3433},[14416,14420,14424,14428,14432,14436],{"type":413,"tag":448,"props":14417,"children":14418},{"style":455},[14419],{"type":418,"value":10537},{"type":413,"tag":448,"props":14421,"children":14422},{"style":461},[14423],{"type":418,"value":464},{"type":413,"tag":448,"props":14425,"children":14426},{"style":461},[14427],{"type":418,"value":995},{"type":413,"tag":448,"props":14429,"children":14430},{"style":467},[14431],{"type":418,"value":10341},{"type":413,"tag":448,"props":14433,"children":14434},{"style":461},[14435],{"type":418,"value":1183},{"type":413,"tag":448,"props":14437,"children":14438},{"style":461},[14439],{"type":418,"value":4378},{"type":413,"tag":448,"props":14441,"children":14442},{"class":450,"line":3442},[14443,14447,14451,14455,14459,14463],{"type":413,"tag":448,"props":14444,"children":14445},{"style":455},[14446],{"type":418,"value":10565},{"type":413,"tag":448,"props":14448,"children":14449},{"style":461},[14450],{"type":418,"value":464},{"type":413,"tag":448,"props":14452,"children":14453},{"style":1029},[14454],{"type":418,"value":5418},{"type":413,"tag":448,"props":14456,"children":14457},{"style":461},[14458],{"type":418,"value":898},{"type":413,"tag":448,"props":14460,"children":14461},{"style":1029},[14462],{"type":418,"value":1315},{"type":413,"tag":448,"props":14464,"children":14465},{"style":461},[14466],{"type":418,"value":4378},{"type":413,"tag":448,"props":14468,"children":14469},{"class":450,"line":3466},[14470,14474,14478],{"type":413,"tag":448,"props":14471,"children":14472},{"style":461},[14473],{"type":418,"value":1825},{"type":413,"tag":448,"props":14475,"children":14476},{"style":1029},[14477],{"type":418,"value":2031},{"type":413,"tag":448,"props":14479,"children":14480},{"style":461},[14481],{"type":418,"value":5802},{"type":413,"tag":448,"props":14483,"children":14484},{"class":450,"line":3490},[14485],{"type":413,"tag":448,"props":14486,"children":14487},{"emptyLinePlaceholder":505},[14488],{"type":418,"value":508},{"type":413,"tag":448,"props":14490,"children":14491},{"class":450,"line":3514},[14492,14496,14500,14504,14508,14512,14516,14520,14524,14528],{"type":413,"tag":448,"props":14493,"children":14494},{"style":461},[14495],{"type":418,"value":6133},{"type":413,"tag":448,"props":14497,"children":14498},{"style":1029},[14499],{"type":418,"value":8717},{"type":413,"tag":448,"props":14501,"children":14502},{"style":461},[14503],{"type":418,"value":898},{"type":413,"tag":448,"props":14505,"children":14506},{"style":2000},[14507],{"type":418,"value":10478},{"type":413,"tag":448,"props":14509,"children":14510},{"style":1029},[14511],{"type":418,"value":2041},{"type":413,"tag":448,"props":14513,"children":14514},{"style":461},[14515],{"type":418,"value":1183},{"type":413,"tag":448,"props":14517,"children":14518},{"style":467},[14519],{"type":418,"value":1258},{"type":413,"tag":448,"props":14521,"children":14522},{"style":461},[14523],{"type":418,"value":1183},{"type":413,"tag":448,"props":14525,"children":14526},{"style":461},[14527],{"type":418,"value":2059},{"type":413,"tag":448,"props":14529,"children":14530},{"style":461},[14531],{"type":418,"value":8752},{"type":413,"tag":448,"props":14533,"children":14534},{"class":450,"line":3522},[14535,14539,14543,14547,14551,14555],{"type":413,"tag":448,"props":14536,"children":14537},{"style":455},[14538],{"type":418,"value":10300},{"type":413,"tag":448,"props":14540,"children":14541},{"style":461},[14542],{"type":418,"value":464},{"type":413,"tag":448,"props":14544,"children":14545},{"style":1029},[14546],{"type":418,"value":4675},{"type":413,"tag":448,"props":14548,"children":14549},{"style":461},[14550],{"type":418,"value":898},{"type":413,"tag":448,"props":14552,"children":14553},{"style":1029},[14554],{"type":418,"value":458},{"type":413,"tag":448,"props":14556,"children":14557},{"style":461},[14558],{"type":418,"value":4378},{"type":413,"tag":448,"props":14560,"children":14561},{"class":450,"line":3531},[14562,14566,14570,14574,14578,14582],{"type":413,"tag":448,"props":14563,"children":14564},{"style":455},[14565],{"type":418,"value":10537},{"type":413,"tag":448,"props":14567,"children":14568},{"style":461},[14569],{"type":418,"value":464},{"type":413,"tag":448,"props":14571,"children":14572},{"style":461},[14573],{"type":418,"value":995},{"type":413,"tag":448,"props":14575,"children":14576},{"style":467},[14577],{"type":418,"value":10697},{"type":413,"tag":448,"props":14579,"children":14580},{"style":461},[14581],{"type":418,"value":1183},{"type":413,"tag":448,"props":14583,"children":14584},{"style":461},[14585],{"type":418,"value":4378},{"type":413,"tag":448,"props":14587,"children":14588},{"class":450,"line":3539},[14589,14593,14597,14601,14605,14609],{"type":413,"tag":448,"props":14590,"children":14591},{"style":455},[14592],{"type":418,"value":10565},{"type":413,"tag":448,"props":14594,"children":14595},{"style":461},[14596],{"type":418,"value":464},{"type":413,"tag":448,"props":14598,"children":14599},{"style":1029},[14600],{"type":418,"value":5418},{"type":413,"tag":448,"props":14602,"children":14603},{"style":461},[14604],{"type":418,"value":898},{"type":413,"tag":448,"props":14606,"children":14607},{"style":1029},[14608],{"type":418,"value":1258},{"type":413,"tag":448,"props":14610,"children":14611},{"style":461},[14612],{"type":418,"value":4378},{"type":413,"tag":448,"props":14614,"children":14615},{"class":450,"line":3607},[14616,14620,14624],{"type":413,"tag":448,"props":14617,"children":14618},{"style":461},[14619],{"type":418,"value":1825},{"type":413,"tag":448,"props":14621,"children":14622},{"style":1029},[14623],{"type":418,"value":2031},{"type":413,"tag":448,"props":14625,"children":14626},{"style":461},[14627],{"type":418,"value":5802},{"type":413,"tag":448,"props":14629,"children":14630},{"class":450,"line":3623},[14631],{"type":413,"tag":448,"props":14632,"children":14633},{"emptyLinePlaceholder":505},[14634],{"type":418,"value":508},{"type":413,"tag":448,"props":14636,"children":14637},{"class":450,"line":3631},[14638,14642,14646,14650,14654,14658,14662,14666,14670,14674],{"type":413,"tag":448,"props":14639,"children":14640},{"style":461},[14641],{"type":418,"value":6133},{"type":413,"tag":448,"props":14643,"children":14644},{"style":1029},[14645],{"type":418,"value":8717},{"type":413,"tag":448,"props":14647,"children":14648},{"style":461},[14649],{"type":418,"value":898},{"type":413,"tag":448,"props":14651,"children":14652},{"style":2000},[14653],{"type":418,"value":10478},{"type":413,"tag":448,"props":14655,"children":14656},{"style":1029},[14657],{"type":418,"value":2041},{"type":413,"tag":448,"props":14659,"children":14660},{"style":461},[14661],{"type":418,"value":1183},{"type":413,"tag":448,"props":14663,"children":14664},{"style":467},[14665],{"type":418,"value":10786},{"type":413,"tag":448,"props":14667,"children":14668},{"style":461},[14669],{"type":418,"value":1183},{"type":413,"tag":448,"props":14671,"children":14672},{"style":461},[14673],{"type":418,"value":2059},{"type":413,"tag":448,"props":14675,"children":14676},{"style":461},[14677],{"type":418,"value":8752},{"type":413,"tag":448,"props":14679,"children":14680},{"class":450,"line":3640},[14681,14685,14689,14693,14697,14701],{"type":413,"tag":448,"props":14682,"children":14683},{"style":455},[14684],{"type":418,"value":10300},{"type":413,"tag":448,"props":14686,"children":14687},{"style":461},[14688],{"type":418,"value":464},{"type":413,"tag":448,"props":14690,"children":14691},{"style":1029},[14692],{"type":418,"value":4675},{"type":413,"tag":448,"props":14694,"children":14695},{"style":461},[14696],{"type":418,"value":898},{"type":413,"tag":448,"props":14698,"children":14699},{"style":1029},[14700],{"type":418,"value":458},{"type":413,"tag":448,"props":14702,"children":14703},{"style":461},[14704],{"type":418,"value":4378},{"type":413,"tag":448,"props":14706,"children":14708},{"class":450,"line":14707},55,[14709,14713,14717,14721,14725,14729],{"type":413,"tag":448,"props":14710,"children":14711},{"style":455},[14712],{"type":418,"value":10537},{"type":413,"tag":448,"props":14714,"children":14715},{"style":461},[14716],{"type":418,"value":464},{"type":413,"tag":448,"props":14718,"children":14719},{"style":461},[14720],{"type":418,"value":995},{"type":413,"tag":448,"props":14722,"children":14723},{"style":467},[14724],{"type":418,"value":10845},{"type":413,"tag":448,"props":14726,"children":14727},{"style":461},[14728],{"type":418,"value":1183},{"type":413,"tag":448,"props":14730,"children":14731},{"style":461},[14732],{"type":418,"value":4378},{"type":413,"tag":448,"props":14734,"children":14736},{"class":450,"line":14735},56,[14737,14741,14745,14749,14753,14757],{"type":413,"tag":448,"props":14738,"children":14739},{"style":455},[14740],{"type":418,"value":10565},{"type":413,"tag":448,"props":14742,"children":14743},{"style":461},[14744],{"type":418,"value":464},{"type":413,"tag":448,"props":14746,"children":14747},{"style":1029},[14748],{"type":418,"value":5893},{"type":413,"tag":448,"props":14750,"children":14751},{"style":461},[14752],{"type":418,"value":898},{"type":413,"tag":448,"props":14754,"children":14755},{"style":1029},[14756],{"type":418,"value":9210},{"type":413,"tag":448,"props":14758,"children":14759},{"style":461},[14760],{"type":418,"value":4378},{"type":413,"tag":448,"props":14762,"children":14764},{"class":450,"line":14763},57,[14765,14769,14773],{"type":413,"tag":448,"props":14766,"children":14767},{"style":461},[14768],{"type":418,"value":1825},{"type":413,"tag":448,"props":14770,"children":14771},{"style":1029},[14772],{"type":418,"value":2031},{"type":413,"tag":448,"props":14774,"children":14775},{"style":461},[14776],{"type":418,"value":5802},{"type":413,"tag":448,"props":14778,"children":14780},{"class":450,"line":14779},58,[14781],{"type":413,"tag":448,"props":14782,"children":14783},{"emptyLinePlaceholder":505},[14784],{"type":418,"value":508},{"type":413,"tag":448,"props":14786,"children":14788},{"class":450,"line":14787},59,[14789,14793,14797,14801,14805,14809,14813,14817,14821,14825],{"type":413,"tag":448,"props":14790,"children":14791},{"style":461},[14792],{"type":418,"value":6133},{"type":413,"tag":448,"props":14794,"children":14795},{"style":1029},[14796],{"type":418,"value":8717},{"type":413,"tag":448,"props":14798,"children":14799},{"style":461},[14800],{"type":418,"value":898},{"type":413,"tag":448,"props":14802,"children":14803},{"style":2000},[14804],{"type":418,"value":10478},{"type":413,"tag":448,"props":14806,"children":14807},{"style":1029},[14808],{"type":418,"value":2041},{"type":413,"tag":448,"props":14810,"children":14811},{"style":461},[14812],{"type":418,"value":1183},{"type":413,"tag":448,"props":14814,"children":14815},{"style":467},[14816],{"type":418,"value":12144},{"type":413,"tag":448,"props":14818,"children":14819},{"style":461},[14820],{"type":418,"value":1183},{"type":413,"tag":448,"props":14822,"children":14823},{"style":461},[14824],{"type":418,"value":2059},{"type":413,"tag":448,"props":14826,"children":14827},{"style":461},[14828],{"type":418,"value":8752},{"type":413,"tag":448,"props":14830,"children":14832},{"class":450,"line":14831},60,[14833,14837,14841,14845,14849,14853],{"type":413,"tag":448,"props":14834,"children":14835},{"style":455},[14836],{"type":418,"value":10300},{"type":413,"tag":448,"props":14838,"children":14839},{"style":461},[14840],{"type":418,"value":464},{"type":413,"tag":448,"props":14842,"children":14843},{"style":1029},[14844],{"type":418,"value":4675},{"type":413,"tag":448,"props":14846,"children":14847},{"style":461},[14848],{"type":418,"value":898},{"type":413,"tag":448,"props":14850,"children":14851},{"style":1029},[14852],{"type":418,"value":458},{"type":413,"tag":448,"props":14854,"children":14855},{"style":461},[14856],{"type":418,"value":4378},{"type":413,"tag":448,"props":14858,"children":14860},{"class":450,"line":14859},61,[14861,14865,14869,14873,14877,14881],{"type":413,"tag":448,"props":14862,"children":14863},{"style":455},[14864],{"type":418,"value":10537},{"type":413,"tag":448,"props":14866,"children":14867},{"style":461},[14868],{"type":418,"value":464},{"type":413,"tag":448,"props":14870,"children":14871},{"style":461},[14872],{"type":418,"value":995},{"type":413,"tag":448,"props":14874,"children":14875},{"style":467},[14876],{"type":418,"value":12063},{"type":413,"tag":448,"props":14878,"children":14879},{"style":461},[14880],{"type":418,"value":1183},{"type":413,"tag":448,"props":14882,"children":14883},{"style":461},[14884],{"type":418,"value":4378},{"type":413,"tag":448,"props":14886,"children":14888},{"class":450,"line":14887},62,[14889,14893,14897,14901,14905,14909,14913,14917,14921,14925,14929],{"type":413,"tag":448,"props":14890,"children":14891},{"style":455},[14892],{"type":418,"value":10565},{"type":413,"tag":448,"props":14894,"children":14895},{"style":461},[14896],{"type":418,"value":464},{"type":413,"tag":448,"props":14898,"children":14899},{"style":1029},[14900],{"type":418,"value":4181},{"type":413,"tag":448,"props":14902,"children":14903},{"style":461},[14904],{"type":418,"value":898},{"type":413,"tag":448,"props":14906,"children":14907},{"style":2000},[14908],{"type":418,"value":12234},{"type":413,"tag":448,"props":14910,"children":14911},{"style":1029},[14912],{"type":418,"value":2041},{"type":413,"tag":448,"props":14914,"children":14915},{"style":461},[14916],{"type":418,"value":1183},{"type":413,"tag":448,"props":14918,"children":14919},{"style":467},[14920],{"type":418,"value":12247},{"type":413,"tag":448,"props":14922,"children":14923},{"style":461},[14924],{"type":418,"value":1183},{"type":413,"tag":448,"props":14926,"children":14927},{"style":1029},[14928],{"type":418,"value":2031},{"type":413,"tag":448,"props":14930,"children":14931},{"style":461},[14932],{"type":418,"value":4378},{"type":413,"tag":448,"props":14934,"children":14936},{"class":450,"line":14935},63,[14937,14941,14945],{"type":413,"tag":448,"props":14938,"children":14939},{"style":461},[14940],{"type":418,"value":1825},{"type":413,"tag":448,"props":14942,"children":14943},{"style":1029},[14944],{"type":418,"value":2031},{"type":413,"tag":448,"props":14946,"children":14947},{"style":461},[14948],{"type":418,"value":5802},{"type":413,"tag":448,"props":14950,"children":14952},{"class":450,"line":14951},64,[14953],{"type":413,"tag":448,"props":14954,"children":14955},{"emptyLinePlaceholder":505},[14956],{"type":418,"value":508},{"type":413,"tag":448,"props":14958,"children":14960},{"class":450,"line":14959},65,[14961,14965,14969,14973,14977,14981,14985,14989,14993,14997,15001,15005,15009,15013],{"type":413,"tag":448,"props":14962,"children":14963},{"style":6130},[14964],{"type":418,"value":8699},{"type":413,"tag":448,"props":14966,"children":14967},{"style":1029},[14968],{"type":418,"value":12346},{"type":413,"tag":448,"props":14970,"children":14971},{"style":461},[14972],{"type":418,"value":1037},{"type":413,"tag":448,"props":14974,"children":14975},{"style":2000},[14976],{"type":418,"value":12302},{"type":413,"tag":448,"props":14978,"children":14979},{"style":1029},[14980],{"type":418,"value":2041},{"type":413,"tag":448,"props":14982,"children":14983},{"style":461},[14984],{"type":418,"value":1183},{"type":413,"tag":448,"props":14986,"children":14987},{"style":467},[14988],{"type":418,"value":12367},{"type":413,"tag":448,"props":14990,"children":14991},{"style":461},[14992],{"type":418,"value":1183},{"type":413,"tag":448,"props":14994,"children":14995},{"style":461},[14996],{"type":418,"value":2059},{"type":413,"tag":448,"props":14998,"children":14999},{"style":461},[15000],{"type":418,"value":995},{"type":413,"tag":448,"props":15002,"children":15003},{"style":467},[15004],{"type":418,"value":12384},{"type":413,"tag":448,"props":15006,"children":15007},{"style":461},[15008],{"type":418,"value":1183},{"type":413,"tag":448,"props":15010,"children":15011},{"style":1029},[15012],{"type":418,"value":2031},{"type":413,"tag":448,"props":15014,"children":15015},{"style":461},[15016],{"type":418,"value":5802},{"type":413,"tag":448,"props":15018,"children":15020},{"class":450,"line":15019},66,[15021,15025,15029,15033,15037,15041,15045,15049,15053,15057],{"type":413,"tag":448,"props":15022,"children":15023},{"style":461},[15024],{"type":418,"value":6133},{"type":413,"tag":448,"props":15026,"children":15027},{"style":1029},[15028],{"type":418,"value":8717},{"type":413,"tag":448,"props":15030,"children":15031},{"style":461},[15032],{"type":418,"value":898},{"type":413,"tag":448,"props":15034,"children":15035},{"style":2000},[15036],{"type":418,"value":12416},{"type":413,"tag":448,"props":15038,"children":15039},{"style":1029},[15040],{"type":418,"value":2041},{"type":413,"tag":448,"props":15042,"children":15043},{"style":461},[15044],{"type":418,"value":1183},{"type":413,"tag":448,"props":15046,"children":15047},{"style":467},[15048],{"type":418,"value":12429},{"type":413,"tag":448,"props":15050,"children":15051},{"style":461},[15052],{"type":418,"value":1183},{"type":413,"tag":448,"props":15054,"children":15055},{"style":461},[15056],{"type":418,"value":2059},{"type":413,"tag":448,"props":15058,"children":15059},{"style":461},[15060],{"type":418,"value":8752},{"type":413,"tag":448,"props":15062,"children":15064},{"class":450,"line":15063},67,[15065,15069,15073,15077,15081,15085],{"type":413,"tag":448,"props":15066,"children":15067},{"style":455},[15068],{"type":418,"value":10300},{"type":413,"tag":448,"props":15070,"children":15071},{"style":461},[15072],{"type":418,"value":464},{"type":413,"tag":448,"props":15074,"children":15075},{"style":1029},[15076],{"type":418,"value":4675},{"type":413,"tag":448,"props":15078,"children":15079},{"style":461},[15080],{"type":418,"value":898},{"type":413,"tag":448,"props":15082,"children":15083},{"style":1029},[15084],{"type":418,"value":458},{"type":413,"tag":448,"props":15086,"children":15087},{"style":461},[15088],{"type":418,"value":4378},{"type":413,"tag":448,"props":15090,"children":15092},{"class":450,"line":15091},68,[15093,15097,15101,15105,15109,15113],{"type":413,"tag":448,"props":15094,"children":15095},{"style":455},[15096],{"type":418,"value":12476},{"type":413,"tag":448,"props":15098,"children":15099},{"style":461},[15100],{"type":418,"value":464},{"type":413,"tag":448,"props":15102,"children":15103},{"style":461},[15104],{"type":418,"value":995},{"type":413,"tag":448,"props":15106,"children":15107},{"style":467},[15108],{"type":418,"value":8035},{"type":413,"tag":448,"props":15110,"children":15111},{"style":461},[15112],{"type":418,"value":1183},{"type":413,"tag":448,"props":15114,"children":15115},{"style":461},[15116],{"type":418,"value":4378},{"type":413,"tag":448,"props":15118,"children":15120},{"class":450,"line":15119},69,[15121,15125,15129,15133,15137,15141],{"type":413,"tag":448,"props":15122,"children":15123},{"style":455},[15124],{"type":418,"value":12504},{"type":413,"tag":448,"props":15126,"children":15127},{"style":461},[15128],{"type":418,"value":464},{"type":413,"tag":448,"props":15130,"children":15131},{"style":461},[15132],{"type":418,"value":995},{"type":413,"tag":448,"props":15134,"children":15135},{"style":467},[15136],{"type":418,"value":12517},{"type":413,"tag":448,"props":15138,"children":15139},{"style":461},[15140],{"type":418,"value":1183},{"type":413,"tag":448,"props":15142,"children":15143},{"style":461},[15144],{"type":418,"value":4378},{"type":413,"tag":448,"props":15146,"children":15148},{"class":450,"line":15147},70,[15149,15153,15157,15161],{"type":413,"tag":448,"props":15150,"children":15151},{"style":455},[15152],{"type":418,"value":12533},{"type":413,"tag":448,"props":15154,"children":15155},{"style":461},[15156],{"type":418,"value":464},{"type":413,"tag":448,"props":15158,"children":15159},{"style":1029},[15160],{"type":418,"value":12542},{"type":413,"tag":448,"props":15162,"children":15163},{"style":461},[15164],{"type":418,"value":4378},{"type":413,"tag":448,"props":15166,"children":15168},{"class":450,"line":15167},71,[15169,15173,15177,15181,15185,15189],{"type":413,"tag":448,"props":15170,"children":15171},{"style":455},[15172],{"type":418,"value":12554},{"type":413,"tag":448,"props":15174,"children":15175},{"style":461},[15176],{"type":418,"value":464},{"type":413,"tag":448,"props":15178,"children":15179},{"style":461},[15180],{"type":418,"value":995},{"type":413,"tag":448,"props":15182,"children":15183},{"style":467},[15184],{"type":418,"value":7100},{"type":413,"tag":448,"props":15186,"children":15187},{"style":461},[15188],{"type":418,"value":1183},{"type":413,"tag":448,"props":15190,"children":15191},{"style":461},[15192],{"type":418,"value":4378},{"type":413,"tag":448,"props":15194,"children":15196},{"class":450,"line":15195},72,[15197,15201,15205,15209,15213,15217],{"type":413,"tag":448,"props":15198,"children":15199},{"style":455},[15200],{"type":418,"value":12582},{"type":413,"tag":448,"props":15202,"children":15203},{"style":461},[15204],{"type":418,"value":464},{"type":413,"tag":448,"props":15206,"children":15207},{"style":461},[15208],{"type":418,"value":995},{"type":413,"tag":448,"props":15210,"children":15211},{"style":467},[15212],{"type":418,"value":12595},{"type":413,"tag":448,"props":15214,"children":15215},{"style":461},[15216],{"type":418,"value":1183},{"type":413,"tag":448,"props":15218,"children":15219},{"style":461},[15220],{"type":418,"value":4378},{"type":413,"tag":448,"props":15222,"children":15224},{"class":450,"line":15223},73,[15225,15229,15233,15237,15241,15245],{"type":413,"tag":448,"props":15226,"children":15227},{"style":455},[15228],{"type":418,"value":12611},{"type":413,"tag":448,"props":15230,"children":15231},{"style":461},[15232],{"type":418,"value":464},{"type":413,"tag":448,"props":15234,"children":15235},{"style":461},[15236],{"type":418,"value":995},{"type":413,"tag":448,"props":15238,"children":15239},{"style":467},[15240],{"type":418,"value":12624},{"type":413,"tag":448,"props":15242,"children":15243},{"style":461},[15244],{"type":418,"value":1183},{"type":413,"tag":448,"props":15246,"children":15247},{"style":461},[15248],{"type":418,"value":4378},{"type":413,"tag":448,"props":15250,"children":15252},{"class":450,"line":15251},74,[15253,15257,15261,15265],{"type":413,"tag":448,"props":15254,"children":15255},{"style":455},[15256],{"type":418,"value":12640},{"type":413,"tag":448,"props":15258,"children":15259},{"style":461},[15260],{"type":418,"value":464},{"type":413,"tag":448,"props":15262,"children":15263},{"style":477},[15264],{"type":418,"value":12649},{"type":413,"tag":448,"props":15266,"children":15267},{"style":461},[15268],{"type":418,"value":4378},{"type":413,"tag":448,"props":15270,"children":15272},{"class":450,"line":15271},75,[15273,15277,15281],{"type":413,"tag":448,"props":15274,"children":15275},{"style":461},[15276],{"type":418,"value":1825},{"type":413,"tag":448,"props":15278,"children":15279},{"style":1029},[15280],{"type":418,"value":2031},{"type":413,"tag":448,"props":15282,"children":15283},{"style":461},[15284],{"type":418,"value":5802},{"type":413,"tag":414,"props":15286,"children":15287},{},[15288,15289,15295],{"type":418,"value":7918},{"type":413,"tag":813,"props":15290,"children":15293},{"href":15291,"rel":15292},"https://github.com/TechWatching/AzureOIDC",[817],[15294],{"type":418,"value":7928},{"type":418,"value":898},{"type":413,"tag":414,"props":15297,"children":15298},{},[15299],{"type":418,"value":15300},"I hope you enjoyed this article. Please feel free to share your thoughts in the comments, ask questions, or make suggestions. Keep learning.",{"type":413,"tag":3710,"props":15302,"children":15303},{},[15304],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":15306},[15307,15313,15314,15323,15324],{"id":7982,"depth":473,"text":7985,"children":15308},[15309,15310,15311,15312],{"id":8007,"depth":488,"text":8010},{"id":8067,"depth":488,"text":8070},{"id":8150,"depth":488,"text":8153},{"id":8251,"depth":488,"text":8254},{"id":8265,"depth":473,"text":8268},{"id":8331,"depth":473,"text":8334,"children":15315},[15316,15317,15318,15320,15321,15322],{"id":8337,"depth":488,"text":8340},{"id":913,"depth":488,"text":916},{"id":8965,"depth":488,"text":15319},"Create the identity in Azure Active Directory for the GitHub Actions workflow",{"id":9592,"depth":488,"text":9595},{"id":10207,"depth":488,"text":10210},{"id":10915,"depth":488,"text":10918},{"id":12731,"depth":473,"text":12734},{"id":7882,"depth":473,"text":7885,"children":15325},[15326,15327,15328,15329],{"id":12957,"depth":488,"text":12960},{"id":12973,"depth":488,"text":12976},{"id":13007,"depth":488,"text":13010},{"id":13104,"depth":488,"text":13107},"content:1.posts:53.azure-ready-github-repository.md","1.posts/53.azure-ready-github-repository.md",{"_path":103,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":102,"description":15333,"lead":15334,"date":15335,"image":15336,"badge":15338,"tags":15340,"body":15341,"_type":3726,"_id":15574,"_source":3728,"_file":15575,"_extension":3730},"This is my first article of the series Tips I learned this week for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.","Tooling around .NET, Azure, Github and VS Code.","2022-01-14T00:00:00.000Z",{"src":15337},"/images/surface_1.jpg",{"label":15339},"Tips",[272,239,225,233,208,206],{"type":410,"children":15342,"toc":15567},[15343,15357,15363,15376,15385,15390,15402,15413,15443,15452,15458,15472,15485,15498,15507,15520,15526,15540,15549,15562],{"type":413,"tag":414,"props":15344,"children":15345},{},[15346,15348,15355],{"type":418,"value":15347},"This is my first article of the series ",{"type":413,"tag":813,"props":15349,"children":15352},{"href":15350,"rel":15351},"https://www.techwatching.dev/tags/tips-learned-this-week/",[817],[15353],{"type":418,"value":15354},"Tips I learned this week",{"type":418,"value":15356}," for 2022 🚀! And today we are going to see some tips about .NET, Azure, GitHub, and VS Code.",{"type":413,"tag":420,"props":15358,"children":15360},{"id":15359},"net-tip-of-the-week-changing-the-net-cli-language",[15361],{"type":418,"value":15362},".NET tip of the week: changing the .NET CLI language",{"type":413,"tag":414,"props":15364,"children":15365},{},[15366,15368,15374],{"type":418,"value":15367},"Did you know that you could change the language of the .NET CLI to the one you find most appropriate? By default, the dotnet CLI messages you see when running a dotnet program are your language OS (French in my case). However, by setting the \"DOTNET_CLI_UI_LANGUAGE\" variable environment to ",{"type":413,"tag":444,"props":15369,"children":15371},{"className":15370},[],[15372],{"type":418,"value":15373},"en",{"type":418,"value":15375}," for instance I can change it to English.",{"type":413,"tag":414,"props":15377,"children":15378},{},[15379],{"type":413,"tag":832,"props":15380,"children":15384},{"alt":15381,"className":15382,"src":15383},".NET CLI language change in terminal.",[836,837],"/posts/images/w022022tips_dotnet_cli.png",[],{"type":413,"tag":414,"props":15386,"children":15387},{},[15388],{"type":418,"value":15389},"Why is it useful? Let's imagine I have an issue with a dotnet CLI command and that I want to get some help from the community by posting a question to a Q&A website with a screenshot of my error. If all the messages are in French I will probably not get many answers whereas if it's in English everyone will be able to understand what my commands are doing. There is also the fact that sometimes French accents and special characters are not well displayed by some terminals.",{"type":413,"tag":420,"props":15391,"children":15393},{"id":15392},"the-azure-tip-you-did-not-know-about-simplify-your-azure-cli-configuration-with-azure-init",[15394,15396],{"type":418,"value":15395},"The Azure tip you did not know about: simplify your Azure CLI configuration with ",{"type":413,"tag":444,"props":15397,"children":15399},{"className":15398},[],[15400],{"type":418,"value":15401},"azure init",{"type":413,"tag":414,"props":15403,"children":15404},{},[15405,15407,15412],{"type":418,"value":15406},"I don't know if you use a lot Azure CLI but it's a very nice tool! Each time I use Azure CLI, I think \"it's awesome 🤩 I should use it more often instead of using Azure Portal\". I even wrote a post about that 2 years ago: \"",{"type":413,"tag":813,"props":15408,"children":15410},{"href":1382,"rel":15409},[817],[15411],{"type":418,"value":15},{"type":418,"value":7979},{"type":413,"tag":414,"props":15414,"children":15415},{},[15416,15418,15424,15426,15433,15435,15441],{"type":418,"value":15417},"However, if you want to configure your Azure CLI, it can be sometimes a bit boring and slow to configure it using the ",{"type":413,"tag":444,"props":15419,"children":15421},{"className":15420},[],[15422],{"type":418,"value":15423},"az config",{"type":418,"value":15425}," command. That is why Microsoft has ",{"type":413,"tag":813,"props":15427,"children":15430},{"href":15428,"rel":15429},"https://techcommunity.microsoft.com/t5/azure-tools-blog/streamline-configuring-azure-cli-with-az-init/ba-p/3051810",[817],[15431],{"type":418,"value":15432},"released in preview",{"type":418,"value":15434}," an Azure CLI extension called ",{"type":413,"tag":444,"props":15436,"children":15438},{"className":15437},[],[15439],{"type":418,"value":15440},"az init",{"type":418,"value":15442}," to simplify this configuration. For example you can quickly configure the output of the commands or the syntax highlighting, things like that.",{"type":413,"tag":414,"props":15444,"children":15445},{},[15446],{"type":413,"tag":832,"props":15447,"children":15451},{"alt":15448,"className":15449,"src":15450},"azure init command output.",[836,837],"/posts/images/w022022tips_az_init.png",[],{"type":413,"tag":420,"props":15453,"children":15455},{"id":15454},"tool-of-the-week-github-code-search",[15456],{"type":418,"value":15457},"Tool of the week: GitHub Code Search",{"type":413,"tag":414,"props":15459,"children":15460},{},[15461,15463,15470],{"type":418,"value":15462},"Have you ever wished you could easily search code on GitHub in multiple repositories without cloning anything? That is now possible with ",{"type":413,"tag":813,"props":15464,"children":15467},{"href":15465,"rel":15466},"https://cs.github.com/",[817],[15468],{"type":418,"value":15469},"GitHub Code Search",{"type":418,"value":15471},". It is still in preview but looks promising! You have access to nice filters to find exactly the code you are looking for, and once you get it you can navigate in and across files.",{"type":413,"tag":414,"props":15473,"children":15474},{},[15475,15477,15483],{"type":418,"value":15476},"For a long time, I have kept a bookmark to the \"",{"type":413,"tag":813,"props":15478,"children":15481},{"href":15479,"rel":15480},"https://source.dot.net/",[817],[15482],{"type":418,"value":15479},{"type":418,"value":15484},"\" website for the times when I needed to understand how something was implemented in the .NET Core framework. But with GitHub Code Search I think I don't need it anymore. .NET Core is open source and all the source code is on GitHub so I can quickly find everything I need just by searching it on GitHub.",{"type":413,"tag":414,"props":15486,"children":15487},{},[15488,15490,15496],{"type":418,"value":15489},"For instance, let's say I don't remember exactly what configuration is injected by default in a dotnet project when you use the ",{"type":413,"tag":444,"props":15491,"children":15493},{"className":15492},[],[15494],{"type":418,"value":15495},"Host.CreateDefaultBuilder",{"type":418,"value":15497}," method. I will scope my search to dotnet organization repositories and a few keystrokes later, I can see all the configuration providers used to load some default configuration in a project.",{"type":413,"tag":414,"props":15499,"children":15500},{},[15501],{"type":413,"tag":832,"props":15502,"children":15506},{"alt":15503,"className":15504,"src":15505},"GitHub search usage.",[836,837],"/posts/images/w022022tips_githu_cs.gif",[],{"type":413,"tag":414,"props":15508,"children":15509},{},[15510,15512,15519],{"type":418,"value":15511},"You can read more about GitHub Code Search on ",{"type":413,"tag":813,"props":15513,"children":15516},{"href":15514,"rel":15515},"https://github.blog/2021-12-08-improving-github-code-search/",[817],[15517],{"type":418,"value":15518},"GitHub's blog",{"type":418,"value":898},{"type":413,"tag":420,"props":15521,"children":15523},{"id":15522},"the-vs-code-extension-you-should-try-i18n-ally",[15524],{"type":418,"value":15525},"The VS Code extension you should try: i18n ally",{"type":413,"tag":414,"props":15527,"children":15528},{},[15529,15531,15538],{"type":418,"value":15530},"When you are developing an application that supports several languages, it can quickly become annoying to go in every translation file when you need to check or modify a translation. If you are developing your application using VS Code, you probably should check out the extension ",{"type":413,"tag":813,"props":15532,"children":15535},{"href":15533,"rel":15534},"https://github.com/lokalise/i18n-ally",[817],[15536],{"type":418,"value":15537},"i18n ally",{"type":418,"value":15539}," because it will save you a lot of time.",{"type":413,"tag":414,"props":15541,"children":15542},{},[15543],{"type":413,"tag":832,"props":15544,"children":15548},{"alt":15545,"className":15546,"src":15547},"i18n ally extension in vscode.",[836,837],"/posts/images/w222021tips_i18n_ally.png",[],{"type":413,"tag":414,"props":15550,"children":15551},{},[15552,15554,15560],{"type":418,"value":15553},"It is very handy and I like the fact the extension support lots of frameworks like Vue.js, Angular, React, Svelte, and Flutter (you can find the complete list of supported frameworks ",{"type":413,"tag":813,"props":15555,"children":15558},{"href":15556,"rel":15557},"https://github.com/lokalise/i18n-ally/wiki/Supported-Frameworks",[817],[15559],{"type":418,"value":1386},{"type":418,"value":15561},"). My only regret with this extension is not to have heard about it sooner.",{"type":413,"tag":414,"props":15563,"children":15564},{},[15565],{"type":418,"value":15566},"And that's it for this week, happy learning!",{"title":401,"searchDepth":473,"depth":473,"links":15568},[15569,15570,15572,15573],{"id":15359,"depth":473,"text":15362},{"id":15392,"depth":473,"text":15571},"The Azure tip you did not know about: simplify your Azure CLI configuration with azure init",{"id":15454,"depth":473,"text":15457},{"id":15522,"depth":473,"text":15525},"content:1.posts:32.w02-2022-tips-learned-this-week.md","1.posts/32.w02-2022-tips-learned-this-week.md",{"_path":94,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":93,"description":15577,"date":15578,"lead":15579,"image":15580,"badge":15582,"tags":15584,"body":15585,"_type":3726,"_id":15890,"_source":3728,"_file":15891,"_extension":3730},"Do you often star a GitHub repository and later when you want to get back to it struggle to find it on your stars page? I do! Well, I did... until I discovered Astral, the web application that allows you to Organize Your GitHub Stars With Ease. That is what we are going to talk about in this article.","2021-11-28T00:00:00.000Z","Another way to bookmark GitHub repositories.",{"src":15581},"/images/stars_1.jpg",{"label":15583},"Tooling",[206,233],{"type":410,"children":15586,"toc":15883},[15587,15609,15615,15637,15642,15651,15656,15665,15671,15676,15699,15704,15710,15721,15730,15735,15740,15763,15772,15780,15786,15791,15796,15814,15822,15831,15836,15857,15866,15870],{"type":413,"tag":414,"props":15588,"children":15589},{},[15590,15592,15599,15601,15607],{"type":418,"value":15591},"Do you often star a GitHub repository and later when you want to get back to it struggle to find it on your stars page? I do! Well, I did... until I discovered ",{"type":413,"tag":813,"props":15593,"children":15596},{"href":15594,"rel":15595},"https://astralapp.com/",[817],[15597],{"type":418,"value":15598},"Astral",{"type":418,"value":15600},", the web application that allows you to ",{"type":413,"tag":444,"props":15602,"children":15604},{"className":15603},[],[15605],{"type":418,"value":15606},"Organize Your GitHub Stars With Ease",{"type":418,"value":15608},". That is what we are going to talk about in this article.",{"type":413,"tag":420,"props":15610,"children":15612},{"id":15611},"github-stars-as-a-bookmarking-tool",[15613],{"type":418,"value":15614},"GitHub stars as a bookmarking tool.",{"type":413,"tag":414,"props":15616,"children":15617},{},[15618,15620,15627,15629,15635],{"type":418,"value":15619},"When you find an interesting GitHub repository, instead of adding it to your browser bookmarks among a lot of other websites, you can star it. As ",{"type":413,"tag":813,"props":15621,"children":15624},{"href":15622,"rel":15623},"https://docs.github.com/en/get-started/exploring-projects-on-github/saving-repositories-with-stars",[817],[15625],{"type":418,"value":15626},"GitHub Docs",{"type":418,"value":15628}," say: ",{"type":413,"tag":444,"props":15630,"children":15632},{"className":15631},[],[15633],{"type":418,"value":15634},"Starring make it easy to find a repository again later",{"type":418,"value":15636},". Indeed usually, when I come across a nice GitHub repository, I want to go back to it later (to deep dive into the awesome framework I discover, to try this new open source tool, to have this useful sample somewhere when I will need it...).",{"type":413,"tag":414,"props":15638,"children":15639},{},[15640],{"type":418,"value":15641},"As you can see below, all the GitHub repositories you have starred can be found on your GitHub stars page.",{"type":413,"tag":414,"props":15643,"children":15644},{},[15645],{"type":413,"tag":832,"props":15646,"children":15650},{"alt":15647,"className":15648,"src":15649},"\"Your stars\" menu in GitHub.",[836,837],"/posts/images/astral_github_1.png",[],{"type":413,"tag":414,"props":15652,"children":15653},{},[15654],{"type":418,"value":15655},"In addition to that, you can sort, filter (by language or topic), and search starred repositories:",{"type":413,"tag":414,"props":15657,"children":15658},{},[15659],{"type":413,"tag":832,"props":15660,"children":15664},{"alt":15661,"className":15662,"src":15663},"Starred GitHub repositories filters.",[836,837],"/posts/images/astral_github_2.png",[],{"type":413,"tag":420,"props":15666,"children":15668},{"id":15667},"have-you-seen-that-repository-i-am-looking-for",[15669],{"type":418,"value":15670},"Have you seen that repository I am looking for?",{"type":413,"tag":414,"props":15672,"children":15673},{},[15674],{"type":418,"value":15675},"Using GitHub stars to bookmark the repositories you are interested in is great but if you do it a lot, it can become hard to find later the repository you want. Even if it is possible to sort, filter, and search repositories, it is sometimes impossible to quickly find what you are looking for. And there are good reasons for that:",{"type":413,"tag":3766,"props":15677,"children":15678},{},[15679,15684,15689,15694],{"type":413,"tag":2159,"props":15680,"children":15681},{},[15682],{"type":418,"value":15683},"You have starred this repository a long time ago, and it does not stand out from other repositories in terms of activity or number of stars so sorting won't help you",{"type":413,"tag":2159,"props":15685,"children":15686},{},[15687],{"type":418,"value":15688},"Most of your starred repositories are in the same language so filters are useless",{"type":413,"tag":2159,"props":15690,"children":15691},{},[15692],{"type":418,"value":15693},"The repository was not tagged with a topic that could help you to find it",{"type":413,"tag":2159,"props":15695,"children":15696},{},[15697],{"type":418,"value":15698},"You don't remember the name of the repository",{"type":413,"tag":414,"props":15700,"children":15701},{},[15702],{"type":418,"value":15703},"The problem is that starred repositories can only be filtered with information that is not particularly useful to you. What we would need is something to organize the starred repositories in a way relevant to us. And here comes Astral.",{"type":413,"tag":420,"props":15705,"children":15707},{"id":15706},"what-is-astral",[15708],{"type":418,"value":15709},"What is Astral?",{"type":413,"tag":414,"props":15711,"children":15712},{},[15713,15719],{"type":413,"tag":813,"props":15714,"children":15717},{"href":15715,"rel":15716},"https://github.com/astralapp/astral",[817],[15718],{"type":418,"value":15598},{"type":418,"value":15720}," is an open source web application that helps you organize your starred repositories.",{"type":413,"tag":414,"props":15722,"children":15723},{},[15724],{"type":413,"tag":832,"props":15725,"children":15729},{"alt":15726,"className":15727,"src":15728},"Astral home website.",[836,837],"/posts/images/astral_app_1.png",[],{"type":413,"tag":414,"props":15731,"children":15732},{},[15733],{"type":418,"value":15734},"It solves the issues I was previously pointing out by allowing us to add tags to our starred repositories. That means I can create a tag with a meaningful name and add this tag to the appropriate repositories.",{"type":413,"tag":414,"props":15736,"children":15737},{},[15738],{"type":418,"value":15739},"Once grouped by tags, it becomes very easy to find the repositories you need. The interface is quite simple but shows all the information we need:",{"type":413,"tag":3766,"props":15741,"children":15742},{},[15743,15748,15753,15758],{"type":413,"tag":2159,"props":15744,"children":15745},{},[15746],{"type":418,"value":15747},"the list of starred repositories grouped by tags",{"type":413,"tag":2159,"props":15749,"children":15750},{},[15751],{"type":418,"value":15752},"basic information for each repository (language, number of stars, number of pull requests, number of days since the last commit, the latest release, ...)",{"type":413,"tag":2159,"props":15754,"children":15755},{},[15756],{"type":418,"value":15757},"a preview of the README file of the currently selected repository with the URL to quickly clone the repository",{"type":413,"tag":2159,"props":15759,"children":15760},{},[15761],{"type":418,"value":15762},"a notes section where you can write extra information for each repository",{"type":413,"tag":414,"props":15764,"children":15765},{},[15766],{"type":413,"tag":832,"props":15767,"children":15771},{"alt":15768,"className":15769,"src":15770},"List of starred repositories in Astral.",[836,837],"/posts/images/astral_app_2.png",[],{"type":413,"tag":841,"props":15773,"children":15774},{"icon":843},[15775],{"type":413,"tag":414,"props":15776,"children":15777},{},[15778],{"type":418,"value":15779},"Astral can also be self-hosted if you need. As it is a free web application, I don't see the point of self-hosting it but it is possible.",{"type":413,"tag":420,"props":15781,"children":15783},{"id":15782},"how-do-i-use-astral",[15784],{"type":418,"value":15785},"How do I use Astral?",{"type":413,"tag":414,"props":15787,"children":15788},{},[15789],{"type":418,"value":15790},"I organize my starred repositories by grouping them with tags that I create in Astral and that are relevant to my way of categorizing things. That is the power of creating custom tags and assigning repositories to them, everyone can organize its starred repositories as it suits him or her.",{"type":413,"tag":414,"props":15792,"children":15793},{},[15794],{"type":418,"value":15795},"To be honest, I only started to use Astral recently so my organization is subject to change but here are kinds of tags I like to create:",{"type":413,"tag":3766,"props":15797,"children":15798},{},[15799,15804,15809],{"type":413,"tag":2159,"props":15800,"children":15801},{},[15802],{"type":418,"value":15803},"Tags for different IT areas (like database, cloud, testing, IoT,..)",{"type":413,"tag":2159,"props":15805,"children":15806},{},[15807],{"type":418,"value":15808},"Tags for the type of repository (like libraries, training, samples)",{"type":413,"tag":2159,"props":15810,"children":15811},{},[15812],{"type":418,"value":15813},"Tags for the different frameworks I am interested in",{"type":413,"tag":841,"props":15815,"children":15816},{"icon":843},[15817],{"type":413,"tag":414,"props":15818,"children":15819},{},[15820],{"type":418,"value":15821},"The language used in a repository is one thing but that does not say what framework is used (like ASP.NET Core, MAUI, Vue.js, React.js,...) and that can be a useful criterion when you are later looking for repositories using a specific framework",{"type":413,"tag":414,"props":15823,"children":15824},{},[15825],{"type":413,"tag":832,"props":15826,"children":15830},{"alt":15827,"className":15828,"src":15829},"Astral website with tags.",[836,837],"/posts/images/astral_app_3.png",[],{"type":413,"tag":414,"props":15832,"children":15833},{},[15834],{"type":418,"value":15835},"Starred repositories I have not yet tagged are located in the top left corner of the application. I try to tag a starred repository with different tags to help the future me looking for some repositories with multiple criteria.",{"type":413,"tag":414,"props":15837,"children":15838},{},[15839,15841,15847,15849,15855],{"type":418,"value":15840},"Speaking of multiple criteria, you can create ",{"type":413,"tag":444,"props":15842,"children":15844},{"className":15843},[],[15845],{"type":418,"value":15846},"Smart Filters",{"type":418,"value":15848}," in Astral to filter your starred repositories with specific rules. For instance, I created a smart filter called ",{"type":413,"tag":444,"props":15850,"children":15852},{"className":15851},[],[15853],{"type":418,"value":15854},"Microsoft 365 samples",{"type":418,"value":15856}," to list active repositories showing samples to build Microsoft 365 applications (Teams applications, applications using Microsoft Graph...). This is just an example but you can create much more complex filters.",{"type":413,"tag":414,"props":15858,"children":15859},{},[15860],{"type":413,"tag":832,"props":15861,"children":15865},{"alt":15862,"className":15863,"src":15864},"Smart filters in Astral.",[836,837],"/posts/images/astral_app_4.png",[],{"type":413,"tag":420,"props":15867,"children":15868},{"id":7882},[15869],{"type":418,"value":7885},{"type":413,"tag":414,"props":15871,"children":15872},{},[15873,15875,15881],{"type":418,"value":15874},"If you are often bookmarking GitHub repositories for future usage, Astral is a nice little web application to add to your toolbox. I found it by chance, but I liked it and I am now regularly using it. So try it and if you like it, give it a star and tag the repo with a ",{"type":413,"tag":444,"props":15876,"children":15878},{"className":15877},[],[15879],{"type":418,"value":15880},"tools",{"type":418,"value":15882}," tag in Astral 😉.",{"title":401,"searchDepth":473,"depth":473,"links":15884},[15885,15886,15887,15888,15889],{"id":15611,"depth":473,"text":15614},{"id":15667,"depth":473,"text":15670},{"id":15706,"depth":473,"text":15709},{"id":15782,"depth":473,"text":15785},{"id":7882,"depth":473,"text":7885},"content:1.posts:29.astral.md","1.posts/29.astral.md",{"_path":88,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":87,"description":15893,"lead":15894,"date":15895,"badge":15896,"image":15897,"tags":15899,"body":15900,"_type":3726,"_id":17076,"_source":3728,"_file":17077,"_extension":3730},"Today I talk to you about the recent changes I made to my blog when I migrated it to Statiq and open-sourced it.","What changed on my blog - Statiq, GitHub, giscus, and much more.","2021-11-07T00:00:00.000Z",{"label":15583},{"src":15898},"/images/migration_1.jpg",[331,239,233,307,334],{"type":410,"children":15901,"toc":17059},[15902,15915,15921,15926,15988,15993,15999,16005,16010,16032,16044,16121,16127,16141,16146,16152,16166,16179,16184,16193,16207,16213,16233,16246,16252,16257,16263,16268,16277,16282,16290,16304,16313,16325,16355,16361,16366,16735,16740,16746,16751,16760,16766,16778,16806,16819,16869,16878,16890,16923,16929,16943,16952,16958,16963,17033,17038,17055],{"type":413,"tag":414,"props":15903,"children":15904},{},[15905,15907,15913],{"type":418,"value":15906},"Today I talk to you about the recent changes I made to my blog when I migrated it to ",{"type":413,"tag":813,"props":15908,"children":15911},{"href":15909,"rel":15910},"https://statiq.dev/",[817],[15912],{"type":418,"value":331},{"type":418,"value":15914}," and open-sourced it.",{"type":413,"tag":420,"props":15916,"children":15918},{"id":15917},"some-context",[15919],{"type":418,"value":15920},"Some context",{"type":413,"tag":414,"props":15922,"children":15923},{},[15924],{"type":418,"value":15925},"I initially created my blog in March 2019 using:",{"type":413,"tag":3766,"props":15927,"children":15928},{},[15929,15941,15953,15964,15976],{"type":413,"tag":2159,"props":15930,"children":15931},{},[15932,15939],{"type":413,"tag":813,"props":15933,"children":15936},{"href":15934,"rel":15935},"https://github.com/Wyamio/Wyam",[817],[15937],{"type":418,"value":15938},"Wyam",{"type":418,"value":15940}," (a .NET static website generator) to generate the website",{"type":413,"tag":2159,"props":15942,"children":15943},{},[15944,15951],{"type":413,"tag":813,"props":15945,"children":15948},{"href":15946,"rel":15947},"https://azure.microsoft.com/en-us/services/devops/repos/",[817],[15949],{"type":418,"value":15950},"Azure Repos",{"type":418,"value":15952}," to store the source code on a private git repository",{"type":413,"tag":2159,"props":15954,"children":15955},{},[15956,15962],{"type":413,"tag":813,"props":15957,"children":15960},{"href":15958,"rel":15959},"https://azure.microsoft.com/en-us/services/devops/pipelines/",[817],[15961],{"type":418,"value":278},{"type":418,"value":15963}," to build and deploy the website",{"type":413,"tag":2159,"props":15965,"children":15966},{},[15967,15974],{"type":413,"tag":813,"props":15968,"children":15971},{"href":15969,"rel":15970},"https://www.netlify.com/",[817],[15972],{"type":418,"value":15973},"Netlify",{"type":418,"value":15975}," to host the website",{"type":413,"tag":2159,"props":15977,"children":15978},{},[15979,15986],{"type":413,"tag":813,"props":15980,"children":15983},{"href":15981,"rel":15982},"https://disqus.com/",[817],[15984],{"type":418,"value":15985},"Disqus",{"type":418,"value":15987}," to allow visitors to comment on my articles",{"type":413,"tag":414,"props":15989,"children":15990},{},[15991],{"type":418,"value":15992},"A little bit more than 2 years later in October 2021, everything was still working perfectly fine and I could have let everything that way. Yet, I thought some things could be improved and I wanted to change some parts of this stack.",{"type":413,"tag":420,"props":15994,"children":15996},{"id":15995},"migrating-from-wyam-to-statiq",[15997],{"type":418,"value":15998},"Migrating from Wyam to Statiq",{"type":413,"tag":866,"props":16000,"children":16002},{"id":16001},"why",[16003],{"type":418,"value":16004},"Why?",{"type":413,"tag":414,"props":16006,"children":16007},{},[16008],{"type":418,"value":16009},"I am convinced that static website generators have a great future and are one of the best solutions for blogs #ThisIsTheWay.",{"type":413,"tag":414,"props":16011,"children":16012},{},[16013,16015,16021,16023,16030],{"type":418,"value":16014},"Although Wyam was working fine for my blog, it has been \"rebranded and rebooted as ",{"type":413,"tag":813,"props":16016,"children":16019},{"href":16017,"rel":16018},"https://www.statiq.dev/",[817],[16020],{"type":418,"value":331},{"type":418,"value":16022}," with a ton of improvements\" (as you can read on ",{"type":413,"tag":813,"props":16024,"children":16027},{"href":16025,"rel":16026},"https://wyam.io/",[817],[16028],{"type":418,"value":16029},"Wyam website",{"type":418,"value":16031},") so it made sense to migrate to use an actively maintained tool.",{"type":413,"tag":414,"props":16033,"children":16034},{},[16035,16037,16042],{"type":418,"value":16036},"I could have migrated to another static website generator (there are so many of them!) but I like using one written in .NET. If I want to customize how my website is generated, I can easily modify the code as it's .NET code. So ",{"type":413,"tag":444,"props":16038,"children":16040},{"className":16039},[],[16041],{"type":418,"value":331},{"type":418,"value":16043}," is a good choice for me.",{"type":413,"tag":841,"props":16045,"children":16046},{"icon":843},[16047,16066],{"type":413,"tag":414,"props":16048,"children":16049},{},[16050,16052,16057,16059,16064],{"type":418,"value":16051},"By the way, in this article when I am talking about ",{"type":413,"tag":444,"props":16053,"children":16055},{"className":16054},[],[16056],{"type":418,"value":331},{"type":418,"value":16058}," I am talking about the static site generator but technically ",{"type":413,"tag":444,"props":16060,"children":16062},{"className":16061},[],[16063],{"type":418,"value":331},{"type":418,"value":16065}," is more than that. It is a static generation platform that is divided into 3 parts:",{"type":413,"tag":3766,"props":16067,"children":16068},{},[16069,16080,16096],{"type":413,"tag":2159,"props":16070,"children":16071},{},[16072,16078],{"type":413,"tag":444,"props":16073,"children":16075},{"className":16074},[],[16076],{"type":418,"value":16077},"Statiq Framework",{"type":418,"value":16079}," ➡ a framework to build a custom static generator application",{"type":413,"tag":2159,"props":16081,"children":16082},{},[16083,16089,16091],{"type":413,"tag":444,"props":16084,"children":16086},{"className":16085},[],[16087],{"type":418,"value":16088},"Statiq Web",{"type":418,"value":16090}," ➡ a static website generation toolkit built on top of ",{"type":413,"tag":444,"props":16092,"children":16094},{"className":16093},[],[16095],{"type":418,"value":16077},{"type":413,"tag":2159,"props":16097,"children":16098},{},[16099,16105,16107,16112,16114,16120],{"type":413,"tag":444,"props":16100,"children":16102},{"className":16101},[],[16103],{"type":418,"value":16104},"Statiq Docs",{"type":418,"value":16106}," ➡ a toolkit built on top of ",{"type":413,"tag":444,"props":16108,"children":16110},{"className":16109},[],[16111],{"type":418,"value":16088},{"type":418,"value":16113}," to generate a site with .NET API documentation\nYou may not know, but the .NET Foundation website is generated using ",{"type":413,"tag":444,"props":16115,"children":16117},{"className":16116},[],[16118],{"type":418,"value":16119},"Statiq.Web",{"type":418,"value":898},{"type":413,"tag":866,"props":16122,"children":16124},{"id":16123},"how",[16125],{"type":418,"value":16126},"How?",{"type":413,"tag":414,"props":16128,"children":16129},{},[16130,16132,16139],{"type":418,"value":16131},"Migration was quite easy (some CSS classes to replace and some configuration to change and that was it!). Statiq has a ",{"type":413,"tag":813,"props":16133,"children":16136},{"href":16134,"rel":16135},"https://www.statiq.dev/web/porting-from-wyam",[817],[16137],{"type":418,"value":16138},"page",{"type":418,"value":16140}," in its documentation to explain how to do that.",{"type":413,"tag":414,"props":16142,"children":16143},{},[16144],{"type":418,"value":16145},"The main difference is that instead of using the Wyam CLI to generate my blog from my articles in markdown and a config file, I now have a .NET console application that I run to do the same.",{"type":413,"tag":866,"props":16147,"children":16149},{"id":16148},"what-changed",[16150],{"type":418,"value":16151},"What changed?",{"type":413,"tag":414,"props":16153,"children":16154},{},[16155,16157,16164],{"type":418,"value":16156},"Although Statiq is a reboot of Wyam, and a lot has changed internally, my blog is pretty much the same as before. Statiq comes with the theme ",{"type":413,"tag":813,"props":16158,"children":16161},{"href":16159,"rel":16160},"https://github.com/statiqdev/CleanBlog",[817],[16162],{"type":418,"value":16163},"CleanBlog",{"type":418,"value":16165}," that I was using before with Wyam so the UI looks the same. However as it uses a more recent version of the theme, the migration brought a few improvements to my blog:",{"type":413,"tag":3766,"props":16167,"children":16168},{},[16169,16174],{"type":413,"tag":2159,"props":16170,"children":16171},{},[16172],{"type":418,"value":16173},"there is now a search box to search my blog (everything is indexed so finding an article that might interest you is easier than ever)",{"type":413,"tag":2159,"props":16175,"children":16176},{},[16177],{"type":418,"value":16178},"the code highlighting is prettier than before",{"type":413,"tag":414,"props":16180,"children":16181},{},[16182],{"type":418,"value":16183},"You can see below an example of that:",{"type":413,"tag":414,"props":16185,"children":16186},{},[16187],{"type":413,"tag":832,"props":16188,"children":16192},{"alt":16189,"className":16190,"src":16191},"Screenshot of the techwatching.dev blog.",[836,837],"/posts/images/migrating_blog_1.png",[],{"type":413,"tag":414,"props":16194,"children":16195},{},[16196,16198,16205],{"type":418,"value":16197},"I also took the opportunity of migrating my blog to correct a lot of grammar and spelling mistakes there were on my articles. To find the mistakes and correct them I used the free version of ",{"type":413,"tag":813,"props":16199,"children":16202},{"href":16200,"rel":16201},"https://www.grammarly.com/",[817],[16203],{"type":418,"value":16204},"Grammarly",{"type":418,"value":16206}," and I was surprised by how good it was. I intend to use it to write my future articles and I strongly recommend it to you. It is especially useful to me as I am not an English native speaker. Of course, I am not saying there will be no mistake in my articles but I should catch most of them with Grammarly.",{"type":413,"tag":420,"props":16208,"children":16210},{"id":16209},"open-sourcing-my-blog",[16211],{"type":418,"value":16212},"Open-sourcing my blog",{"type":413,"tag":414,"props":16214,"children":16215},{},[16216,16218,16224,16226,16232],{"type":418,"value":16217},"People interested in creating their blog sometimes ask me what stack I used to build my blog. So I thought open-sourcing my blog would be a great way to answer this question and show exactly how this blog is built. If you are a .NET developer and want to create your blog, I strongly recommend you to use ",{"type":413,"tag":813,"props":16219,"children":16222},{"href":16220,"rel":16221},"https://www.statiq.dev/web/",[817],[16223],{"type":418,"value":16088},{"type":418,"value":16225},". You can get started by following the documentation, it is very easy. And now, you have an example of a blog using Statiq that you can look at ",{"type":413,"tag":813,"props":16227,"children":16230},{"href":16228,"rel":16229},"https://github.com/techwatching/techwatching.dev",[817],[16231],{"type":418,"value":1386},{"type":418,"value":898},{"type":413,"tag":414,"props":16234,"children":16235},{},[16236,16238,16244],{"type":418,"value":16237},"I am often a consumer of open source code (as we all are these days) so it feels great to be a contributor this time by sharing the source code of my blog (even if there is currently not much customization). I don't expect many people to look at it but at least it's ",{"type":413,"tag":813,"props":16239,"children":16241},{"href":16228,"rel":16240},[817],[16242],{"type":418,"value":16243},"there",{"type":418,"value":16245}," if you care.",{"type":413,"tag":420,"props":16247,"children":16249},{"id":16248},"all-in-on-github",[16250],{"type":418,"value":16251},"All-in on GitHub",{"type":413,"tag":414,"props":16253,"children":16254},{},[16255],{"type":418,"value":16256},"GitHub is one of the best platforms for open source projects. But whether it be for open source or proprietary software, GitHub is above all a great development platform to build, ship, and maintain software. I am more familiar with Azure DevOps which is a great platform too and that I use at work but using GitHub was the opportunity to learn new things. Therefore, I decided to migrate to GitHub for my blog and not only for hosting the code.",{"type":413,"tag":866,"props":16258,"children":16260},{"id":16259},"hosting-the-source-code-of-my-blog",[16261],{"type":418,"value":16262},"Hosting the source code of my blog",{"type":413,"tag":414,"props":16264,"children":16265},{},[16266],{"type":418,"value":16267},"Speaking of hosting the code, here is my new git repository on GitHub:",{"type":413,"tag":414,"props":16269,"children":16270},{},[16271],{"type":413,"tag":832,"props":16272,"children":16276},{"alt":16273,"className":16274,"src":16275},"Techwatching.dev GitHub repository.",[836,837],"/posts/images/migrating_blog_2.png",[],{"type":413,"tag":414,"props":16278,"children":16279},{},[16280],{"type":418,"value":16281},"To move my code to GitHub, I just created a new git repository in GitHub and copy-pasted my code there. Adding GitHub as a new remote of my repository could have been a better way to migrate my code to GitHub while preserving the commit history. However, I did not care about history and took the opportunity to reorganize my code.",{"type":413,"tag":841,"props":16283,"children":16284},{"icon":843},[16285],{"type":413,"tag":414,"props":16286,"children":16287},{},[16288],{"type":418,"value":16289},"I know that it is possible to have public projects/git repositories in Azure DevOps so I could have kept my code there, but as I said, moving to GitHub to store my code was a choice.",{"type":413,"tag":414,"props":16291,"children":16292},{},[16293,16295,16302],{"type":418,"value":16294},"And now that my git repository is on GitHub, I can use the ",{"type":413,"tag":813,"props":16296,"children":16299},{"href":16297,"rel":16298},"https://docs.github.com/en/codespaces/the-githubdev-web-based-editor",[817],[16300],{"type":418,"value":16301},"github.dev",{"type":418,"value":16303}," web-based editor to modify my repository directly in the browser. How cool is that?",{"type":413,"tag":414,"props":16305,"children":16306},{},[16307],{"type":413,"tag":832,"props":16308,"children":16312},{"alt":16309,"className":16310,"src":16311},"Blog in github.dev editor.",[836,837],"/posts/images/migrating_blog_3.png",[],{"type":413,"tag":414,"props":16314,"children":16315},{},[16316,16318,16323],{"type":418,"value":16317},"I don't know if I will use ",{"type":413,"tag":444,"props":16319,"children":16321},{"className":16320},[],[16322],{"type":418,"value":16301},{"type":418,"value":16324}," a lot but I like the fact of being able to work on my blog from any computer without having to install anything.",{"type":413,"tag":841,"props":16326,"children":16327},{"icon":1103},[16328],{"type":413,"tag":414,"props":16329,"children":16330},{},[16331,16333,16338,16340,16346,16348,16353],{"type":418,"value":16332},"If you never heard of github.dev, simply go to any GitHub repository in your favorite web browser and press ",{"type":413,"tag":444,"props":16334,"children":16336},{"className":16335},[],[16337],{"type":418,"value":898},{"type":418,"value":16339}," to open this repository in a vscode-like editor that runs entirely in your browser. You can also replace ",{"type":413,"tag":444,"props":16341,"children":16343},{"className":16342},[],[16344],{"type":418,"value":16345},"github.com",{"type":418,"value":16347}," with ",{"type":413,"tag":444,"props":16349,"children":16351},{"className":16350},[],[16352],{"type":418,"value":16301},{"type":418,"value":16354}," in the URL to open it. It even works on your mobile although I don't find it very convenient.",{"type":413,"tag":866,"props":16356,"children":16358},{"id":16357},"building-and-deploying-my-blog",[16359],{"type":418,"value":16360},"Building and deploying my blog",{"type":413,"tag":414,"props":16362,"children":16363},{},[16364],{"type":418,"value":16365},"Coming from Azure DevOps, moving from Azure Pipelines to GitHub Actions was not a big deal. What changed however is that my pipeline doesn't need to install any specific CLI to build and deploy my blog. Indeed, with Statiq my blog is a .NET console application, so my site can be generated directly with the .NET CLI. Statiq as built-in support for deploying a website on different platforms including Netlify thus my pipeline to generate and deploy my site is quite simple:",{"type":413,"tag":437,"props":16367,"children":16371},{"className":16368,"code":16369,"language":16370,"meta":401,"style":401},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: Deploy Blog to Netlify\n\non:\n  push:\n    branches: \n      - main\n  schedule:\n  - cron: \"0 5 * * *\"\n\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n    - uses: actions/checkout@v2\n      with:\n        ref: main\n        submodules: recursive\n    - uses: actions/setup-dotnet@v1\n      with:\n        dotnet-version: '5.0.x'\n    - run: dotnet run -c Release -- deploy\n      env:\n        NetlifySiteId: ${{ secrets.NetlifySiteId }}\n        NetlifyAccessToken: ${{ secrets.NetlifyAccessToken }}\n","yml",[16372],{"type":413,"tag":444,"props":16373,"children":16374},{"__ignoreMap":401},[16375,16391,16398,16409,16421,16437,16448,16460,16489,16496,16507,16519,16535,16546,16567,16579,16595,16612,16632,16643,16668,16689,16701,16718],{"type":413,"tag":448,"props":16376,"children":16377},{"class":450,"line":451},[16378,16382,16386],{"type":413,"tag":448,"props":16379,"children":16380},{"style":455},[16381],{"type":418,"value":458},{"type":413,"tag":448,"props":16383,"children":16384},{"style":461},[16385],{"type":418,"value":464},{"type":413,"tag":448,"props":16387,"children":16388},{"style":467},[16389],{"type":418,"value":16390}," Deploy Blog to Netlify\n",{"type":413,"tag":448,"props":16392,"children":16393},{"class":450,"line":473},[16394],{"type":413,"tag":448,"props":16395,"children":16396},{"emptyLinePlaceholder":505},[16397],{"type":418,"value":508},{"type":413,"tag":448,"props":16399,"children":16400},{"class":450,"line":488},[16401,16405],{"type":413,"tag":448,"props":16402,"children":16403},{"style":477},[16404],{"type":418,"value":480},{"type":413,"tag":448,"props":16406,"children":16407},{"style":461},[16408],{"type":418,"value":485},{"type":413,"tag":448,"props":16410,"children":16411},{"class":450,"line":501},[16412,16417],{"type":413,"tag":448,"props":16413,"children":16414},{"style":455},[16415],{"type":418,"value":16416},"  push",{"type":413,"tag":448,"props":16418,"children":16419},{"style":461},[16420],{"type":418,"value":485},{"type":413,"tag":448,"props":16422,"children":16423},{"class":450,"line":511},[16424,16429,16433],{"type":413,"tag":448,"props":16425,"children":16426},{"style":455},[16427],{"type":418,"value":16428},"    branches",{"type":413,"tag":448,"props":16430,"children":16431},{"style":461},[16432],{"type":418,"value":464},{"type":413,"tag":448,"props":16434,"children":16435},{"style":1029},[16436],{"type":418,"value":2605},{"type":413,"tag":448,"props":16438,"children":16439},{"class":450,"line":524},[16440,16444],{"type":413,"tag":448,"props":16441,"children":16442},{"style":461},[16443],{"type":418,"value":623},{"type":413,"tag":448,"props":16445,"children":16446},{"style":467},[16447],{"type":418,"value":6725},{"type":413,"tag":448,"props":16449,"children":16450},{"class":450,"line":542},[16451,16456],{"type":413,"tag":448,"props":16452,"children":16453},{"style":455},[16454],{"type":418,"value":16455},"  schedule",{"type":413,"tag":448,"props":16457,"children":16458},{"style":461},[16459],{"type":418,"value":485},{"type":413,"tag":448,"props":16461,"children":16462},{"class":450,"line":560},[16463,16467,16472,16476,16480,16485],{"type":413,"tag":448,"props":16464,"children":16465},{"style":461},[16466],{"type":418,"value":6720},{"type":413,"tag":448,"props":16468,"children":16469},{"style":455},[16470],{"type":418,"value":16471}," cron",{"type":413,"tag":448,"props":16473,"children":16474},{"style":461},[16475],{"type":418,"value":464},{"type":413,"tag":448,"props":16477,"children":16478},{"style":461},[16479],{"type":418,"value":995},{"type":413,"tag":448,"props":16481,"children":16482},{"style":467},[16483],{"type":418,"value":16484},"0 5 * * *",{"type":413,"tag":448,"props":16486,"children":16487},{"style":461},[16488],{"type":418,"value":1005},{"type":413,"tag":448,"props":16490,"children":16491},{"class":450,"line":573},[16492],{"type":413,"tag":448,"props":16493,"children":16494},{"emptyLinePlaceholder":505},[16495],{"type":418,"value":508},{"type":413,"tag":448,"props":16497,"children":16498},{"class":450,"line":586},[16499,16503],{"type":413,"tag":448,"props":16500,"children":16501},{"style":455},[16502],{"type":418,"value":566},{"type":413,"tag":448,"props":16504,"children":16505},{"style":461},[16506],{"type":418,"value":485},{"type":413,"tag":448,"props":16508,"children":16509},{"class":450,"line":604},[16510,16515],{"type":413,"tag":448,"props":16511,"children":16512},{"style":455},[16513],{"type":418,"value":16514},"  build",{"type":413,"tag":448,"props":16516,"children":16517},{"style":461},[16518],{"type":418,"value":485},{"type":413,"tag":448,"props":16520,"children":16521},{"class":450,"line":617},[16522,16526,16530],{"type":413,"tag":448,"props":16523,"children":16524},{"style":455},[16525],{"type":418,"value":592},{"type":413,"tag":448,"props":16527,"children":16528},{"style":461},[16529],{"type":418,"value":464},{"type":413,"tag":448,"props":16531,"children":16532},{"style":467},[16533],{"type":418,"value":16534}," windows-latest\n",{"type":413,"tag":448,"props":16536,"children":16537},{"class":450,"line":650},[16538,16542],{"type":413,"tag":448,"props":16539,"children":16540},{"style":455},[16541],{"type":418,"value":610},{"type":413,"tag":448,"props":16543,"children":16544},{"style":461},[16545],{"type":418,"value":485},{"type":413,"tag":448,"props":16547,"children":16548},{"class":450,"line":668},[16549,16554,16558,16562],{"type":413,"tag":448,"props":16550,"children":16551},{"style":461},[16552],{"type":418,"value":16553},"    -",{"type":413,"tag":448,"props":16555,"children":16556},{"style":455},[16557],{"type":418,"value":11431},{"type":413,"tag":448,"props":16559,"children":16560},{"style":461},[16561],{"type":418,"value":464},{"type":413,"tag":448,"props":16563,"children":16564},{"style":467},[16565],{"type":418,"value":16566}," actions/checkout@v2\n",{"type":413,"tag":448,"props":16568,"children":16569},{"class":450,"line":681},[16570,16575],{"type":413,"tag":448,"props":16571,"children":16572},{"style":455},[16573],{"type":418,"value":16574},"      with",{"type":413,"tag":448,"props":16576,"children":16577},{"style":461},[16578],{"type":418,"value":485},{"type":413,"tag":448,"props":16580,"children":16581},{"class":450,"line":699},[16582,16587,16591],{"type":413,"tag":448,"props":16583,"children":16584},{"style":455},[16585],{"type":418,"value":16586},"        ref",{"type":413,"tag":448,"props":16588,"children":16589},{"style":461},[16590],{"type":418,"value":464},{"type":413,"tag":448,"props":16592,"children":16593},{"style":467},[16594],{"type":418,"value":6725},{"type":413,"tag":448,"props":16596,"children":16597},{"class":450,"line":717},[16598,16603,16607],{"type":413,"tag":448,"props":16599,"children":16600},{"style":455},[16601],{"type":418,"value":16602},"        submodules",{"type":413,"tag":448,"props":16604,"children":16605},{"style":461},[16606],{"type":418,"value":464},{"type":413,"tag":448,"props":16608,"children":16609},{"style":467},[16610],{"type":418,"value":16611}," recursive\n",{"type":413,"tag":448,"props":16613,"children":16614},{"class":450,"line":735},[16615,16619,16623,16627],{"type":413,"tag":448,"props":16616,"children":16617},{"style":461},[16618],{"type":418,"value":16553},{"type":413,"tag":448,"props":16620,"children":16621},{"style":455},[16622],{"type":418,"value":11431},{"type":413,"tag":448,"props":16624,"children":16625},{"style":461},[16626],{"type":418,"value":464},{"type":413,"tag":448,"props":16628,"children":16629},{"style":467},[16630],{"type":418,"value":16631}," actions/setup-dotnet@v1\n",{"type":413,"tag":448,"props":16633,"children":16634},{"class":450,"line":743},[16635,16639],{"type":413,"tag":448,"props":16636,"children":16637},{"style":455},[16638],{"type":418,"value":16574},{"type":413,"tag":448,"props":16640,"children":16641},{"style":461},[16642],{"type":418,"value":485},{"type":413,"tag":448,"props":16644,"children":16645},{"class":450,"line":772},[16646,16651,16655,16659,16664],{"type":413,"tag":448,"props":16647,"children":16648},{"style":455},[16649],{"type":418,"value":16650},"        dotnet-version",{"type":413,"tag":448,"props":16652,"children":16653},{"style":461},[16654],{"type":418,"value":464},{"type":413,"tag":448,"props":16656,"children":16657},{"style":461},[16658],{"type":418,"value":637},{"type":413,"tag":448,"props":16660,"children":16661},{"style":467},[16662],{"type":418,"value":16663},"5.0.x",{"type":413,"tag":448,"props":16665,"children":16666},{"style":461},[16667],{"type":418,"value":647},{"type":413,"tag":448,"props":16669,"children":16670},{"class":450,"line":791},[16671,16675,16680,16684],{"type":413,"tag":448,"props":16672,"children":16673},{"style":461},[16674],{"type":418,"value":16553},{"type":413,"tag":448,"props":16676,"children":16677},{"style":455},[16678],{"type":418,"value":16679}," run",{"type":413,"tag":448,"props":16681,"children":16682},{"style":461},[16683],{"type":418,"value":464},{"type":413,"tag":448,"props":16685,"children":16686},{"style":467},[16687],{"type":418,"value":16688}," dotnet run -c Release -- deploy\n",{"type":413,"tag":448,"props":16690,"children":16691},{"class":450,"line":800},[16692,16697],{"type":413,"tag":448,"props":16693,"children":16694},{"style":455},[16695],{"type":418,"value":16696},"      env",{"type":413,"tag":448,"props":16698,"children":16699},{"style":461},[16700],{"type":418,"value":485},{"type":413,"tag":448,"props":16702,"children":16703},{"class":450,"line":2909},[16704,16709,16713],{"type":413,"tag":448,"props":16705,"children":16706},{"style":455},[16707],{"type":418,"value":16708},"        NetlifySiteId",{"type":413,"tag":448,"props":16710,"children":16711},{"style":461},[16712],{"type":418,"value":464},{"type":413,"tag":448,"props":16714,"children":16715},{"style":467},[16716],{"type":418,"value":16717}," ${{ secrets.NetlifySiteId }}\n",{"type":413,"tag":448,"props":16719,"children":16720},{"class":450,"line":3021},[16721,16726,16730],{"type":413,"tag":448,"props":16722,"children":16723},{"style":455},[16724],{"type":418,"value":16725},"        NetlifyAccessToken",{"type":413,"tag":448,"props":16727,"children":16728},{"style":461},[16729],{"type":418,"value":464},{"type":413,"tag":448,"props":16731,"children":16732},{"style":467},[16733],{"type":418,"value":16734}," ${{ secrets.NetlifyAccessToken }}\n",{"type":413,"tag":414,"props":16736,"children":16737},{},[16738],{"type":418,"value":16739},"This pipeline runs every day and each time something is merged on my main branch. This way my website is redeployed when I publish a new article (which generally corresponds to a commit being made on the main branch through the merge of the branch where I was writing the article). This also allows me to finalize an article but publish it at a future date without having to take care of it.",{"type":413,"tag":866,"props":16741,"children":16743},{"id":16742},"hosting-my-website",[16744],{"type":418,"value":16745},"Hosting my website",{"type":413,"tag":414,"props":16747,"children":16748},{},[16749],{"type":418,"value":16750},"This is the only part where I did not really go all-in on GitHub as I did not use GitHub Pages to host my blog, I kept Netlify. I am happy with it, it does the job, costs me nothing, and allows me to have previews of my blog if I want to so there was no reason to change.",{"type":413,"tag":414,"props":16752,"children":16753},{},[16754],{"type":413,"tag":832,"props":16755,"children":16759},{"alt":16756,"className":16757,"src":16758},"Netlify dashboard the blog.",[836,837],"/posts/images/migrating_blog_4.png",[],{"type":413,"tag":866,"props":16761,"children":16763},{"id":16762},"providing-a-comments-system",[16764],{"type":418,"value":16765},"Providing a comments system",{"type":413,"tag":414,"props":16767,"children":16768},{},[16769,16771,16776],{"type":418,"value":16770},"I was previously using the well-known comments system ",{"type":413,"tag":813,"props":16772,"children":16774},{"href":15981,"rel":16773},[817],[16775],{"type":418,"value":15985},{"type":418,"value":16777}," to let readers of my blog comment on the articles. To be honest, it works well, has a lot of features (moderation, monitoring...), and is used on many blogs. However, I have always found it a bit complex for my needs and was annoyed to \"force\" my readers to create a Disqus account to write comments. So when I read articles of people complaining about Disqus ads, tracking and performance issues I knew it was time to find an alternative.",{"type":413,"tag":414,"props":16779,"children":16780},{},[16781,16783,16790,16792,16798,16799,16804],{"type":418,"value":16782},"And there are many alternatives to Disqus! But one I found very interesting was ",{"type":413,"tag":813,"props":16784,"children":16787},{"href":16785,"rel":16786},"https://utteranc.es/",[817],[16788],{"type":418,"value":16789},"utterances",{"type":418,"value":16791},", a GitHub application that relies on GitHub issues to store blog comments. As the creator of this library explains ",{"type":413,"tag":813,"props":16793,"children":16796},{"href":16794,"rel":16795},"https://danyow.net/using-github-issues-for-blog-comments/",[817],[16797],{"type":418,"value":1386},{"type":418,"value":5053},{"type":413,"tag":444,"props":16800,"children":16802},{"className":16801},[],[16803],{"type":418,"value":16789},{"type":418,"value":16805}," served as a POC for the GitHub-based feedback system in Microsoft Docs. I thought using GitHub issues for the comments of my blog was awesome because:",{"type":413,"tag":3766,"props":16807,"children":16808},{},[16809,16814],{"type":413,"tag":2159,"props":16810,"children":16811},{},[16812],{"type":418,"value":16813},"my readers will not have to create an account to write comments, my readers are developers so they probably already have a GitHub account",{"type":413,"tag":2159,"props":16815,"children":16816},{},[16817],{"type":418,"value":16818},"with comments stored as GitHub issues on my GitHub repository, I have everything at the same place (code, pipelines, and comments)",{"type":413,"tag":414,"props":16820,"children":16821},{},[16822,16824,16829,16831,16838,16840,16845,16847,16854,16856,16861,16863,16868],{"type":418,"value":16823},"But you know what? I finally did not choose ",{"type":413,"tag":444,"props":16825,"children":16827},{"className":16826},[],[16828],{"type":418,"value":16789},{"type":418,"value":16830}," as the comments system for my blog 😀. Instead, I chose to use ",{"type":413,"tag":813,"props":16832,"children":16835},{"href":16833,"rel":16834},"https://giscus.app/",[817],[16836],{"type":418,"value":16837},"giscus",{"type":418,"value":16839}," which is similar to ",{"type":413,"tag":444,"props":16841,"children":16843},{"className":16842},[],[16844],{"type":418,"value":16789},{"type":418,"value":16846}," (in fact it is heavily based on it) but stores comments in ",{"type":413,"tag":813,"props":16848,"children":16851},{"href":16849,"rel":16850},"https://docs.github.com/en/discussions",[817],[16852],{"type":418,"value":16853},"GitHub Discussions",{"type":418,"value":16855},". GitHub Discussions did not exist when ",{"type":413,"tag":444,"props":16857,"children":16859},{"className":16858},[],[16860],{"type":418,"value":16789},{"type":418,"value":16862}," was created but I think discussions are a much more appropriate place than GitHub issues to store comments, that's why I chose it. Apart from that, advantages are the same as ",{"type":413,"tag":444,"props":16864,"children":16866},{"className":16865},[],[16867],{"type":418,"value":16789},{"type":418,"value":898},{"type":413,"tag":414,"props":16870,"children":16871},{},[16872],{"type":413,"tag":832,"props":16873,"children":16877},{"alt":16874,"className":16875,"src":16876},"Comment on the blog using discuss.",[836,837],"/posts/images/migrating_blog_5.png",[],{"type":413,"tag":414,"props":16879,"children":16880},{},[16881,16883,16888],{"type":418,"value":16882},"If you don't have a comments system on your blog yet or that your current one does not satisfy you, you should check ",{"type":413,"tag":813,"props":16884,"children":16886},{"href":16833,"rel":16885},[817],[16887],{"type":418,"value":16837},{"type":418,"value":16889},", I am very happy with it.",{"type":413,"tag":841,"props":16891,"children":16892},{"icon":843},[16893],{"type":413,"tag":414,"props":16894,"children":16895},{},[16896,16898,16903,16905,16912,16914,16921],{"type":418,"value":16897},"If you are currently using Disqus and want to migrate to ",{"type":413,"tag":444,"props":16899,"children":16901},{"className":16900},[],[16902],{"type":418,"value":16837},{"type":418,"value":16904}," (while preserving your existing comments), the easiest way I found was to export the Disqus comments in a file, use this ",{"type":413,"tag":813,"props":16906,"children":16909},{"href":16907,"rel":16908},"https://github.com/JuergenGutsch/disqus-to-github-issues",[817],[16910],{"type":418,"value":16911},"tool",{"type":418,"value":16913}," on GitHub to convert them into issues, and manually convert existing issues to discussions on each issue page. You can read this ",{"type":413,"tag":813,"props":16915,"children":16918},{"href":16916,"rel":16917},"https://ljvmiranda921.github.io/notebook/2021/03/26/migrating-from-disqus-to-utterances/",[817],[16919],{"type":418,"value":16920},"blog post",{"type":418,"value":16922}," that partially explains how to do that.",{"type":413,"tag":866,"props":16924,"children":16926},{"id":16925},"managing-my-blog-as-a-project",[16927],{"type":418,"value":16928},"Managing my blog as a project",{"type":413,"tag":414,"props":16930,"children":16931},{},[16932,16934,16941],{"type":418,"value":16933},"My blog is not very hard to manage but there are always things to do or think about: improvements to do, articles to write, ideas to find. Instead of writing that down on my ToDo app or my OneNote as I used to do, I decided to use the ",{"type":413,"tag":813,"props":16935,"children":16938},{"href":16936,"rel":16937},"https://github.com/features/issues/",[817],[16939],{"type":418,"value":16940},"GitHub Issues beta",{"type":418,"value":16942}," that allows you to create a \"project\" with a backlog, boards, and issues that can be categorized with custom fields.",{"type":413,"tag":414,"props":16944,"children":16945},{},[16946],{"type":413,"tag":832,"props":16947,"children":16951},{"alt":16948,"className":16949,"src":16950},"Github project for the blog.",[836,837],"/posts/images/migrating_blog_6.png",[],{"type":413,"tag":420,"props":16953,"children":16955},{"id":16954},"summary",[16956],{"type":418,"value":16957},"Summary",{"type":413,"tag":414,"props":16959,"children":16960},{},[16961],{"type":418,"value":16962},"In this article, I talked to you about what changed on my blog, and what my new stack is:",{"type":413,"tag":3766,"props":16964,"children":16965},{},[16966,16976,16987,16997,17008,17024],{"type":413,"tag":2159,"props":16967,"children":16968},{},[16969,16974],{"type":413,"tag":813,"props":16970,"children":16972},{"href":16220,"rel":16971},[817],[16973],{"type":418,"value":331},{"type":418,"value":16975}," a .NET static website generator to generate the website",{"type":413,"tag":2159,"props":16977,"children":16978},{},[16979,16985],{"type":413,"tag":813,"props":16980,"children":16983},{"href":16981,"rel":16982},"https://github.com/",[817],[16984],{"type":418,"value":233},{"type":418,"value":16986}," to store the source code on a public (open source) git repository",{"type":413,"tag":2159,"props":16988,"children":16989},{},[16990,16996],{"type":413,"tag":813,"props":16991,"children":16994},{"href":16992,"rel":16993},"https://github.com/features/actions",[817],[16995],{"type":418,"value":307},{"type":418,"value":15963},{"type":413,"tag":2159,"props":16998,"children":16999},{},[17000,17006],{"type":413,"tag":813,"props":17001,"children":17003},{"href":16936,"rel":17002},[817],[17004],{"type":418,"value":17005},"GitHub Issues (beta)",{"type":418,"value":17007}," to manage my ideas for the blog",{"type":413,"tag":2159,"props":17009,"children":17010},{},[17011,17016,17017,17022],{"type":413,"tag":813,"props":17012,"children":17014},{"href":16849,"rel":17013},[817],[17015],{"type":418,"value":16853},{"type":418,"value":16347},{"type":413,"tag":813,"props":17018,"children":17020},{"href":16833,"rel":17019},[817],[17021],{"type":418,"value":16837},{"type":418,"value":17023}," to allow visitors to comment my articles",{"type":413,"tag":2159,"props":17025,"children":17026},{},[17027,17032],{"type":413,"tag":813,"props":17028,"children":17030},{"href":15969,"rel":17029},[817],[17031],{"type":418,"value":15973},{"type":418,"value":15975},{"type":413,"tag":414,"props":17034,"children":17035},{},[17036],{"type":418,"value":17037},"I like this new stack where most things are centralized in one place: GitHub. I own the content of this blog, but I love that code to generate this blog is open source. There is still plenty of room for improvement on my blog, but I am confident Statiq will help me to continue customizing my blog easily. I hope you liked this article, do not hesitate to comment (you now know how comments work behind the scenes 😀).",{"type":413,"tag":841,"props":17039,"children":17040},{"icon":843},[17041],{"type":413,"tag":414,"props":17042,"children":17043},{},[17044,17046,17053],{"type":418,"value":17045},"If you are reading this article from hashnode or dev.to and not directly on my ",{"type":413,"tag":813,"props":17047,"children":17050},{"href":17048,"rel":17049},"https://techwatching.dev",[817],[17051],{"type":418,"value":17052},"blog",{"type":418,"value":17054},", these changes do not apply to you. But do not worry, I will continue to cross-post my articles on these platforms too which have great communities.",{"type":413,"tag":3710,"props":17056,"children":17057},{},[17058],{"type":418,"value":3714},{"title":401,"searchDepth":473,"depth":473,"links":17060},[17061,17062,17067,17068,17075],{"id":15917,"depth":473,"text":15920},{"id":15995,"depth":473,"text":15998,"children":17063},[17064,17065,17066],{"id":16001,"depth":488,"text":16004},{"id":16123,"depth":488,"text":16126},{"id":16148,"depth":488,"text":16151},{"id":16209,"depth":473,"text":16212},{"id":16248,"depth":473,"text":16251,"children":17069},[17070,17071,17072,17073,17074],{"id":16259,"depth":488,"text":16262},{"id":16357,"depth":488,"text":16360},{"id":16742,"depth":488,"text":16745},{"id":16762,"depth":488,"text":16765},{"id":16925,"depth":488,"text":16928},{"id":16954,"depth":473,"text":16957},"content:1.posts:27.migrating-blog.md","1.posts/27.migrating-blog.md",{"_path":19,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":18,"description":17079,"lead":17080,"date":17081,"image":17082,"tags":17084,"badge":17085,"body":17086,"_type":3726,"_id":17345,"_source":3728,"_file":17346,"_extension":3730},"The other day when I was looking for a way to automate my development environment setup, I came across Gitpod. Not really what I was looking for but I discovered an awesome tool for working on open source projects.","An IDE in the browser","2019-08-12T00:00:00.000Z",{"src":17083},"/images/github-usbkey.jpg",[233,206,208],{"label":15583},{"type":410,"children":17087,"toc":17343},[17088,17102,17107,17136,17141,17152,17175,17204,17219,17224,17239,17244,17249,17258,17276,17293,17298,17338],{"type":413,"tag":414,"props":17089,"children":17090},{},[17091,17093,17100],{"type":418,"value":17092},"The other day when I was looking for a way to automate my development environment setup, I came across ",{"type":413,"tag":813,"props":17094,"children":17097},{"href":17095,"rel":17096},"https://www.gitpod.io/",[817],[17098],{"type":418,"value":17099},"Gitpod",{"type":418,"value":17101},". Not really what I was looking for but I discovered an awesome tool for working on open source projects.",{"type":413,"tag":414,"props":17103,"children":17104},{},[17105],{"type":418,"value":17106},"Gitpod is an online service that aims at providing ready-to-code development environments in the browser for GitHub projects.",{"type":413,"tag":414,"props":17108,"children":17109},{},[17110,17112,17119,17121,17127,17129,17135],{"type":418,"value":17111},"Let's see that with one project I was contributing to a few months ago: the ",{"type":413,"tag":813,"props":17113,"children":17116},{"href":17114,"rel":17115},"https://github.com/voxxrin/voxxrin-companion-ui",[817],[17117],{"type":418,"value":17118},"Voxxrin Companion mobile app",{"type":418,"value":17120},".\nFirst, let's go to the project GitHub's page, and prefix the URL of the page with ",{"type":413,"tag":444,"props":17122,"children":17124},{"className":17123},[],[17125],{"type":418,"value":17126},"gitpod.io/#",{"type":418,"value":17128}," which gives us the following URL: ",{"type":413,"tag":813,"props":17130,"children":17133},{"href":17131,"rel":17132},"http://gitpod.io/#https://github.com/voxxrin/voxxrin-companion-ui",[817],[17134],{"type":418,"value":17131},{"type":418,"value":898},{"type":413,"tag":414,"props":17137,"children":17138},{},[17139],{"type":418,"value":17140},"As I am already logged in to the  Gitpod account I created (free for open source developers with a quota of 100 hours/month) Gitpod will start creating a development environment for me. That means pulling a Docker image with everything I need to code (for specific needs, you can also specify a custom docker image to use) and initializing a workspace for me with the code of the project.",{"type":413,"tag":414,"props":17142,"children":17143},{},[17144,17146],{"type":418,"value":17145},"Less than 30s and here we are :\n",{"type":413,"tag":832,"props":17147,"children":17151},{"alt":17148,"className":17149,"src":17150},"Voxxr.in project opened in gitpod in browser.",[836,837],"/posts/images/gitpod_voxxrin_1.png",[],{"type":413,"tag":414,"props":17153,"children":17154},{},[17155,17157,17164,17166,17173],{"type":418,"value":17156},"I have now a complete development environment running in the cloud with the code of my project already cloned. If the editor looks familiar to you it's because ",{"type":413,"tag":813,"props":17158,"children":17161},{"href":17159,"rel":17160},"https://www.theia-ide.org/",[817],[17162],{"type":418,"value":17163},"Theia",{"type":418,"value":17165}," (the IDE's name) is very similar to ",{"type":413,"tag":813,"props":17167,"children":17170},{"href":17168,"rel":17169},"http://typefox.io/theia-vs-code-in-the-cloud",[817],[17171],{"type":418,"value":17172},"VS Code but in the cloud",{"type":418,"value":17174}," (it reuses many parts from VS Code). This is great because it means I can use an IDE I am already familiar with, and even use vs code extensions (provided you have the .vsix files to install them).",{"type":413,"tag":414,"props":17176,"children":17177},{},[17178,17180,17186,17188,17194,17196,17202],{"type":418,"value":17179},"So let's run my project which is an ionic application. Node is already installed so I just have to type ",{"type":413,"tag":444,"props":17181,"children":17183},{"className":17182},[],[17184],{"type":418,"value":17185},"npm install",{"type":418,"value":17187}," and then ",{"type":413,"tag":444,"props":17189,"children":17191},{"className":17190},[],[17192],{"type":418,"value":17193},"npm run-script serve",{"type":418,"value":17195}," in the terminal opened in the editor exactly as if I was working on my local VS Code. My application is configured to be launched on port ",{"type":413,"tag":444,"props":17197,"children":17199},{"className":17198},[],[17200],{"type":418,"value":17201},"8100",{"type":418,"value":17203}," so Gitpod will suggest I expose this port for me to be able to view my application in my browser.",{"type":413,"tag":414,"props":17205,"children":17206},{},[17207,17213],{"type":413,"tag":832,"props":17208,"children":17212},{"alt":17209,"className":17210,"src":17211},"GitPod suggestion of opening port to run the application.",[836,837],"/posts/images/gitpod_voxxrin_2.png",[],{"type":413,"tag":832,"props":17214,"children":17218},{"alt":17215,"className":17216,"src":17217},"GitPod suggestion of opening live preview of the application.",[836,837],"/posts/images/gitpod_voxxrin_3.png",[],{"type":413,"tag":414,"props":17220,"children":17221},{},[17222],{"type":418,"value":17223},"I can now open in my computer browser the application running in my Gitpod workspace. I can also preview it directly in Gitpod.",{"type":413,"tag":414,"props":17225,"children":17226},{},[17227,17233],{"type":413,"tag":832,"props":17228,"children":17232},{"alt":17229,"className":17230,"src":17231},"Voxxr.in application served in a browser tab.",[836,837],"/posts/images/gitpod_voxxrin_5.png",[],{"type":413,"tag":832,"props":17234,"children":17238},{"alt":17235,"className":17236,"src":17237},"Voxxr.in application served in GitPod tab.",[836,837],"/posts/images/gitpod_voxxrin_4.png",[],{"type":413,"tag":414,"props":17240,"children":17241},{},[17242],{"type":418,"value":17243},"If I have some modifications to do I can push them directly from here to my GitHub repository as my Gitpod account is associated with my GitHub account.",{"type":413,"tag":414,"props":17245,"children":17246},{},[17247],{"type":418,"value":17248},"When I have finished, I can just stop the workspace and that's it.",{"type":413,"tag":414,"props":17250,"children":17251},{},[17252],{"type":413,"tag":832,"props":17253,"children":17257},{"alt":17254,"className":17255,"src":17256},"GitPod menu to stop the workspace.",[836,837],"/posts/images/gitpod_voxxrin_7.png",[],{"type":413,"tag":414,"props":17259,"children":17260},{},[17261,17263,17274],{"type":418,"value":17262},"I created the workspace for my project as-is but lots of things can be configured by having a ",{"type":413,"tag":813,"props":17264,"children":17267},{"href":17265,"rel":17266},"https://www.gitpod.io/docs/41_config_gitpod_file/",[817],[17268],{"type":413,"tag":444,"props":17269,"children":17271},{"className":17270},[],[17272],{"type":418,"value":17273},"gitpod.yml",{"type":418,"value":17275}," file in the repository of your project",{"type":413,"tag":414,"props":17277,"children":17278},{},[17279,17281,17291],{"type":418,"value":17280},"With Gitpod you just need a browser and an internet connection to be able to work on any of your GitHub projects from anywhere. When you work on multiple open source projects the nice thing is that it allows you to easily switch from one to another. I wonder if the Browser-Based Web Companion ",{"type":413,"tag":813,"props":17282,"children":17285},{"href":17283,"rel":17284},"https://devblogs.microsoft.com/visualstudio/intelligent-productivity-and-collaboration-from-anywhere/",[817],[17286],{"type":413,"tag":3838,"props":17287,"children":17288},{},[17289],{"type":418,"value":17290},"Visual Studio Online",{"type":418,"value":17292}," announced by Microsoft at Build 2019 will offer the same capabilities and how it will differ from Gitpod.",{"type":413,"tag":414,"props":17294,"children":17295},{},[17296],{"type":418,"value":17297},"This was just a quick introduction to Gitpod but there are far more things you can do with it:",{"type":413,"tag":3766,"props":17299,"children":17300},{},[17301,17313,17318,17323,17328,17333],{"type":413,"tag":2159,"props":17302,"children":17303},{},[17304,17306,17311],{"type":418,"value":17305},"running scripts on the start-up of your environment  (an ",{"type":413,"tag":444,"props":17307,"children":17309},{"className":17308},[],[17310],{"type":418,"value":17185},{"type":418,"value":17312}," for instance)",{"type":413,"tag":2159,"props":17314,"children":17315},{},[17316],{"type":418,"value":17317},"continuously auto-building your repository",{"type":413,"tag":2159,"props":17319,"children":17320},{},[17321],{"type":418,"value":17322},"install a database",{"type":413,"tag":2159,"props":17324,"children":17325},{},[17326],{"type":418,"value":17327},"use it for private projects (not free, there are multiple pricings available)",{"type":413,"tag":2159,"props":17329,"children":17330},{},[17331],{"type":418,"value":17332},"share an environment with other users",{"type":413,"tag":2159,"props":17334,"children":17335},{},[17336],{"type":418,"value":17337},"...",{"type":413,"tag":414,"props":17339,"children":17340},{},[17341],{"type":418,"value":17342},"But the best is you try and judge by yourself.",{"title":401,"searchDepth":473,"depth":473,"links":17344},[],"content:1.posts:4.gitpod.md","1.posts/4.gitpod.md",1716749600619]