[{"data":1,"prerenderedAt":3792},["Reactive",2],{"navigation":3,"aAII9Cz3yR":204,"tags-git":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,1643,1866,2301,2571,2988,3204],{"_path":121,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":120,"description":402,"lead":402,"date":403,"image":404,"badge":406,"tags":408,"body":409,"_type":1638,"_id":1639,"_source":1640,"_file":1641,"_extension":1642},"posts",false,"","The \"this\" in TypeScript, a must-have tool for Durable Functions, and a new git alias.","2022-05-23T00:00:00.000Z",{"src":405},"/images/surface_1.jpg",{"label":407},"Tips",[272,358,241,257,206],{"type":410,"children":411,"toc":1632},"root",[412,428,450,455,711,747,773,884,896,918,1031,1064,1470,1476,1490,1499,1511,1521,1527,1541,1586,1621,1626],{"type":413,"tag":414,"props":415,"children":417},"element","h2",{"id":416},"reminder-for-my-future-self-dont-forget-about-this-in-ts",[418,421],{"type":419,"value":420},"text","Reminder for my future self: don't forget about \"this\" in ",{"type":413,"tag":422,"props":423,"children":425},"code",{"className":424},[],[426],{"type":419,"value":427},"ts",{"type":413,"tag":429,"props":430,"children":431},"p",{},[432,434,440,442,448],{"type":419,"value":433},"Once again, I found myself forgetting that ",{"type":413,"tag":422,"props":435,"children":437},{"className":436},[],[438],{"type":419,"value":439},"this",{"type":419,"value":441}," can lose context in JavaScript/TypeScript which results in exceptions because ",{"type":413,"tag":422,"props":443,"children":445},{"className":444},[],[446],{"type":419,"value":447},"this ",{"type":419,"value":449}," is undefined. This is probably obvious for most developers but this is not a case I come across often so it's better to write it down so that I have something to refer to next time.",{"type":413,"tag":429,"props":451,"children":452},{},[453],{"type":419,"value":454},"Let's take an example:",{"type":413,"tag":456,"props":457,"children":460},"pre",{"className":458,"code":459,"language":427,"meta":401,"style":401},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class AudioBook {\n    private isStarted = false;\n\n    constructor(public title: string) {\n    }\n    \n    play() {\n        this.isStarted = true;\n    }\n\n    stop() {\n        this.isStarted = false;\n    }\n}\n",[461],{"type":413,"tag":422,"props":462,"children":463},{"__ignoreMap":401},[464,488,519,529,573,582,592,610,637,645,653,670,694,702],{"type":413,"tag":465,"props":466,"children":469},"span",{"class":467,"line":468},"line",1,[470,476,482],{"type":413,"tag":465,"props":471,"children":473},{"style":472},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[474],{"type":419,"value":475},"class",{"type":413,"tag":465,"props":477,"children":479},{"style":478},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[480],{"type":419,"value":481}," AudioBook",{"type":413,"tag":465,"props":483,"children":485},{"style":484},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[486],{"type":419,"value":487}," {\n",{"type":413,"tag":465,"props":489,"children":491},{"class":467,"line":490},2,[492,497,503,508,514],{"type":413,"tag":465,"props":493,"children":494},{"style":472},[495],{"type":419,"value":496},"    private",{"type":413,"tag":465,"props":498,"children":500},{"style":499},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[501],{"type":419,"value":502}," isStarted",{"type":413,"tag":465,"props":504,"children":505},{"style":484},[506],{"type":419,"value":507}," =",{"type":413,"tag":465,"props":509,"children":511},{"style":510},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[512],{"type":419,"value":513}," false",{"type":413,"tag":465,"props":515,"children":516},{"style":484},[517],{"type":419,"value":518},";\n",{"type":413,"tag":465,"props":520,"children":522},{"class":467,"line":521},3,[523],{"type":413,"tag":465,"props":524,"children":526},{"emptyLinePlaceholder":525},true,[527],{"type":419,"value":528},"\n",{"type":413,"tag":465,"props":530,"children":532},{"class":467,"line":531},4,[533,538,543,548,554,559,564,569],{"type":413,"tag":465,"props":534,"children":535},{"style":472},[536],{"type":419,"value":537},"    constructor",{"type":413,"tag":465,"props":539,"children":540},{"style":484},[541],{"type":419,"value":542},"(",{"type":413,"tag":465,"props":544,"children":545},{"style":472},[546],{"type":419,"value":547},"public",{"type":413,"tag":465,"props":549,"children":551},{"style":550},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[552],{"type":419,"value":553}," title",{"type":413,"tag":465,"props":555,"children":556},{"style":484},[557],{"type":419,"value":558},":",{"type":413,"tag":465,"props":560,"children":561},{"style":478},[562],{"type":419,"value":563}," string",{"type":413,"tag":465,"props":565,"children":566},{"style":484},[567],{"type":419,"value":568},")",{"type":413,"tag":465,"props":570,"children":571},{"style":484},[572],{"type":419,"value":487},{"type":413,"tag":465,"props":574,"children":576},{"class":467,"line":575},5,[577],{"type":413,"tag":465,"props":578,"children":579},{"style":484},[580],{"type":419,"value":581},"    }\n",{"type":413,"tag":465,"props":583,"children":585},{"class":467,"line":584},6,[586],{"type":413,"tag":465,"props":587,"children":589},{"style":588},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[590],{"type":419,"value":591},"    \n",{"type":413,"tag":465,"props":593,"children":595},{"class":467,"line":594},7,[596,601,606],{"type":413,"tag":465,"props":597,"children":598},{"style":499},[599],{"type":419,"value":600},"    play",{"type":413,"tag":465,"props":602,"children":603},{"style":484},[604],{"type":419,"value":605},"()",{"type":413,"tag":465,"props":607,"children":608},{"style":484},[609],{"type":419,"value":487},{"type":413,"tag":465,"props":611,"children":613},{"class":467,"line":612},8,[614,619,624,628,633],{"type":413,"tag":465,"props":615,"children":616},{"style":484},[617],{"type":419,"value":618},"        this.",{"type":413,"tag":465,"props":620,"children":621},{"style":588},[622],{"type":419,"value":623},"isStarted",{"type":413,"tag":465,"props":625,"children":626},{"style":484},[627],{"type":419,"value":507},{"type":413,"tag":465,"props":629,"children":630},{"style":510},[631],{"type":419,"value":632}," true",{"type":413,"tag":465,"props":634,"children":635},{"style":484},[636],{"type":419,"value":518},{"type":413,"tag":465,"props":638,"children":640},{"class":467,"line":639},9,[641],{"type":413,"tag":465,"props":642,"children":643},{"style":484},[644],{"type":419,"value":581},{"type":413,"tag":465,"props":646,"children":648},{"class":467,"line":647},10,[649],{"type":413,"tag":465,"props":650,"children":651},{"emptyLinePlaceholder":525},[652],{"type":419,"value":528},{"type":413,"tag":465,"props":654,"children":656},{"class":467,"line":655},11,[657,662,666],{"type":413,"tag":465,"props":658,"children":659},{"style":499},[660],{"type":419,"value":661},"    stop",{"type":413,"tag":465,"props":663,"children":664},{"style":484},[665],{"type":419,"value":605},{"type":413,"tag":465,"props":667,"children":668},{"style":484},[669],{"type":419,"value":487},{"type":413,"tag":465,"props":671,"children":673},{"class":467,"line":672},12,[674,678,682,686,690],{"type":413,"tag":465,"props":675,"children":676},{"style":484},[677],{"type":419,"value":618},{"type":413,"tag":465,"props":679,"children":680},{"style":588},[681],{"type":419,"value":623},{"type":413,"tag":465,"props":683,"children":684},{"style":484},[685],{"type":419,"value":507},{"type":413,"tag":465,"props":687,"children":688},{"style":510},[689],{"type":419,"value":513},{"type":413,"tag":465,"props":691,"children":692},{"style":484},[693],{"type":419,"value":518},{"type":413,"tag":465,"props":695,"children":697},{"class":467,"line":696},13,[698],{"type":413,"tag":465,"props":699,"children":700},{"style":484},[701],{"type":419,"value":581},{"type":413,"tag":465,"props":703,"children":705},{"class":467,"line":704},14,[706],{"type":413,"tag":465,"props":707,"children":708},{"style":484},[709],{"type":419,"value":710},"}\n",{"type":413,"tag":429,"props":712,"children":713},{},[714,716,722,724,729,731,737,739,745],{"type":419,"value":715},"This is a class ",{"type":413,"tag":422,"props":717,"children":719},{"className":718},[],[720],{"type":419,"value":721},"AudioBook",{"type":419,"value":723}," that has a private boolean field ",{"type":413,"tag":422,"props":725,"children":727},{"className":726},[],[728],{"type":419,"value":623},{"type":419,"value":730}," that is modified by the two methods ",{"type":413,"tag":422,"props":732,"children":734},{"className":733},[],[735],{"type":419,"value":736},"play",{"type":419,"value":738}," and ",{"type":413,"tag":422,"props":740,"children":742},{"className":741},[],[743],{"type":419,"value":744},"stop",{"type":419,"value":746},".",{"type":413,"tag":429,"props":748,"children":749},{},[750,752,757,759,764,766,771],{"type":419,"value":751},"If I create an instance of ",{"type":413,"tag":422,"props":753,"children":755},{"className":754},[],[756],{"type":419,"value":721},{"type":419,"value":758}," and I want to assign the ",{"type":413,"tag":422,"props":760,"children":762},{"className":761},[],[763],{"type":419,"value":736},{"type":419,"value":765}," function to a variable, an exception will occur when the function is run because ",{"type":413,"tag":422,"props":767,"children":769},{"className":768},[],[770],{"type":419,"value":439},{"type":419,"value":772}," will be undefined.",{"type":413,"tag":456,"props":774,"children":776},{"className":458,"code":775,"language":427,"meta":401,"style":401},"const audioBook = new AudioBook(\"The Unicorn Project\");\nconst listenDevOpsBook = audioBook.play;\nlistenDevOpsBook();\n",[777],{"type":413,"tag":422,"props":778,"children":779},{"__ignoreMap":401},[780,835,868],{"type":413,"tag":465,"props":781,"children":782},{"class":467,"line":468},[783,788,793,798,803,808,812,817,823,827,831],{"type":413,"tag":465,"props":784,"children":785},{"style":472},[786],{"type":419,"value":787},"const",{"type":413,"tag":465,"props":789,"children":790},{"style":588},[791],{"type":419,"value":792}," audioBook ",{"type":413,"tag":465,"props":794,"children":795},{"style":484},[796],{"type":419,"value":797},"=",{"type":413,"tag":465,"props":799,"children":800},{"style":484},[801],{"type":419,"value":802}," new",{"type":413,"tag":465,"props":804,"children":806},{"style":805},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[807],{"type":419,"value":481},{"type":413,"tag":465,"props":809,"children":810},{"style":588},[811],{"type":419,"value":542},{"type":413,"tag":465,"props":813,"children":814},{"style":484},[815],{"type":419,"value":816},"\"",{"type":413,"tag":465,"props":818,"children":820},{"style":819},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[821],{"type":419,"value":822},"The Unicorn Project",{"type":413,"tag":465,"props":824,"children":825},{"style":484},[826],{"type":419,"value":816},{"type":413,"tag":465,"props":828,"children":829},{"style":588},[830],{"type":419,"value":568},{"type":413,"tag":465,"props":832,"children":833},{"style":484},[834],{"type":419,"value":518},{"type":413,"tag":465,"props":836,"children":837},{"class":467,"line":490},[838,842,847,851,856,860,864],{"type":413,"tag":465,"props":839,"children":840},{"style":472},[841],{"type":419,"value":787},{"type":413,"tag":465,"props":843,"children":844},{"style":588},[845],{"type":419,"value":846}," listenDevOpsBook ",{"type":413,"tag":465,"props":848,"children":849},{"style":484},[850],{"type":419,"value":797},{"type":413,"tag":465,"props":852,"children":853},{"style":588},[854],{"type":419,"value":855}," audioBook",{"type":413,"tag":465,"props":857,"children":858},{"style":484},[859],{"type":419,"value":746},{"type":413,"tag":465,"props":861,"children":862},{"style":588},[863],{"type":419,"value":736},{"type":413,"tag":465,"props":865,"children":866},{"style":484},[867],{"type":419,"value":518},{"type":413,"tag":465,"props":869,"children":870},{"class":467,"line":521},[871,876,880],{"type":413,"tag":465,"props":872,"children":873},{"style":805},[874],{"type":419,"value":875},"listenDevOpsBook",{"type":413,"tag":465,"props":877,"children":878},{"style":588},[879],{"type":419,"value":605},{"type":413,"tag":465,"props":881,"children":882},{"style":484},[883],{"type":419,"value":518},{"type":413,"tag":429,"props":885,"children":886},{},[887],{"type":413,"tag":888,"props":889,"children":895},"img",{"alt":890,"className":891,"src":894},"JavaScript Failed error in console output.",[892,893],"rounded-lg","mx-auto","/posts/images/w202022tips_this_1.png",[],{"type":413,"tag":429,"props":897,"children":898},{},[899,901,910,912,917],{"type":419,"value":900},"The solution to avoid that is to use the ",{"type":413,"tag":902,"props":903,"children":907},"a",{"href":904,"rel":905},"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind",[906],"nofollow",[908],{"type":419,"value":909},"bind",{"type":419,"value":911}," function to specify the object to use as ",{"type":413,"tag":422,"props":913,"children":915},{"className":914},[],[916],{"type":419,"value":439},{"type":419,"value":746},{"type":413,"tag":456,"props":919,"children":921},{"className":458,"code":920,"language":427,"meta":401,"style":401},"const audioBook = new AudioBook(\"The Unicorn Project\");\nconst listenDevOpsBook = audioBook.play.bind(audioBook);\nlistenDevOpsBook();\n",[922],{"type":413,"tag":422,"props":923,"children":924},{"__ignoreMap":401},[925,972,1016],{"type":413,"tag":465,"props":926,"children":927},{"class":467,"line":468},[928,932,936,940,944,948,952,956,960,964,968],{"type":413,"tag":465,"props":929,"children":930},{"style":472},[931],{"type":419,"value":787},{"type":413,"tag":465,"props":933,"children":934},{"style":588},[935],{"type":419,"value":792},{"type":413,"tag":465,"props":937,"children":938},{"style":484},[939],{"type":419,"value":797},{"type":413,"tag":465,"props":941,"children":942},{"style":484},[943],{"type":419,"value":802},{"type":413,"tag":465,"props":945,"children":946},{"style":805},[947],{"type":419,"value":481},{"type":413,"tag":465,"props":949,"children":950},{"style":588},[951],{"type":419,"value":542},{"type":413,"tag":465,"props":953,"children":954},{"style":484},[955],{"type":419,"value":816},{"type":413,"tag":465,"props":957,"children":958},{"style":819},[959],{"type":419,"value":822},{"type":413,"tag":465,"props":961,"children":962},{"style":484},[963],{"type":419,"value":816},{"type":413,"tag":465,"props":965,"children":966},{"style":588},[967],{"type":419,"value":568},{"type":413,"tag":465,"props":969,"children":970},{"style":484},[971],{"type":419,"value":518},{"type":413,"tag":465,"props":973,"children":974},{"class":467,"line":490},[975,979,983,987,991,995,999,1003,1007,1012],{"type":413,"tag":465,"props":976,"children":977},{"style":472},[978],{"type":419,"value":787},{"type":413,"tag":465,"props":980,"children":981},{"style":588},[982],{"type":419,"value":846},{"type":413,"tag":465,"props":984,"children":985},{"style":484},[986],{"type":419,"value":797},{"type":413,"tag":465,"props":988,"children":989},{"style":588},[990],{"type":419,"value":855},{"type":413,"tag":465,"props":992,"children":993},{"style":484},[994],{"type":419,"value":746},{"type":413,"tag":465,"props":996,"children":997},{"style":588},[998],{"type":419,"value":736},{"type":413,"tag":465,"props":1000,"children":1001},{"style":484},[1002],{"type":419,"value":746},{"type":413,"tag":465,"props":1004,"children":1005},{"style":805},[1006],{"type":419,"value":909},{"type":413,"tag":465,"props":1008,"children":1009},{"style":588},[1010],{"type":419,"value":1011},"(audioBook)",{"type":413,"tag":465,"props":1013,"children":1014},{"style":484},[1015],{"type":419,"value":518},{"type":413,"tag":465,"props":1017,"children":1018},{"class":467,"line":521},[1019,1023,1027],{"type":413,"tag":465,"props":1020,"children":1021},{"style":805},[1022],{"type":419,"value":875},{"type":413,"tag":465,"props":1024,"children":1025},{"style":588},[1026],{"type":419,"value":605},{"type":413,"tag":465,"props":1028,"children":1029},{"style":484},[1030],{"type":419,"value":518},{"type":413,"tag":429,"props":1032,"children":1033},{},[1034,1036,1041,1043,1048,1050,1055,1057,1062],{"type":419,"value":1035},"To avoid having to use bind everywhere the ",{"type":413,"tag":422,"props":1037,"children":1039},{"className":1038},[],[1040],{"type":419,"value":736},{"type":419,"value":1042}," or the ",{"type":413,"tag":422,"props":1044,"children":1046},{"className":1045},[],[1047],{"type":419,"value":744},{"type":419,"value":1049}," methods are used, we can do the ",{"type":413,"tag":422,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":419,"value":909},{"type":419,"value":1056}," thing directly in the constructor of the ",{"type":413,"tag":422,"props":1058,"children":1060},{"className":1059},[],[1061],{"type":419,"value":721},{"type":419,"value":1063}," class.",{"type":413,"tag":456,"props":1065,"children":1067},{"className":458,"code":1066,"language":427,"meta":401,"style":401},"class AudioBook {\n    private isStarted = false;\n\n    constructor(public title: string) {\n        this.play = this.play.bind(this);\n        this.stop = this.stop.bind(this);\n    }\n    \n    play() {\n        this.isStarted = true;\n    }\n\n    stop() {\n        this.isStarted = false;\n    }\n}\n\nconst audioBook = new AudioBook(\"The Unicorn Project\");\nconst listenDevOpsBook = audioBook.play;\nlistenDevOpsBook();\n",[1068],{"type":413,"tag":422,"props":1069,"children":1070},{"__ignoreMap":401},[1071,1086,1109,1116,1151,1199,1246,1253,1260,1275,1298,1305,1312,1327,1350,1358,1366,1374,1422,1454],{"type":413,"tag":465,"props":1072,"children":1073},{"class":467,"line":468},[1074,1078,1082],{"type":413,"tag":465,"props":1075,"children":1076},{"style":472},[1077],{"type":419,"value":475},{"type":413,"tag":465,"props":1079,"children":1080},{"style":478},[1081],{"type":419,"value":481},{"type":413,"tag":465,"props":1083,"children":1084},{"style":484},[1085],{"type":419,"value":487},{"type":413,"tag":465,"props":1087,"children":1088},{"class":467,"line":490},[1089,1093,1097,1101,1105],{"type":413,"tag":465,"props":1090,"children":1091},{"style":472},[1092],{"type":419,"value":496},{"type":413,"tag":465,"props":1094,"children":1095},{"style":499},[1096],{"type":419,"value":502},{"type":413,"tag":465,"props":1098,"children":1099},{"style":484},[1100],{"type":419,"value":507},{"type":413,"tag":465,"props":1102,"children":1103},{"style":510},[1104],{"type":419,"value":513},{"type":413,"tag":465,"props":1106,"children":1107},{"style":484},[1108],{"type":419,"value":518},{"type":413,"tag":465,"props":1110,"children":1111},{"class":467,"line":521},[1112],{"type":413,"tag":465,"props":1113,"children":1114},{"emptyLinePlaceholder":525},[1115],{"type":419,"value":528},{"type":413,"tag":465,"props":1117,"children":1118},{"class":467,"line":531},[1119,1123,1127,1131,1135,1139,1143,1147],{"type":413,"tag":465,"props":1120,"children":1121},{"style":472},[1122],{"type":419,"value":537},{"type":413,"tag":465,"props":1124,"children":1125},{"style":484},[1126],{"type":419,"value":542},{"type":413,"tag":465,"props":1128,"children":1129},{"style":472},[1130],{"type":419,"value":547},{"type":413,"tag":465,"props":1132,"children":1133},{"style":550},[1134],{"type":419,"value":553},{"type":413,"tag":465,"props":1136,"children":1137},{"style":484},[1138],{"type":419,"value":558},{"type":413,"tag":465,"props":1140,"children":1141},{"style":478},[1142],{"type":419,"value":563},{"type":413,"tag":465,"props":1144,"children":1145},{"style":484},[1146],{"type":419,"value":568},{"type":413,"tag":465,"props":1148,"children":1149},{"style":484},[1150],{"type":419,"value":487},{"type":413,"tag":465,"props":1152,"children":1153},{"class":467,"line":575},[1154,1158,1162,1166,1171,1175,1179,1183,1187,1191,1195],{"type":413,"tag":465,"props":1155,"children":1156},{"style":484},[1157],{"type":419,"value":618},{"type":413,"tag":465,"props":1159,"children":1160},{"style":588},[1161],{"type":419,"value":736},{"type":413,"tag":465,"props":1163,"children":1164},{"style":484},[1165],{"type":419,"value":507},{"type":413,"tag":465,"props":1167,"children":1168},{"style":484},[1169],{"type":419,"value":1170}," this.",{"type":413,"tag":465,"props":1172,"children":1173},{"style":588},[1174],{"type":419,"value":736},{"type":413,"tag":465,"props":1176,"children":1177},{"style":484},[1178],{"type":419,"value":746},{"type":413,"tag":465,"props":1180,"children":1181},{"style":805},[1182],{"type":419,"value":909},{"type":413,"tag":465,"props":1184,"children":1185},{"style":499},[1186],{"type":419,"value":542},{"type":413,"tag":465,"props":1188,"children":1189},{"style":484},[1190],{"type":419,"value":439},{"type":413,"tag":465,"props":1192,"children":1193},{"style":499},[1194],{"type":419,"value":568},{"type":413,"tag":465,"props":1196,"children":1197},{"style":484},[1198],{"type":419,"value":518},{"type":413,"tag":465,"props":1200,"children":1201},{"class":467,"line":584},[1202,1206,1210,1214,1218,1222,1226,1230,1234,1238,1242],{"type":413,"tag":465,"props":1203,"children":1204},{"style":484},[1205],{"type":419,"value":618},{"type":413,"tag":465,"props":1207,"children":1208},{"style":588},[1209],{"type":419,"value":744},{"type":413,"tag":465,"props":1211,"children":1212},{"style":484},[1213],{"type":419,"value":507},{"type":413,"tag":465,"props":1215,"children":1216},{"style":484},[1217],{"type":419,"value":1170},{"type":413,"tag":465,"props":1219,"children":1220},{"style":588},[1221],{"type":419,"value":744},{"type":413,"tag":465,"props":1223,"children":1224},{"style":484},[1225],{"type":419,"value":746},{"type":413,"tag":465,"props":1227,"children":1228},{"style":805},[1229],{"type":419,"value":909},{"type":413,"tag":465,"props":1231,"children":1232},{"style":499},[1233],{"type":419,"value":542},{"type":413,"tag":465,"props":1235,"children":1236},{"style":484},[1237],{"type":419,"value":439},{"type":413,"tag":465,"props":1239,"children":1240},{"style":499},[1241],{"type":419,"value":568},{"type":413,"tag":465,"props":1243,"children":1244},{"style":484},[1245],{"type":419,"value":518},{"type":413,"tag":465,"props":1247,"children":1248},{"class":467,"line":594},[1249],{"type":413,"tag":465,"props":1250,"children":1251},{"style":484},[1252],{"type":419,"value":581},{"type":413,"tag":465,"props":1254,"children":1255},{"class":467,"line":612},[1256],{"type":413,"tag":465,"props":1257,"children":1258},{"style":588},[1259],{"type":419,"value":591},{"type":413,"tag":465,"props":1261,"children":1262},{"class":467,"line":639},[1263,1267,1271],{"type":413,"tag":465,"props":1264,"children":1265},{"style":499},[1266],{"type":419,"value":600},{"type":413,"tag":465,"props":1268,"children":1269},{"style":484},[1270],{"type":419,"value":605},{"type":413,"tag":465,"props":1272,"children":1273},{"style":484},[1274],{"type":419,"value":487},{"type":413,"tag":465,"props":1276,"children":1277},{"class":467,"line":647},[1278,1282,1286,1290,1294],{"type":413,"tag":465,"props":1279,"children":1280},{"style":484},[1281],{"type":419,"value":618},{"type":413,"tag":465,"props":1283,"children":1284},{"style":588},[1285],{"type":419,"value":623},{"type":413,"tag":465,"props":1287,"children":1288},{"style":484},[1289],{"type":419,"value":507},{"type":413,"tag":465,"props":1291,"children":1292},{"style":510},[1293],{"type":419,"value":632},{"type":413,"tag":465,"props":1295,"children":1296},{"style":484},[1297],{"type":419,"value":518},{"type":413,"tag":465,"props":1299,"children":1300},{"class":467,"line":655},[1301],{"type":413,"tag":465,"props":1302,"children":1303},{"style":484},[1304],{"type":419,"value":581},{"type":413,"tag":465,"props":1306,"children":1307},{"class":467,"line":672},[1308],{"type":413,"tag":465,"props":1309,"children":1310},{"emptyLinePlaceholder":525},[1311],{"type":419,"value":528},{"type":413,"tag":465,"props":1313,"children":1314},{"class":467,"line":696},[1315,1319,1323],{"type":413,"tag":465,"props":1316,"children":1317},{"style":499},[1318],{"type":419,"value":661},{"type":413,"tag":465,"props":1320,"children":1321},{"style":484},[1322],{"type":419,"value":605},{"type":413,"tag":465,"props":1324,"children":1325},{"style":484},[1326],{"type":419,"value":487},{"type":413,"tag":465,"props":1328,"children":1329},{"class":467,"line":704},[1330,1334,1338,1342,1346],{"type":413,"tag":465,"props":1331,"children":1332},{"style":484},[1333],{"type":419,"value":618},{"type":413,"tag":465,"props":1335,"children":1336},{"style":588},[1337],{"type":419,"value":623},{"type":413,"tag":465,"props":1339,"children":1340},{"style":484},[1341],{"type":419,"value":507},{"type":413,"tag":465,"props":1343,"children":1344},{"style":510},[1345],{"type":419,"value":513},{"type":413,"tag":465,"props":1347,"children":1348},{"style":484},[1349],{"type":419,"value":518},{"type":413,"tag":465,"props":1351,"children":1353},{"class":467,"line":1352},15,[1354],{"type":413,"tag":465,"props":1355,"children":1356},{"style":484},[1357],{"type":419,"value":581},{"type":413,"tag":465,"props":1359,"children":1361},{"class":467,"line":1360},16,[1362],{"type":413,"tag":465,"props":1363,"children":1364},{"style":484},[1365],{"type":419,"value":710},{"type":413,"tag":465,"props":1367,"children":1369},{"class":467,"line":1368},17,[1370],{"type":413,"tag":465,"props":1371,"children":1372},{"emptyLinePlaceholder":525},[1373],{"type":419,"value":528},{"type":413,"tag":465,"props":1375,"children":1377},{"class":467,"line":1376},18,[1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418],{"type":413,"tag":465,"props":1379,"children":1380},{"style":472},[1381],{"type":419,"value":787},{"type":413,"tag":465,"props":1383,"children":1384},{"style":588},[1385],{"type":419,"value":792},{"type":413,"tag":465,"props":1387,"children":1388},{"style":484},[1389],{"type":419,"value":797},{"type":413,"tag":465,"props":1391,"children":1392},{"style":484},[1393],{"type":419,"value":802},{"type":413,"tag":465,"props":1395,"children":1396},{"style":805},[1397],{"type":419,"value":481},{"type":413,"tag":465,"props":1399,"children":1400},{"style":588},[1401],{"type":419,"value":542},{"type":413,"tag":465,"props":1403,"children":1404},{"style":484},[1405],{"type":419,"value":816},{"type":413,"tag":465,"props":1407,"children":1408},{"style":819},[1409],{"type":419,"value":822},{"type":413,"tag":465,"props":1411,"children":1412},{"style":484},[1413],{"type":419,"value":816},{"type":413,"tag":465,"props":1415,"children":1416},{"style":588},[1417],{"type":419,"value":568},{"type":413,"tag":465,"props":1419,"children":1420},{"style":484},[1421],{"type":419,"value":518},{"type":413,"tag":465,"props":1423,"children":1425},{"class":467,"line":1424},19,[1426,1430,1434,1438,1442,1446,1450],{"type":413,"tag":465,"props":1427,"children":1428},{"style":472},[1429],{"type":419,"value":787},{"type":413,"tag":465,"props":1431,"children":1432},{"style":588},[1433],{"type":419,"value":846},{"type":413,"tag":465,"props":1435,"children":1436},{"style":484},[1437],{"type":419,"value":797},{"type":413,"tag":465,"props":1439,"children":1440},{"style":588},[1441],{"type":419,"value":855},{"type":413,"tag":465,"props":1443,"children":1444},{"style":484},[1445],{"type":419,"value":746},{"type":413,"tag":465,"props":1447,"children":1448},{"style":588},[1449],{"type":419,"value":736},{"type":413,"tag":465,"props":1451,"children":1452},{"style":484},[1453],{"type":419,"value":518},{"type":413,"tag":465,"props":1455,"children":1457},{"class":467,"line":1456},20,[1458,1462,1466],{"type":413,"tag":465,"props":1459,"children":1460},{"style":805},[1461],{"type":419,"value":875},{"type":413,"tag":465,"props":1463,"children":1464},{"style":588},[1465],{"type":419,"value":605},{"type":413,"tag":465,"props":1467,"children":1468},{"style":484},[1469],{"type":419,"value":518},{"type":413,"tag":414,"props":1471,"children":1473},{"id":1472},"tool-of-the-week-durable-functions-monitor",[1474],{"type":419,"value":1475},"Tool of the week: Durable Functions Monitor ⚡",{"type":413,"tag":429,"props":1477,"children":1478},{},[1479,1481,1488],{"type":419,"value":1480},"If you are an Azure developer, you are probably already familiar with Azure Functions which is one of the solutions to do serverless in Azure. And, you may also have used Durable Functions to build serverless workflows. If I quote ",{"type":413,"tag":902,"props":1482,"children":1485},{"href":1483,"rel":1484},"https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp",[906],[1486],{"type":419,"value":1487},"Microsoft documentation",{"type":419,"value":1489},": \"Durable Functions is an extension of Azure Functions that lets you write stateful functions in a serverless compute environment.\" In concrete terms, if you are developing multiple Azure Functions and you want to orchestrate their execution while maintaining a state, Durable Functions are what you need. I like this technology a lot ❤️. When used correctly and for the right purpose, it can solve many issues you would face to implementing manually a workflow. Enough talk, let's go back to the tool of the week!",{"type":413,"tag":429,"props":1491,"children":1492},{},[1493],{"type":413,"tag":888,"props":1494,"children":1498},{"alt":1495,"className":1496,"src":1497},"GitHub README of the Durable Functions Monitor project.",[892,893],"/posts/images/w202022tips_durablemonitor_1.png",[],{"type":413,"tag":429,"props":1500,"children":1501},{},[1502,1509],{"type":413,"tag":902,"props":1503,"children":1506},{"href":1504,"rel":1505},"https://github.com/microsoft/DurableFunctionsMonitor",[906],[1507],{"type":419,"value":1508},"Durable Functions Monitor",{"type":419,"value":1510}," is a UI tool that allows you to monitor, manage and debug your Azure Durable Functions. That's something very valuable because the tooling in Azure Portal is very poor for Durable Functions. Moreover, because a workflow can last for a long time and is often composed of many Azure Functions, it can be quite hard to understand at what stage the workflow is and what functions have already been executed 🤔. Durable Functions can help you with that and offers many other interesting features (functions graph, sequence diagram...). I heard about it a while ago but did not take the time to try it until recently and honestly it's too bad because it's a must-have to work with Azure Durable Functions 🚀!",{"type":413,"tag":1512,"props":1513,"children":1515},"callout",{"icon":1514},"i-heroicons-light-bulb",[1516],{"type":413,"tag":429,"props":1517,"children":1518},{},[1519],{"type":419,"value":1520},"It's worth noting that Durable Functions Monitor can be used as a vscode extension, as a Standalone service, or directly in your Function App.",{"type":413,"tag":414,"props":1522,"children":1524},{"id":1523},"git-tip-of-the-week-alias-to-force-push-commits",[1525],{"type":419,"value":1526},"Git tip of the week: alias to force push commits",{"type":413,"tag":429,"props":1528,"children":1529},{},[1530,1532,1539],{"type":419,"value":1531},"I often force push changes on my git branches. Indeed, I try to keep a clean and easy to read the history on my branches by using the ",{"type":413,"tag":902,"props":1533,"children":1536},{"href":1534,"rel":1535},"https://www.techwatching.dev/gitcheatsheet#when-you-want-to-have-a-clean-commit-history-on-your-branch-before-creating-your-pull-request",[906],[1537],{"type":419,"value":1538},"interactive rebase command",{"type":419,"value":1540}," so that it's easier for my colleagues to review my Pull Requests and I can use a rebase merging strategy instead of squashing my changes in a big commit when completing them.",{"type":413,"tag":429,"props":1542,"children":1543},{},[1544,1546,1552,1554,1560,1562,1568,1570,1577,1579,1585],{"type":419,"value":1545},"Before, I was using the ",{"type":413,"tag":422,"props":1547,"children":1549},{"className":1548},[],[1550],{"type":419,"value":1551},"git push --force",{"type":419,"value":1553}," command but reading a few articles on the topic convinced me that I should use the ",{"type":413,"tag":422,"props":1555,"children":1557},{"className":1556},[],[1558],{"type":419,"value":1559},"git push --force-with-lease",{"type":419,"value":1561}," command instead to avoid crushing commits colleagues could have done on my branch (even if there is little risk as I only rewrite the history of already pushed changes when working alone on a branch). You can read more about ",{"type":413,"tag":422,"props":1563,"children":1565},{"className":1564},[],[1566],{"type":419,"value":1567},"--force-with-lease",{"type":419,"value":1569}," on the git ",{"type":413,"tag":902,"props":1571,"children":1574},{"href":1572,"rel":1573},"https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegt",[906],[1575],{"type":419,"value":1576},"documentation",{"type":419,"value":1578},". The only problem with this command is that it's a bit long to write so here is an alias to add to your ",{"type":413,"tag":422,"props":1580,"children":1582},{"className":1581},[],[1583],{"type":419,"value":1584},".gitconfig",{"type":419,"value":558},{"type":413,"tag":456,"props":1587,"children":1591},{"className":1588,"code":1589,"language":1590,"meta":401,"style":401},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[alias]\n    pf = push origin --force-with-lease\n","yaml",[1592],{"type":413,"tag":422,"props":1593,"children":1594},{"__ignoreMap":401},[1595,1613],{"type":413,"tag":465,"props":1596,"children":1597},{"class":467,"line":468},[1598,1603,1608],{"type":413,"tag":465,"props":1599,"children":1600},{"style":484},[1601],{"type":419,"value":1602},"[",{"type":413,"tag":465,"props":1604,"children":1605},{"style":819},[1606],{"type":419,"value":1607},"alias",{"type":413,"tag":465,"props":1609,"children":1610},{"style":484},[1611],{"type":419,"value":1612},"]\n",{"type":413,"tag":465,"props":1614,"children":1615},{"class":467,"line":490},[1616],{"type":413,"tag":465,"props":1617,"children":1618},{"style":819},[1619],{"type":419,"value":1620},"    pf = push origin --force-with-lease\n",{"type":413,"tag":429,"props":1622,"children":1623},{},[1624],{"type":419,"value":1625},"And that's it for this week, happy learning!",{"type":413,"tag":1627,"props":1628,"children":1629},"style",{},[1630],{"type":419,"value":1631},"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":490,"depth":490,"links":1633},[1634,1636,1637],{"id":416,"depth":490,"text":1635},"Reminder for my future self: don't forget about \"this\" in ts",{"id":1472,"depth":490,"text":1475},{"id":1523,"depth":490,"text":1526},"markdown","content:1.posts:38.w20-2022-tips-learned-this-week.md","content","1.posts/38.w20-2022-tips-learned-this-week.md","md",{"_path":118,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":117,"description":1644,"lead":1644,"date":1645,"image":1646,"badge":1647,"tags":1648,"body":1649,"_type":1638,"_id":1864,"_source":1640,"_file":1865,"_extension":1642},"Git commands in vscode, a nice tool for Vue developers and a must-have Visual Studio extension.","2022-05-14T00:00:00.000Z",{"src":405},{"label":407},[272,208,241,340,337,206],{"type":410,"children":1650,"toc":1859},[1651,1657,1689,1699,1704,1713,1725,1731,1780,1789,1803,1812,1818,1832,1841,1846,1855],{"type":413,"tag":414,"props":1652,"children":1654},{"id":1653},"git-tip-of-the-week",[1655],{"type":419,"value":1656},"Git tip of the week",{"type":413,"tag":429,"props":1658,"children":1659},{},[1660,1662,1669,1671,1678,1680,1687],{"type":419,"value":1661},"If you have read my ",{"type":413,"tag":902,"props":1663,"children":1666},{"href":1664,"rel":1665},"https://www.techwatching.dev/gitcheatsheet",[906],[1667],{"type":419,"value":1668},"git cheat sheet",{"type":419,"value":1670},", you know that I am a big fan of the ",{"type":413,"tag":902,"props":1672,"children":1675},{"href":1673,"rel":1674},"https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens",[906],[1676],{"type":419,"value":1677},"GitLens",{"type":419,"value":1679}," vscode extension. I have been using it for a while now but just discovered recently that there is a ",{"type":413,"tag":902,"props":1681,"children":1684},{"href":1682,"rel":1683},"https://github.com/gitkraken/vscode-gitlens#git-command-palette-",[906],[1685],{"type":419,"value":1686},"Git Command Palette",{"type":419,"value":1688}," that gives access to most common Git commands.",{"type":413,"tag":429,"props":1690,"children":1691},{},[1692],{"type":413,"tag":888,"props":1693,"children":1698},{"alt":1694,"className":1695,"src":1696,"width":1697},"GitLens Command Palette in vscode",[892,893],"/posts/images/w192022tips_gitlens_1.png",1000,[],{"type":413,"tag":429,"props":1700,"children":1701},{},[1702],{"type":419,"value":1703},"Usually, I prefer typing the git commands rather than using a visual tool. This way, I know exactly what I am doing (no magic commands done by a tool behind the scene), and I improve my knowledge of git. However, I think that with Git Command Palette, I get the best of both worlds. The UI helps me to use the git command I need without having to type everything and remember the exact syntax of the command. Yet, this is not a UI with buttons that hide from me the git commands being run. I am still aware of the exact git commands I am using and how.",{"type":413,"tag":429,"props":1705,"children":1706},{},[1707],{"type":413,"tag":888,"props":1708,"children":1712},{"alt":1709,"className":1710,"src":1711,"width":1697},"Doing a Git fetch in GitLens Command Palette.",[892,893],"/posts/images/w192022tips_gitlens_2.png",[],{"type":413,"tag":429,"props":1714,"children":1715},{},[1716,1718,1724],{"type":419,"value":1717},"On Windows, the default shortcut to use the Git Command Palette is ",{"type":413,"tag":422,"props":1719,"children":1721},{"className":1720},[],[1722],{"type":419,"value":1723},"Ctrl + Shift + G : ",{"type":419,"value":746},{"type":413,"tag":414,"props":1726,"children":1728},{"id":1727},"tool-of-the-week-vue-telescope",[1729],{"type":419,"value":1730},"Tool of the week: Vue Telescope",{"type":413,"tag":429,"props":1732,"children":1733},{},[1734,1736,1743,1745,1752,1754,1761,1763,1770,1772,1778],{"type":419,"value":1735},"If you are a Vue developer and don't know this tool yet, this is going to make your day! When browsing a website, you are probably wondering if it has been made with Vue.js and if so what is the technology stack behind it. Personally, I find it very interesting to know which frameworks, libraries, or plugins have been used to create a website in Vue. And that's what ",{"type":413,"tag":902,"props":1737,"children":1740},{"href":1738,"rel":1739},"https://vuetelescope.com/",[906],[1741],{"type":419,"value":1742},"Vue Telescope",{"type":419,"value":1744}," is about. It's an open source tool made by ",{"type":413,"tag":902,"props":1746,"children":1749},{"href":1747,"rel":1748},"https://nuxtlabs.com/",[906],[1750],{"type":419,"value":1751},"NuxtLabs",{"type":419,"value":1753}," (the team behind the ",{"type":413,"tag":902,"props":1755,"children":1758},{"href":1756,"rel":1757},"https://nuxtjs.org/",[906],[1759],{"type":419,"value":1760},"Nuxt",{"type":419,"value":1762}," framework) that detects the Vue technologies used in a website. It can be used from a browser ",{"type":413,"tag":902,"props":1764,"children":1767},{"href":1765,"rel":1766},"https://chrome.google.com/webstore/detail/vue-telescope/neaebjphlfplgdhedjdhcnpjkndddbpd",[906],[1768],{"type":419,"value":1769},"extension",{"type":419,"value":1771}," or from Vue Telescope's ",{"type":413,"tag":902,"props":1773,"children":1775},{"href":1738,"rel":1774},[906],[1776],{"type":419,"value":1777},"website",{"type":419,"value":1779}," to search a analyze a specific website.",{"type":413,"tag":429,"props":1781,"children":1782},{},[1783],{"type":413,"tag":888,"props":1784,"children":1788},{"alt":1785,"className":1786,"src":1787,"width":1697},"Vue Telescope extension showing Vue Telescope stack on its website.",[892,893],"/posts/images/w192022tips_vuetelescope_1.png",[],{"type":413,"tag":429,"props":1790,"children":1791},{},[1792,1794,1801],{"type":419,"value":1793},"You can explore the Vue.js websites already scanned by VueTelescope ",{"type":413,"tag":902,"props":1795,"children":1798},{"href":1796,"rel":1797},"https://vuetelescope.com/explore",[906],[1799],{"type":419,"value":1800},"here",{"type":419,"value":1802}," and filter on the frameworks, UI Frameworks you are interested in.",{"type":413,"tag":429,"props":1804,"children":1805},{},[1806],{"type":413,"tag":888,"props":1807,"children":1811},{"alt":1808,"className":1809,"src":1810,"width":1697},"Vue Telescope search.",[892,893],"/posts/images/w192022tips_vuetelescope_2.png",[],{"type":413,"tag":414,"props":1813,"children":1815},{"id":1814},"the-visual-studio-extension-you-should-try-add-new-file",[1816],{"type":419,"value":1817},"The Visual Studio extension you should try: Add New File",{"type":413,"tag":429,"props":1819,"children":1820},{},[1821,1823,1830],{"type":419,"value":1822},"Sometimes the simplest IDE extensions are the best. That's the case for the ",{"type":413,"tag":902,"props":1824,"children":1827},{"href":1825,"rel":1826},"https://marketplace.visualstudio.com/items?itemName=MadsKristensen.AddNewFile64",[906],[1828],{"type":419,"value":1829},"\"Add New\"",{"type":419,"value":1831}," Visual Studio extension which allows you to quickly create a new file by hitting \"Shift+F2\" and writing the name of the file with its extension. Nothing fancy, but it saves you a lot of time compared to adding a new file using the default dialog.",{"type":413,"tag":429,"props":1833,"children":1834},{},[1835],{"type":413,"tag":888,"props":1836,"children":1840},{"alt":1837,"className":1838,"src":1839,"width":1697},"Website of Add New File Visual Studio extension.",[892,893],"/posts/images/w192022tips_addnewfile_1.png",[],{"type":413,"tag":429,"props":1842,"children":1843},{},[1844],{"type":419,"value":1845},"As you can see you can even create the missing folders where the file is placed.",{"type":413,"tag":429,"props":1847,"children":1848},{},[1849],{"type":413,"tag":888,"props":1850,"children":1854},{"alt":1851,"className":1852,"src":1853,"width":1697},"Usage of Add New File in Visual Studio.",[892,893],"/posts/images/w192022tips_addnewfile.gif",[],{"type":413,"tag":429,"props":1856,"children":1857},{},[1858],{"type":419,"value":1625},{"title":401,"searchDepth":490,"depth":490,"links":1860},[1861,1862,1863],{"id":1653,"depth":490,"text":1656},{"id":1727,"depth":490,"text":1730},{"id":1814,"depth":490,"text":1817},"content:1.posts:37.w19-2022-tips-learned-this-week.md","1.posts/37.w19-2022-tips-learned-this-week.md",{"_path":106,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":105,"description":1867,"lead":1868,"date":1869,"image":1870,"badge":1871,"tags":1872,"body":1873,"_type":1638,"_id":2299,"_source":1640,"_file":2300,"_extension":1642},".NET configuration providers, Vite vscode extension, Azure DevOps pull request templates, and degit.","Tooling around .NET, Azure DevOps, and VS Code.","2022-01-24T00:00:00.000Z",{"src":405},{"label":407},[272,239,263,343,208,346,241,206],{"type":410,"children":1874,"toc":2293},[1875,1881,1931,1940,1953,2048,2070,2076,2099,2104,2113,2119,2124,2138,2151,2164,2169,2178,2183,2188,2193,2202,2218,2224,2229,2264,2273,2285,2289],{"type":413,"tag":414,"props":1876,"children":1878},{"id":1877},"net-tip-of-the-week-the-new-way-to-add-a-configuration-source",[1879],{"type":419,"value":1880},".NET tip of the week: the new way to add a configuration source",{"type":413,"tag":429,"props":1882,"children":1883},{},[1884,1886,1892,1893,1899,1901,1907,1909,1914,1916,1921,1923,1930],{"type":419,"value":1885},".NET 6 introduced a new way to build a .NET application using the new ",{"type":413,"tag":422,"props":1887,"children":1889},{"className":1888},[],[1890],{"type":419,"value":1891},"WebApplication",{"type":419,"value":738},{"type":413,"tag":422,"props":1894,"children":1896},{"className":1895},[],[1897],{"type":419,"value":1898},"WebApplicationBuilder",{"type":419,"value":1900}," classes. One thing I like about it is how configuration is handled. Instead of using the ",{"type":413,"tag":422,"props":1902,"children":1904},{"className":1903},[],[1905],{"type":419,"value":1906},"ConfigureAppConfiguration",{"type":419,"value":1908}," method to add a new configuration source, you can directly use the ",{"type":413,"tag":422,"props":1910,"children":1912},{"className":1911},[],[1913],{"type":419,"value":263},{"type":419,"value":1915}," property on the ",{"type":413,"tag":422,"props":1917,"children":1919},{"className":1918},[],[1920],{"type":419,"value":1898},{"type":419,"value":1922}," instance. You can see an example of this change on this screenshot of the ",{"type":413,"tag":902,"props":1924,"children":1927},{"href":1925,"rel":1926},"https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-6.0#add-configuration-providers",[906],[1928],{"type":419,"value":1929},"ASP.NET Core documentation",{"type":419,"value":558},{"type":413,"tag":429,"props":1932,"children":1933},{},[1934],{"type":413,"tag":888,"props":1935,"children":1939},{"alt":1936,"className":1937,"src":1938},"Using configuration provider in ASP.NET 5 versus ASP.NET 6.",[892,893],"/posts/images/w032022tips_net_configuration_1.png",[],{"type":413,"tag":429,"props":1941,"children":1942},{},[1943,1945,1951],{"type":419,"value":1944},"You may think this way of adding a new configuration source does not bring much apart from making the code shorter. I thought it too until I discovered that it enables you to access configuration in the builder from previously registered configuration sources. For instance, if you want to load secrets from an Azure Key Vault into your configuration, you will need to retrieve the Key Vault URI from your configuration (that you may have set in your ",{"type":413,"tag":422,"props":1946,"children":1948},{"className":1947},[],[1949],{"type":419,"value":1950},"appsettings.Development.json",{"type":419,"value":1952}," file). Before you would have to partially build your configuration to get the value of a setting, now you can just access it.",{"type":413,"tag":456,"props":1954,"children":1957},{"className":1955,"code":1956,"language":326,"meta":401,"style":401},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","builder.Configuration.AddAzureKeyVault(new Uri(builder.Configuration[\"KeyVault:VaultUri\"]), new DefaultAzureCredential());\n",[1958],{"type":413,"tag":422,"props":1959,"children":1960},{"__ignoreMap":401},[1961],{"type":413,"tag":465,"props":1962,"children":1963},{"class":467,"line":468},[1964,1969,1973,1977,1981,1986,1991,1996,2000,2004,2008,2012,2016,2020,2025,2029,2034,2038,2043],{"type":413,"tag":465,"props":1965,"children":1966},{"style":588},[1967],{"type":419,"value":1968},"builder",{"type":413,"tag":465,"props":1970,"children":1971},{"style":484},[1972],{"type":419,"value":746},{"type":413,"tag":465,"props":1974,"children":1975},{"style":588},[1976],{"type":419,"value":263},{"type":413,"tag":465,"props":1978,"children":1979},{"style":484},[1980],{"type":419,"value":746},{"type":413,"tag":465,"props":1982,"children":1983},{"style":805},[1984],{"type":419,"value":1985},"AddAzureKeyVault",{"type":413,"tag":465,"props":1987,"children":1988},{"style":484},[1989],{"type":419,"value":1990},"(new",{"type":413,"tag":465,"props":1992,"children":1993},{"style":478},[1994],{"type":419,"value":1995}," Uri",{"type":413,"tag":465,"props":1997,"children":1998},{"style":484},[1999],{"type":419,"value":542},{"type":413,"tag":465,"props":2001,"children":2002},{"style":588},[2003],{"type":419,"value":1968},{"type":413,"tag":465,"props":2005,"children":2006},{"style":484},[2007],{"type":419,"value":746},{"type":413,"tag":465,"props":2009,"children":2010},{"style":588},[2011],{"type":419,"value":263},{"type":413,"tag":465,"props":2013,"children":2014},{"style":484},[2015],{"type":419,"value":1602},{"type":413,"tag":465,"props":2017,"children":2018},{"style":484},[2019],{"type":419,"value":816},{"type":413,"tag":465,"props":2021,"children":2022},{"style":819},[2023],{"type":419,"value":2024},"KeyVault:VaultUri",{"type":413,"tag":465,"props":2026,"children":2027},{"style":484},[2028],{"type":419,"value":816},{"type":413,"tag":465,"props":2030,"children":2031},{"style":484},[2032],{"type":419,"value":2033},"]),",{"type":413,"tag":465,"props":2035,"children":2036},{"style":484},[2037],{"type":419,"value":802},{"type":413,"tag":465,"props":2039,"children":2040},{"style":478},[2041],{"type":419,"value":2042}," DefaultAzureCredential",{"type":413,"tag":465,"props":2044,"children":2045},{"style":484},[2046],{"type":419,"value":2047},"());\n",{"type":413,"tag":429,"props":2049,"children":2050},{},[2051,2053,2060,2062,2068],{"type":419,"value":2052},"Configuration from previously registered sources is already available because configuration sources are directly loaded once they are added. If you want to learn more about the behind-the-scenes, Andrew Lock has a ",{"type":413,"tag":902,"props":2054,"children":2057},{"href":2055,"rel":2056},"https://andrewlock.net/exploring-dotnet-6-part-1-looking-inside-configurationmanager-in-dotnet-6/",[906],[2058],{"type":419,"value":2059},"very interesting article",{"type":419,"value":2061}," about ",{"type":413,"tag":422,"props":2063,"children":2065},{"className":2064},[],[2066],{"type":419,"value":2067},"ConfigurationManager",{"type":419,"value":2069}," that I suggest you read.",{"type":413,"tag":414,"props":2071,"children":2073},{"id":2072},"the-vs-code-extension-you-should-try-vite",[2074],{"type":419,"value":2075},"The VS Code extension you should try: Vite",{"type":413,"tag":429,"props":2077,"children":2078},{},[2079,2081,2088,2090,2097],{"type":419,"value":2080},"If you are developing a front-end using Vite (and there are ",{"type":413,"tag":902,"props":2082,"children":2085},{"href":2083,"rel":2084},"https://vitejs.dev/guide/why.html",[906],[2086],{"type":419,"value":2087},"good reasons",{"type":419,"value":2089}," why you should), there is a ",{"type":413,"tag":902,"props":2091,"children":2094},{"href":2092,"rel":2093},"https://marketplace.visualstudio.com/items?itemName=antfu.vite",[906],[2095],{"type":419,"value":2096},"Vite extension for VS Code",{"type":419,"value":2098}," currently in preview.",{"type":413,"tag":429,"props":2100,"children":2101},{},[2102],{"type":419,"value":2103},"You can see the main features of this extension below: little things that make you always more productive.",{"type":413,"tag":429,"props":2105,"children":2106},{},[2107],{"type":413,"tag":888,"props":2108,"children":2112},{"alt":2109,"className":2110,"src":2111},"Vs code vite exension.",[892,893],"/posts/images/w032022tips_vscode_vite_1.png",[],{"type":413,"tag":414,"props":2114,"children":2116},{"id":2115},"the-azure-devops-tip-you-did-not-know-about-creating-pull-requests-templates",[2117],{"type":419,"value":2118},"The Azure DevOps tip you did not know about: creating pull requests templates",{"type":413,"tag":429,"props":2120,"children":2121},{},[2122],{"type":419,"value":2123},"As a developer working with Azure DevOps, you probably spend a lot of time reviewing your colleagues pull requests and what helps you to have a good context (of what problem a pull request solves or what new feature it brings) are having a work item associated to the pull request, and having a good description. You can enforce the pull request to have an associated work item by setting it to mandatory in your branch policies, but \"having a good description\" is not something you can enforce.",{"type":413,"tag":429,"props":2125,"children":2126},{},[2127,2129,2136],{"type":419,"value":2128},"However, you can provide some guidance on what the description should tell, how it should be organized, what are the key points to verify before submitting the pull request... How do you do that? By creating a pull request template in your repository which will be a markdown file that will be automatically added to a pull request description when the pull request is created. You can read the ",{"type":413,"tag":902,"props":2130,"children":2133},{"href":2131,"rel":2132},"https://docs.microsoft.com/en-us/azure/devops/repos/git/pull-request-templates?view=azure-devops",[906],[2134],{"type":419,"value":2135},"official documentation",{"type":419,"value":2137}," but let me show you quickly how it works:",{"type":413,"tag":429,"props":2139,"children":2140},{},[2141,2143,2149],{"type":419,"value":2142},"1- You create a ",{"type":413,"tag":422,"props":2144,"children":2146},{"className":2145},[],[2147],{"type":419,"value":2148},".azuredevops",{"type":419,"value":2150}," folder in the root of your git repository",{"type":413,"tag":429,"props":2152,"children":2153},{},[2154,2156,2162],{"type":419,"value":2155},"2- You create a markdown file ",{"type":413,"tag":422,"props":2157,"children":2159},{"className":2158},[],[2160],{"type":419,"value":2161},"pull_request_template.md",{"type":419,"value":2163}," containing the description you want",{"type":413,"tag":429,"props":2165,"children":2166},{},[2167],{"type":419,"value":2168},"You can see below an example of a template I created:",{"type":413,"tag":429,"props":2170,"children":2171},{},[2172],{"type":413,"tag":888,"props":2173,"children":2177},{"alt":2174,"className":2175,"src":2176},"Pull request markdown template file.",[892,893],"/posts/images/w032022tips_pr_template_1.png",[],{"type":413,"tag":429,"props":2179,"children":2180},{},[2181],{"type":419,"value":2182},"3- You commit this file and push it in your main branch",{"type":413,"tag":429,"props":2184,"children":2185},{},[2186],{"type":419,"value":2187},"4- Now when someone creates a pull request, he will have a pre-filled description to complete before submitting his pull request",{"type":413,"tag":429,"props":2189,"children":2190},{},[2191],{"type":419,"value":2192},"This is what it looks like for my template:",{"type":413,"tag":429,"props":2194,"children":2195},{},[2196],{"type":413,"tag":888,"props":2197,"children":2201},{"alt":2198,"className":2199,"src":2200},"Pull request template in Azure DevOps.",[892,893],"/posts/images/w032022tips_pr_template_2.png",[],{"type":413,"tag":1512,"props":2203,"children":2205},{"icon":2204},"i-heroicons-chat-bubble-left-20-solid",[2206],{"type":413,"tag":429,"props":2207,"children":2208},{},[2209,2211,2217],{"type":419,"value":2210},"If you are using GitHub and not Azure DevOps, just know that there are also pull requests templates in ",{"type":413,"tag":902,"props":2212,"children":2215},{"href":2213,"rel":2214},"https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository",[906],[2216],{"type":419,"value":233},{"type":419,"value":746},{"type":413,"tag":414,"props":2219,"children":2221},{"id":2220},"tool-of-the-week-degit",[2222],{"type":419,"value":2223},"Tool of the week: degit",{"type":413,"tag":429,"props":2225,"children":2226},{},[2227],{"type":419,"value":2228},"Sometimes you find an interesting open source git repository that could help you save some time when starting a new project. That can be a project template or a sample, it's a repository that you want to start coding from. You can clone it or fork it but you will retrieve the whole git history and that is something that you probably don't want.",{"type":413,"tag":429,"props":2230,"children":2231},{},[2232,2239,2241,2247,2249,2255,2257,2263],{"type":413,"tag":902,"props":2233,"children":2236},{"href":2234,"rel":2235},"https://github.com/Rich-Harris/degit",[906],[2237],{"type":419,"value":2238},"degit",{"type":419,"value":2240}," is a helpful tool that solves this issue. When you run this tool on a git repository, it retrieves locally the latest version of this repository without its git history. It's an ",{"type":413,"tag":422,"props":2242,"children":2244},{"className":2243},[],[2245],{"type":419,"value":2246},"npm",{"type":419,"value":2248}," tool so you can install it globally with ",{"type":413,"tag":422,"props":2250,"children":2252},{"className":2251},[],[2253],{"type":419,"value":2254},"npm install -g degit",{"type":419,"value":2256}," or directly run it using ",{"type":413,"tag":422,"props":2258,"children":2260},{"className":2259},[],[2261],{"type":419,"value":2262},"npx",{"type":419,"value":746},{"type":413,"tag":429,"props":2265,"children":2266},{},[2267],{"type":413,"tag":888,"props":2268,"children":2272},{"alt":2269,"className":2270,"src":2271},"Ouput when using degit package on a repository.",[892,893],"/posts/images/w032022tips_degit_1.png",[],{"type":413,"tag":429,"props":2274,"children":2275},{},[2276,2278,2283],{"type":419,"value":2277},"Don't hesitate to give the project a star on ",{"type":413,"tag":902,"props":2279,"children":2281},{"href":2234,"rel":2280},[906],[2282],{"type":419,"value":233},{"type":419,"value":2284}," if you find it useful.",{"type":413,"tag":429,"props":2286,"children":2287},{},[2288],{"type":419,"value":1625},{"type":413,"tag":1627,"props":2290,"children":2291},{},[2292],{"type":419,"value":1631},{"title":401,"searchDepth":490,"depth":490,"links":2294},[2295,2296,2297,2298],{"id":1877,"depth":490,"text":1880},{"id":2072,"depth":490,"text":2075},{"id":2115,"depth":490,"text":2118},{"id":2220,"depth":490,"text":2223},"content:1.posts:33.w03-2022-tips-learned-this-week.md","1.posts/33.w03-2022-tips-learned-this-week.md",{"_path":91,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":90,"description":2302,"lead":2303,"date":2304,"image":2305,"badge":2306,"tags":2307,"body":2308,"_type":1638,"_id":2569,"_source":1640,"_file":2570,"_extension":1642},"Vue Devtools, Visual Studio themes, Git tips, and .NET Conf replays.","A bit of tooling and a bit of git.","2021-11-14T00:00:00.000Z",{"src":405},{"label":407},[272,337,340,241],{"type":410,"children":2309,"toc":2561},[2310,2322,2334,2364,2373,2379,2402,2425,2434,2440,2445,2450,2456,2484,2512,2529,2535,2548,2557],{"type":413,"tag":414,"props":2311,"children":2313},{"id":2312},"vue-devtools-a-must-have-browser-extension-when-using-vuejs",[2314,2320],{"type":413,"tag":422,"props":2315,"children":2317},{"className":2316},[],[2318],{"type":419,"value":2319},"Vue Devtools",{"type":419,"value":2321},", a must-have browser extension when using Vue.js",{"type":413,"tag":429,"props":2323,"children":2324},{},[2325,2327,2332],{"type":419,"value":2326},"Since a colleague showed me the ",{"type":413,"tag":422,"props":2328,"children":2330},{"className":2329},[],[2331],{"type":419,"value":2319},{"type":419,"value":2333}," extension, it has been a game-changer for me to work on Vue.js projects. It is very useful!",{"type":413,"tag":429,"props":2335,"children":2336},{},[2337,2339,2346,2348,2354,2356,2362],{"type":419,"value":2338},"I could describe to you how this extension works and what are its features but there are already very good articles that do that, like this ",{"type":413,"tag":902,"props":2340,"children":2343},{"href":2341,"rel":2342},"https://www.vuemastery.com/blog/whats-new-in-the-vue3-devtools/",[906],[2344],{"type":419,"value":2345},"one",{"type":419,"value":2347}," on Vue Mastery's blog. Check that, have a look at the ",{"type":413,"tag":902,"props":2349,"children":2352},{"href":2350,"rel":2351},"https://devtools.vuejs.org/",[906],[2353],{"type":419,"value":1576},{"type":419,"value":2355},", install ",{"type":413,"tag":902,"props":2357,"children":2360},{"href":2358,"rel":2359},"https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg",[906],[2361],{"type":419,"value":268},{"type":419,"value":2363}," (the beta version), and try it.",{"type":413,"tag":429,"props":2365,"children":2366},{},[2367],{"type":413,"tag":888,"props":2368,"children":2372},{"alt":2369,"className":2370,"src":2371},"Vue Devtools website.",[892,893],"/posts/images/w452021tips_vue_1.png",[],{"type":413,"tag":414,"props":2374,"children":2376},{"id":2375},"cobalt2-theme-is-available-in-visual-studio-2022",[2377],{"type":419,"value":2378},"Cobalt2 theme is available in Visual Studio 2022",{"type":413,"tag":429,"props":2380,"children":2381},{},[2382,2384,2391,2393,2400],{"type":419,"value":2383},"I have used ",{"type":413,"tag":902,"props":2385,"children":2388},{"href":2386,"rel":2387},"https://marketplace.visualstudio.com/items?itemName=wesbos.theme-cobalt2",[906],[2389],{"type":419,"value":2390},"Cobalt2 theme",{"type":419,"value":2392}," for vscode for quite some time now. And this theme is now available in Visual Studio 2022, you can check ",{"type":413,"tag":902,"props":2394,"children":2397},{"href":2395,"rel":2396},"https://marketplace.visualstudio.com/items?itemName=SIBA.Cobalt2Theme",[906],[2398],{"type":419,"value":2399},"this extension",{"type":419,"value":2401}," to get it.",{"type":413,"tag":429,"props":2403,"children":2404},{},[2405,2407,2414,2416,2423],{"type":419,"value":2406},"A lot of vscode themes have been made available in Visual Studio 2022 thanks to a new tool: ",{"type":413,"tag":902,"props":2408,"children":2411},{"href":2409,"rel":2410},"https://github.com/microsoft/theme-converter-for-vs",[906],[2412],{"type":419,"value":2413},"Theme Converter for Visual Studio",{"type":419,"value":2415},". You can read more about that ",{"type":413,"tag":902,"props":2417,"children":2420},{"href":2418,"rel":2419},"https://devblogs.microsoft.com/visualstudio/custom-themes/",[906],[2421],{"type":419,"value":2422},"in this article",{"type":419,"value":2424}," from Visual Studio dev blog.",{"type":413,"tag":429,"props":2426,"children":2427},{},[2428],{"type":413,"tag":888,"props":2429,"children":2433},{"alt":2430,"className":2431,"src":2432},"Visual Studio 2022 with cobalt theme.",[892,893],"/posts/images/w452021tips_vs_1.png",[],{"type":413,"tag":414,"props":2435,"children":2437},{"id":2436},"keep-a-2nd-clone-for-reviewing-pull-requests",[2438],{"type":419,"value":2439},"Keep a 2nd clone for reviewing pull requests",{"type":413,"tag":429,"props":2441,"children":2442},{},[2443],{"type":419,"value":2444},"I think it is often interesting to checkout the branch of a pull request instead of relying only on the web view to review a PR. It allows checking more things and a better comprehension of the code. However, when you are working on a feature, you don't want to mix your current work with the pull request you are reviewing.",{"type":413,"tag":429,"props":2446,"children":2447},{},[2448],{"type":419,"value":2449},"That is why instead of stashing code changes and switching branches I prefer having on my laptop 2 clones of the same repository I am working on, with one clone dedicated to code reviews.",{"type":413,"tag":414,"props":2451,"children":2453},{"id":2452},"git-clrf",[2454],{"type":419,"value":2455},"Git CLRF",{"type":413,"tag":429,"props":2457,"children":2458},{},[2459,2461,2467,2469,2475,2477,2483],{"type":419,"value":2460},"If you are using Git on Windows, it is a good practice to set your ",{"type":413,"tag":422,"props":2462,"children":2464},{"className":2463},[],[2465],{"type":419,"value":2466},"autocrlf",{"type":419,"value":2468}," to true in your Git configuration to avoid line-ending issues (learn more about this topic in the ",{"type":413,"tag":902,"props":2470,"children":2473},{"href":2471,"rel":2472},"https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration",[906],[2474],{"type":419,"value":1576},{"type":419,"value":2476},"). You can do that with the following command ",{"type":413,"tag":422,"props":2478,"children":2480},{"className":2479},[],[2481],{"type":419,"value":2482},"git config --global core.autocrlf true",{"type":419,"value":746},{"type":413,"tag":429,"props":2485,"children":2486},{},[2487,2489,2494,2496,2502,2504,2510],{"type":419,"value":2488},"Unfortunately, maybe not all your colleagues have correctly configured ",{"type":413,"tag":422,"props":2490,"children":2492},{"className":2491},[],[2493],{"type":419,"value":2466},{"type":419,"value":2495}," on their machine. And you will probably forget to ask each newcomer to check that. So something that can be interesting (if all your team is working on Windows) is to directly enforce this setting on your repository by pushing a ",{"type":413,"tag":422,"props":2497,"children":2499},{"className":2498},[],[2500],{"type":419,"value":2501},".gitattributes",{"type":419,"value":2503}," with ",{"type":413,"tag":422,"props":2505,"children":2507},{"className":2506},[],[2508],{"type":419,"value":2509},"text=auto",{"type":419,"value":2511}," in it).",{"type":413,"tag":1512,"props":2513,"children":2514},{"icon":2204},[2515],{"type":413,"tag":429,"props":2516,"children":2517},{},[2518,2520,2527],{"type":419,"value":2519},"As I was writing these lines, I just saw an article from Scott Hanselman about ",{"type":413,"tag":902,"props":2521,"children":2524},{"href":2522,"rel":2523},"https://www.hanselman.com/blog/carriage-returns-and-line-feeds-will-ultimately-bite-you-some-git-tips",[906],[2525],{"type":419,"value":2526},"Carriage Returns and Line Feeds",{"type":419,"value":2528},", if you want to read more about it.",{"type":413,"tag":414,"props":2530,"children":2532},{"id":2531},"dotnetconf-playlist",[2533],{"type":419,"value":2534},"dotNetConf playlist",{"type":413,"tag":429,"props":2536,"children":2537},{},[2538,2540,2546],{"type":419,"value":2539},"dotNetConf was this week and the replays are available ",{"type":413,"tag":902,"props":2541,"children":2544},{"href":2542,"rel":2543},"https://www.youtube.com/playlist?list=PLdo4fOcmZ0oVFtp9MDEBNbA2sSqYvXSXO",[906],[2545],{"type":419,"value":1800},{"type":419,"value":2547}," if you want to watch some talks you missed.",{"type":413,"tag":429,"props":2549,"children":2550},{},[2551],{"type":413,"tag":888,"props":2552,"children":2556},{"alt":2553,"className":2554,"src":2555},".NET Conf 2021 YouTube playlist.",[892,893],"/posts/images/w452021tips_dotnetconf_1.png",[],{"type":413,"tag":429,"props":2558,"children":2559},{},[2560],{"type":419,"value":1625},{"title":401,"searchDepth":490,"depth":490,"links":2562},[2563,2565,2566,2567,2568],{"id":2312,"depth":490,"text":2564},"Vue Devtools, a must-have browser extension when using Vue.js",{"id":2375,"depth":490,"text":2378},{"id":2436,"depth":490,"text":2439},{"id":2452,"depth":490,"text":2455},{"id":2531,"depth":490,"text":2534},"content:1.posts:28.w45-2021-tips-learned-this-week.md","1.posts/28.w45-2021-tips-learned-this-week.md",{"_path":49,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":48,"description":2572,"lead":2573,"date":2574,"image":2575,"badge":2576,"tags":2577,"body":2578,"_type":1638,"_id":2986,"_source":1640,"_file":2987,"_extension":1642},"This week I learned a few things related to versioning an application","Version in git tag with Azure Pipelines and in application insight logs.","2021-03-26T00:00:00.000Z",{"src":405},{"label":407},[272,241,278,281],{"type":410,"children":2579,"toc":2982},[2580,2584,2590,2603,2608,2630,2635,2717,2753,2766,2811,2823,2829,2842,2851,2856,2883,2974,2978],{"type":413,"tag":429,"props":2581,"children":2582},{},[2583],{"type":419,"value":2572},{"type":413,"tag":414,"props":2585,"children":2587},{"id":2586},"create-a-git-tag-from-an-azure-pipeline",[2588],{"type":419,"value":2589},"Create a git tag from an Azure Pipeline.",{"type":413,"tag":429,"props":2591,"children":2592},{},[2593,2595,2601],{"type":419,"value":2594},"Creating a git tag for your repository stored in Azure DevOps can be done quite easily by creating a tag in your local repository and pushing it to Azure DevOps or by simply manually creating it from the ",{"type":413,"tag":422,"props":2596,"children":2598},{"className":2597},[],[2599],{"type":419,"value":2600},"Tags",{"type":419,"value":2602}," page in Azure DevOps. So why bother creating a tag from an Azure Pipeline?",{"type":413,"tag":429,"props":2604,"children":2605},{},[2606],{"type":419,"value":2607},"Doing things manually is error-prone and takes time, so for repetitive tasks, it is a good idea to automate them. And Azure Pipelines are great at automating things especially when it is relative to building or deploying code. In my team what we wanted was to have our CI/CD pipeline compute in what version was the code we were building and automatically tag the commit built with that version.",{"type":413,"tag":429,"props":2609,"children":2610},{},[2611,2613,2620,2622,2629],{"type":419,"value":2612},"Computing the version in an azure pipeline is not the topic here, so let's just say there are multiple ways to do that like using ",{"type":413,"tag":902,"props":2614,"children":2617},{"href":2615,"rel":2616},"https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#counter",[906],[2618],{"type":419,"value":2619},"variables and the counter expression",{"type":419,"value":2621}," or using the ",{"type":413,"tag":902,"props":2623,"children":2626},{"href":2624,"rel":2625},"https://marketplace.visualstudio.com/items?itemName=gittools.gittools",[906],[2627],{"type":419,"value":2628},"gitversion task",{"type":419,"value":746},{"type":413,"tag":429,"props":2631,"children":2632},{},[2633],{"type":419,"value":2634},"Once you know the version you can use the git command line in a script task to create the tag and push it.",{"type":413,"tag":456,"props":2636,"children":2640},{"className":2637,"code":2638,"language":2639,"meta":401,"style":401},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","- script: |\n    git tag $(VersionPreviouslyComputed)\n    git push origin $(VersionPreviouslyComputed)\n  displayName: Tag version\n  workingDirectory: $(Build.SourcesDirectory)\n","yml",[2641],{"type":413,"tag":422,"props":2642,"children":2643},{"__ignoreMap":401},[2644,2667,2675,2683,2700],{"type":413,"tag":465,"props":2645,"children":2646},{"class":467,"line":468},[2647,2652,2657,2661],{"type":413,"tag":465,"props":2648,"children":2649},{"style":484},[2650],{"type":419,"value":2651},"-",{"type":413,"tag":465,"props":2653,"children":2654},{"style":499},[2655],{"type":419,"value":2656}," script",{"type":413,"tag":465,"props":2658,"children":2659},{"style":484},[2660],{"type":419,"value":558},{"type":413,"tag":465,"props":2662,"children":2664},{"style":2663},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF;--shiki-light-font-style:italic;--shiki-default-font-style:italic;--shiki-dark-font-style:italic",[2665],{"type":419,"value":2666}," |\n",{"type":413,"tag":465,"props":2668,"children":2669},{"class":467,"line":490},[2670],{"type":413,"tag":465,"props":2671,"children":2672},{"style":819},[2673],{"type":419,"value":2674},"    git tag $(VersionPreviouslyComputed)\n",{"type":413,"tag":465,"props":2676,"children":2677},{"class":467,"line":521},[2678],{"type":413,"tag":465,"props":2679,"children":2680},{"style":819},[2681],{"type":419,"value":2682},"    git push origin $(VersionPreviouslyComputed)\n",{"type":413,"tag":465,"props":2684,"children":2685},{"class":467,"line":531},[2686,2691,2695],{"type":413,"tag":465,"props":2687,"children":2688},{"style":499},[2689],{"type":419,"value":2690},"  displayName",{"type":413,"tag":465,"props":2692,"children":2693},{"style":484},[2694],{"type":419,"value":558},{"type":413,"tag":465,"props":2696,"children":2697},{"style":819},[2698],{"type":419,"value":2699}," Tag version\n",{"type":413,"tag":465,"props":2701,"children":2702},{"class":467,"line":575},[2703,2708,2712],{"type":413,"tag":465,"props":2704,"children":2705},{"style":499},[2706],{"type":419,"value":2707},"  workingDirectory",{"type":413,"tag":465,"props":2709,"children":2710},{"style":484},[2711],{"type":419,"value":558},{"type":413,"tag":465,"props":2713,"children":2714},{"style":819},[2715],{"type":419,"value":2716}," $(Build.SourcesDirectory)\n",{"type":413,"tag":429,"props":2718,"children":2719},{},[2720,2722,2728,2730,2736,2738,2744,2746,2752],{"type":419,"value":2721},"For this script to work, you have to ensure that the identity that executes your pipeline has the right to push a tag on your repository. Concretely you have to give the ",{"type":413,"tag":422,"props":2723,"children":2725},{"className":2724},[],[2726],{"type":419,"value":2727},"contribute",{"type":419,"value":2729}," permission to the ",{"type":413,"tag":2731,"props":2732,"children":2733},"strong",{},[2734],{"type":419,"value":2735},"user",{"type":419,"value":2737}," named ",{"type":413,"tag":422,"props":2739,"children":2741},{"className":2740},[],[2742],{"type":419,"value":2743},"Project Collection Build Service ({your organization})",{"type":419,"value":2745}," as described ",{"type":413,"tag":902,"props":2747,"children":2750},{"href":2748,"rel":2749},"https://docs.microsoft.com/en-us/azure/devops/pipelines/scripts/git-commands?view=azure-devops&tabs=yaml#grant-version-control-permissions-to-the-build-service",[906],[2751],{"type":419,"value":1800},{"type":419,"value":746},{"type":413,"tag":429,"props":2754,"children":2755},{},[2756,2758,2764],{"type":419,"value":2757},"Moreover, you need to add an extra checkout task at the beginning of your pipeline. By default, you don't have to add this task, pipelines automatically do a checkout. But in this case, you want to set to true the parameter ",{"type":413,"tag":422,"props":2759,"children":2761},{"className":2760},[],[2762],{"type":419,"value":2763},"persistsCredentials",{"type":419,"value":2765}," to reuse the same credentials used for the initial checkout in the following other git operations in your pipelines.",{"type":413,"tag":456,"props":2767,"children":2769},{"className":2637,"code":2768,"language":2639,"meta":401,"style":401},"- checkout: self\n  persistCredentials: true\n",[2770],{"type":413,"tag":422,"props":2771,"children":2772},{"__ignoreMap":401},[2773,2794],{"type":413,"tag":465,"props":2774,"children":2775},{"class":467,"line":468},[2776,2780,2785,2789],{"type":413,"tag":465,"props":2777,"children":2778},{"style":484},[2779],{"type":419,"value":2651},{"type":413,"tag":465,"props":2781,"children":2782},{"style":499},[2783],{"type":419,"value":2784}," checkout",{"type":413,"tag":465,"props":2786,"children":2787},{"style":484},[2788],{"type":419,"value":558},{"type":413,"tag":465,"props":2790,"children":2791},{"style":819},[2792],{"type":419,"value":2793}," self\n",{"type":413,"tag":465,"props":2795,"children":2796},{"class":467,"line":490},[2797,2802,2806],{"type":413,"tag":465,"props":2798,"children":2799},{"style":499},[2800],{"type":419,"value":2801},"  persistCredentials",{"type":413,"tag":465,"props":2803,"children":2804},{"style":484},[2805],{"type":419,"value":558},{"type":413,"tag":465,"props":2807,"children":2808},{"style":510},[2809],{"type":419,"value":2810}," true\n",{"type":413,"tag":429,"props":2812,"children":2813},{},[2814,2816,2822],{"type":419,"value":2815},"If you are not using a Microsoft-hosted agent but your own on-premise agent, you can have a problem when you delete a tag that was created by a pipeline. Indeed tags in the local repository of an on-premise agent are not automatically fetched and pruned so your following build can fail if it tries to create a tag that still exists locally (even if does not on the remote repository). To avoid that you can do add following command in your script ",{"type":413,"tag":422,"props":2817,"children":2819},{"className":2818},[],[2820],{"type":419,"value":2821},"git fetch origin refs/tags/*:refs/tags/* --prune",{"type":419,"value":746},{"type":413,"tag":414,"props":2824,"children":2826},{"id":2825},"application-version-in-logs-in-application-insights",[2827],{"type":419,"value":2828},"Application version in logs in Application Insights",{"type":413,"tag":429,"props":2830,"children":2831},{},[2832,2834,2840],{"type":419,"value":2833},"When developing applications in Azure, Application Insights is a key component to monitor these applications. But as for many components, we sometimes do not know how to use it to its full potential.\nThis week a colleague told me about a very basic feature that I did not know about: logs in Application Insights contain the version of the application that sends the logs. Indeed there is a property ",{"type":413,"tag":422,"props":2835,"children":2837},{"className":2836},[],[2838],{"type":419,"value":2839},"application_Version",{"type":419,"value":2841}," in each log with the version number of the application.",{"type":413,"tag":429,"props":2843,"children":2844},{},[2845],{"type":413,"tag":888,"props":2846,"children":2850},{"alt":2847,"className":2848,"src":2849},"Application Insights logs.",[892,893],"/posts/images/w122021tips_ai_1.png",[],{"type":413,"tag":429,"props":2852,"children":2853},{},[2854],{"type":419,"value":2855},"It might look not very interesting but it can be really useful to have that in order to filter logs to a specific version in Log Analytics queries.",{"type":413,"tag":429,"props":2857,"children":2858},{},[2859,2861,2867,2869,2874,2876,2881],{"type":419,"value":2860},"One thing to note though is that by default Application Insights sets the ",{"type":413,"tag":422,"props":2862,"children":2864},{"className":2863},[],[2865],{"type":419,"value":2866},"AssemblyVersion",{"type":419,"value":2868}," in the ",{"type":413,"tag":422,"props":2870,"children":2872},{"className":2871},[],[2873],{"type":419,"value":2839},{"type":419,"value":2875}," property. So if you keep that by default, do not forget to set the ",{"type":413,"tag":422,"props":2877,"children":2879},{"className":2878},[],[2880],{"type":419,"value":2866},{"type":419,"value":2882}," with the correct version number when you build the application code. In Azure Pipelines it can be done like that:",{"type":413,"tag":456,"props":2884,"children":2886},{"className":2637,"code":2885,"language":2639,"meta":401,"style":401},"- task: DotNetCoreCLI@2\n  displayName: Build\n  inputs:\n    command: build\n    arguments: -p:AssemblyVersion=$(VersionPreviouslyComputed)\n",[2887],{"type":413,"tag":422,"props":2888,"children":2889},{"__ignoreMap":401},[2890,2911,2927,2940,2957],{"type":413,"tag":465,"props":2891,"children":2892},{"class":467,"line":468},[2893,2897,2902,2906],{"type":413,"tag":465,"props":2894,"children":2895},{"style":484},[2896],{"type":419,"value":2651},{"type":413,"tag":465,"props":2898,"children":2899},{"style":499},[2900],{"type":419,"value":2901}," task",{"type":413,"tag":465,"props":2903,"children":2904},{"style":484},[2905],{"type":419,"value":558},{"type":413,"tag":465,"props":2907,"children":2908},{"style":819},[2909],{"type":419,"value":2910}," DotNetCoreCLI@2\n",{"type":413,"tag":465,"props":2912,"children":2913},{"class":467,"line":490},[2914,2918,2922],{"type":413,"tag":465,"props":2915,"children":2916},{"style":499},[2917],{"type":419,"value":2690},{"type":413,"tag":465,"props":2919,"children":2920},{"style":484},[2921],{"type":419,"value":558},{"type":413,"tag":465,"props":2923,"children":2924},{"style":819},[2925],{"type":419,"value":2926}," Build\n",{"type":413,"tag":465,"props":2928,"children":2929},{"class":467,"line":521},[2930,2935],{"type":413,"tag":465,"props":2931,"children":2932},{"style":499},[2933],{"type":419,"value":2934},"  inputs",{"type":413,"tag":465,"props":2936,"children":2937},{"style":484},[2938],{"type":419,"value":2939},":\n",{"type":413,"tag":465,"props":2941,"children":2942},{"class":467,"line":531},[2943,2948,2952],{"type":413,"tag":465,"props":2944,"children":2945},{"style":499},[2946],{"type":419,"value":2947},"    command",{"type":413,"tag":465,"props":2949,"children":2950},{"style":484},[2951],{"type":419,"value":558},{"type":413,"tag":465,"props":2953,"children":2954},{"style":819},[2955],{"type":419,"value":2956}," build\n",{"type":413,"tag":465,"props":2958,"children":2959},{"class":467,"line":575},[2960,2965,2969],{"type":413,"tag":465,"props":2961,"children":2962},{"style":499},[2963],{"type":419,"value":2964},"    arguments",{"type":413,"tag":465,"props":2966,"children":2967},{"style":484},[2968],{"type":419,"value":558},{"type":413,"tag":465,"props":2970,"children":2971},{"style":819},[2972],{"type":419,"value":2973}," -p:AssemblyVersion=$(VersionPreviouslyComputed)\n",{"type":413,"tag":429,"props":2975,"children":2976},{},[2977],{"type":419,"value":1625},{"type":413,"tag":1627,"props":2979,"children":2980},{},[2981],{"type":419,"value":1631},{"title":401,"searchDepth":490,"depth":490,"links":2983},[2984,2985],{"id":2586,"depth":490,"text":2589},{"id":2825,"depth":490,"text":2828},"content:1.posts:14.w12-2021-tips-learned-this-week.md","1.posts/14.w12-2021-tips-learned-this-week.md",{"_path":46,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":45,"description":2989,"lead":2990,"date":2991,"image":2992,"badge":2993,"tags":2994,"body":2995,"_type":1638,"_id":3202,"_source":1640,"_file":3203,"_extension":1642},"I often see developers talking on Twitter or Dev.to about things they have learned during the previous day or the previous week. I like the idea so I decided to write my first article about tips I learned during this past week. I am not intending to write an article like this every week but from time to time when I feel I have something interesting to share or that I want to keep track of for myself.","Windows Terminal startup actions, a git config setting for submodules, and a better IntelliSense for azure pipelines vscode extension.","2021-03-07T00:00:00.000Z",{"src":405},{"label":407},[272,241,206,275,278],{"type":410,"children":2996,"toc":3197},[2997,3001,3007,3012,3017,3061,3070,3076,3081,3102,3130,3142,3148,3162,3167,3176,3189,3193],{"type":413,"tag":429,"props":2998,"children":2999},{},[3000],{"type":419,"value":2989},{"type":413,"tag":414,"props":3002,"children":3004},{"id":3003},"start-windows-terminal-with-multiple-panes-thanks-to-startup-actions",[3005],{"type":419,"value":3006},"Start Windows Terminal with multiple panes thanks to startup actions.",{"type":413,"tag":429,"props":3008,"children":3009},{},[3010],{"type":419,"value":3011},"The new Windows Terminal has evolved a lot since its first release in preview in 2019. It now has a lot of nice features and it keeps getting better which is awesome. I was previously using Cmder but Windows Terminal has quickly become my default terminal.",{"type":413,"tag":429,"props":3013,"children":3014},{},[3015],{"type":419,"value":3016},"One of the latest releases of Windows Terminal allows specifying startup actions in your settings which is great if you want your terminal to open multiple panes or tabs with some specific profiles when the terminal starts. You can find below an example where I tell the terminal to open 3 panes vertically on 3 different locations using my PowerShell profile for each one. It is especially interesting when your daily work is about working on different git repositories.",{"type":413,"tag":456,"props":3018,"children":3022},{"className":3019,"code":3020,"language":3021,"meta":401,"style":401},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"startupActions\": \"new-tab -p PowerShell -d d:/dev/MyApi1; split-pane -p PowerShell -V -d d:/dev/MyApi2; split-pane -p PowerShell -V -d d:/dev/MyAzureFunctions\"\n","json",[3023],{"type":413,"tag":422,"props":3024,"children":3025},{"__ignoreMap":401},[3026],{"type":413,"tag":465,"props":3027,"children":3028},{"class":467,"line":468},[3029,3033,3038,3042,3047,3051,3056],{"type":413,"tag":465,"props":3030,"children":3031},{"style":484},[3032],{"type":419,"value":816},{"type":413,"tag":465,"props":3034,"children":3035},{"style":819},[3036],{"type":419,"value":3037},"startupActions",{"type":413,"tag":465,"props":3039,"children":3040},{"style":484},[3041],{"type":419,"value":816},{"type":413,"tag":465,"props":3043,"children":3044},{"style":588},[3045],{"type":419,"value":3046},": ",{"type":413,"tag":465,"props":3048,"children":3049},{"style":484},[3050],{"type":419,"value":816},{"type":413,"tag":465,"props":3052,"children":3053},{"style":819},[3054],{"type":419,"value":3055},"new-tab -p PowerShell -d d:/dev/MyApi1; split-pane -p PowerShell -V -d d:/dev/MyApi2; split-pane -p PowerShell -V -d d:/dev/MyAzureFunctions",{"type":413,"tag":465,"props":3057,"children":3058},{"style":484},[3059],{"type":419,"value":3060},"\"\n",{"type":413,"tag":429,"props":3062,"children":3063},{},[3064],{"type":413,"tag":888,"props":3065,"children":3069},{"alt":3066,"className":3067,"src":3068},"A Windows terminal split int 3 PowerShell tabs.",[892,893],"/posts/images/w092021tips_terminal_1.png",[],{"type":413,"tag":414,"props":3071,"children":3073},{"id":3072},"a-git-config-setting-to-make-working-with-submodule-easier",[3074],{"type":419,"value":3075},"A git config setting to make working with submodule easier.",{"type":413,"tag":429,"props":3077,"children":3078},{},[3079],{"type":419,"value":3080},"On the projects I am working on, we are using submodules to share some code between different components. NuGet packages are great to share code between different projects or applications but it is sometimes a bit complicated to handle when you simply want to share a few models and services between an API and an Azure Function for instance. In these situations, it is easier to use submodules for which you don't have to handle versioning (you just reference in your repository a commit or a branch of the submodule you want to use) nor set up source link (you can directly debug the code from the submodules in your project).",{"type":413,"tag":429,"props":3082,"children":3083},{},[3084,3086,3092,3094,3100],{"type":419,"value":3085},"However, one drawback of using submodules is that you have to learn and execute a few additional git commands to manipulate submodules. Typically when you do a ",{"type":413,"tag":422,"props":3087,"children":3089},{"className":3088},[],[3090],{"type":419,"value":3091},"git pull",{"type":419,"value":3093}," in your git repository, you have to do a ",{"type":413,"tag":422,"props":3095,"children":3097},{"className":3096},[],[3098],{"type":419,"value":3099},"git submodule update",{"type":419,"value":3101}," to update the submodules to their respective commit referenced in the \"super\" git repository. That is just one additional command but if you do that often it can quickly become boring 🥱.",{"type":413,"tag":429,"props":3103,"children":3104},{},[3105,3107,3113,3115,3120,3122,3129],{"type":419,"value":3106},"I never really look for a way to make that easier until this week where I discovered that you could pass the ",{"type":413,"tag":422,"props":3108,"children":3110},{"className":3109},[],[3111],{"type":419,"value":3112},"--recurse-submodules",{"type":419,"value":3114}," flag to a ",{"type":413,"tag":422,"props":3116,"children":3118},{"className":3117},[],[3119],{"type":419,"value":3091},{"type":419,"value":3121}," command to automate the process. It works for other commands as well as solving other similar inconveniences. And the best is that it is available as a setting to put in your git configuration. For more information have a look at ",{"type":413,"tag":902,"props":3123,"children":3126},{"href":3124,"rel":3125},"https://git-scm.com/book/en/v2/Git-Tools-Submodules",[906],[3127],{"type":419,"value":3128},"git documentation on the topic",{"type":419,"value":746},{"type":413,"tag":429,"props":3131,"children":3132},{},[3133,3135,3141],{"type":419,"value":3134},"So just execute the following command and be more productive with submodules 🐱‍🏍:\n",{"type":413,"tag":422,"props":3136,"children":3138},{"className":3137},[],[3139],{"type":419,"value":3140},"git config submodule.recurse true",{"type":419,"value":746},{"type":413,"tag":414,"props":3143,"children":3145},{"id":3144},"intellisense-for-azure-pipelines-custom-tasks-in-vscode",[3146],{"type":419,"value":3147},"IntelliSense for Azure Pipelines custom tasks in vscode.",{"type":413,"tag":429,"props":3149,"children":3150},{},[3151,3153,3160],{"type":419,"value":3152},"Azure Pipelines is an awesome CI/CD tool to automate your builds and deployments. The only problem when writing pipelines is that you have to write YAML  😿. I guess we just have to get used to writing YAML because it has become something used everywhere. Fortunately, there is a ",{"type":413,"tag":902,"props":3154,"children":3157},{"href":3155,"rel":3156},"https://marketplace.visualstudio.com/items?itemName=ms-azure-devops.azure-pipelines",[906],[3158],{"type":419,"value":3159},"vscode extension",{"type":419,"value":3161}," that helps writing Azure Pipelines files by providing syntax highlighting and autocompletion for Azure Pipelines YAML files in vscode.",{"type":413,"tag":429,"props":3163,"children":3164},{},[3165],{"type":419,"value":3166},"The extension validates the YAML files by using a generic YAML schema containing the in-box tasks of Azure Pipelines yet that means it is not able to validate tasks that come from extensions you installed in Azure DevOps. But here comes the good news: you can provide your custom schema to the extension so that the extension knows how to validate all the Azure Pipelines tasks available in your Azure DevOps organization. That is not really a tip because it is a well-documented feature of the extension, I just did not take the time to read the documentation to find out about it 😅.",{"type":413,"tag":429,"props":3168,"children":3169},{},[3170],{"type":413,"tag":888,"props":3171,"children":3175},{"alt":3172,"className":3173,"src":3174},"Documentation of the Azure Pipelines vscode extension about YAML schema.",[892,893],"/posts/images/w092021tips_vscodeextension_1.png",[],{"type":413,"tag":429,"props":3177,"children":3178},{},[3179,3181,3187],{"type":419,"value":3180},"As you can see in the documentation, you just have to download the custom schema of your DevOps organization which is located at this URL ",{"type":413,"tag":422,"props":3182,"children":3184},{"className":3183},[],[3185],{"type":419,"value":3186},"https://dev.azure.com/YOU-ORG-HERE/_apis/distributedtask/yamlschema",{"type":419,"value":3188},", reference it in you vs code workspace settings to make it work and enjoy IntelliSense on custom tasks.",{"type":413,"tag":429,"props":3190,"children":3191},{},[3192],{"type":419,"value":1625},{"type":413,"tag":1627,"props":3194,"children":3195},{},[3196],{"type":419,"value":1631},{"title":401,"searchDepth":490,"depth":490,"links":3198},[3199,3200,3201],{"id":3003,"depth":490,"text":3006},{"id":3072,"depth":490,"text":3075},{"id":3144,"depth":490,"text":3147},"content:1.posts:13.w09-2021-tips-learned-this-week.md","1.posts/13.w09-2021-tips-learned-this-week.md",{"_path":25,"_dir":399,"_draft":400,"_partial":400,"_locale":401,"title":24,"description":3205,"lead":3206,"date":3207,"image":3208,"badge":3210,"tags":3211,"body":3212,"_type":1638,"_id":3790,"_source":1640,"_file":3791,"_extension":1642},"When working on a git repository, I often have to manually delete old local branches that I don't use anymore. That's not a huge waste of time but still, that's something I have to do quite often so I decided to automate that.","Playing with Nushell to create a useful git alias to delete unused local git branches.","2020-04-06T00:00:00.000Z",{"src":3209},"/images/branches_1.jpg",{"label":407},[206,241,230,243],{"type":410,"children":3213,"toc":3784},[3214,3218,3224,3229,3242,3275,3280,3293,3299,3319,3324,3334,3355,3364,3377,3408,3414,3434,3443,3464,3473,3484,3493,3498,3677,3683,3702,3732,3753,3766,3775,3780],{"type":413,"tag":429,"props":3215,"children":3216},{},[3217],{"type":419,"value":3205},{"type":413,"tag":414,"props":3219,"children":3221},{"id":3220},"why-do-i-end-up-having-outdated-local-branches-on-my-git-repositories",[3222],{"type":419,"value":3223},"Why do I end up having outdated local branches on my git repositories?",{"type":413,"tag":429,"props":3225,"children":3226},{},[3227],{"type":419,"value":3228},"First, let's talk about how I end up having many useless local git branches. That's something quite usual and directly linked with the way I work with git but chances are that you are having the same issue.",{"type":413,"tag":429,"props":3230,"children":3231},{},[3232,3234,3240],{"type":419,"value":3233},"At work I am working in a small team of developers, we host our git repositories in ",{"type":413,"tag":902,"props":3235,"children":3238},{"href":3236,"rel":3237},"https://azure.microsoft.com/en-us/services/devops/repos/",[906],[3239],{"type":419,"value":343},{"type":419,"value":3241}," and we try to respect the following practices in our daily development:",{"type":413,"tag":3243,"props":3244,"children":3245},"ul",{},[3246,3252,3257],{"type":413,"tag":3247,"props":3248,"children":3249},"li",{},[3250],{"type":419,"value":3251},"having a main branch (master) on which nobody can commit directly",{"type":413,"tag":3247,"props":3253,"children":3254},{},[3255],{"type":419,"value":3256},"always create a short-lived branch (also called feature branch) when developing a new feature of the application",{"type":413,"tag":3247,"props":3258,"children":3259},{},[3260,3262],{"type":419,"value":3261},"only merge a feature branch on the main branch through an Azure DevOps pull request\n",{"type":413,"tag":3243,"props":3263,"children":3264},{},[3265,3270],{"type":413,"tag":3247,"props":3266,"children":3267},{},[3268],{"type":419,"value":3269},"the PR triggers a pipeline that ensures the code build correctly, follow some conventions (with a Sonar analysis for instance) and that unit tests pass",{"type":413,"tag":3247,"props":3271,"children":3272},{},[3273],{"type":419,"value":3274},"the PR can only be completed after a code review of at least one member of the team",{"type":413,"tag":429,"props":3276,"children":3277},{},[3278],{"type":419,"value":3279},"These practices allow us to keep good quality in our code base, not to mess with our git repositories, and ensure the main branch always builds.",{"type":413,"tag":429,"props":3281,"children":3282},{},[3283,3285,3291],{"type":419,"value":3284},"However, each week we are creating a lot of branches that need to be deleted as once merged we no longer need to have them. When a pull request is approved and we decide to complete it, Azure DevOps takes care of automatically merging the associated feature branch into master and deleting it from the repository. Once that's done, I can do a ",{"type":413,"tag":422,"props":3286,"children":3288},{"className":3287},[],[3289],{"type":419,"value":3290},"git fetch --prune",{"type":419,"value":3292}," on my laptop to have the feature branch removed from the remote of my local repository (by the way, I recommend you to directly set the fetch command to prune by default in your git config 👌). Nevertheless, this does not delete the local version of the feature branch thus our problem: over time if we do not think of deleting all these outdated branches, they become too many and we don't even know which branch should be kept or not.",{"type":413,"tag":414,"props":3294,"children":3296},{"id":3295},"git-commands-to-identify-and-delete-outdated-branches",[3297],{"type":419,"value":3298},"Git commands to identify and delete outdated branches.",{"type":413,"tag":429,"props":3300,"children":3301},{},[3302,3304,3309,3311,3317],{"type":419,"value":3303},"As my outdated branches are already removed from my remote (thanks to ",{"type":413,"tag":422,"props":3305,"children":3307},{"className":3306},[],[3308],{"type":419,"value":3290},{"type":419,"value":3310},") it should not be too complicated to use some git commands to guess which branches are not useful anymore. But as it's Azure DevOps that took care of merging them (sometimes with a squash) I cannot use the ",{"type":413,"tag":422,"props":3312,"children":3314},{"className":3313},[],[3315],{"type":419,"value":3316},"git branch --merged",{"type":419,"value":3318}," command.",{"type":413,"tag":429,"props":3320,"children":3321},{},[3322],{"type":419,"value":3323},"If I take my blog repository as an example I have a bunch of branches: some that could be useful (articles I have started to write but did not finish yet and I don't know if I will one day 😋) and some that are already merged into my master branch through a PR.",{"type":413,"tag":429,"props":3325,"children":3326},{},[3327],{"type":413,"tag":888,"props":3328,"children":3333},{"alt":3329,"className":3330,"src":3331,"width":3332},"List all git branches in the terminal.",[892,893],"/posts/images/cleaningbranches_shell_1.png",800,[],{"type":413,"tag":429,"props":3335,"children":3336},{},[3337,3339,3345,3347,3353],{"type":419,"value":3338},"The command ",{"type":413,"tag":422,"props":3340,"children":3342},{"className":3341},[],[3343],{"type":419,"value":3344},"git branch -vl",{"type":419,"value":3346}," (which lists in a verbose way the local git branches) gives us an interesting view as it shows the branches for which the remote has been deleted specifying a ",{"type":413,"tag":422,"props":3348,"children":3350},{"className":3349},[],[3351],{"type":419,"value":3352},"[gone]",{"type":419,"value":3354}," for them. These branches correspond to the outdated branches we want to delete.",{"type":413,"tag":429,"props":3356,"children":3357},{},[3358],{"type":413,"tag":888,"props":3359,"children":3363},{"alt":3360,"className":3361,"src":3362,"width":1697},"List all git branches with verbose tag in terminal.",[892,893],"/posts/images/cleaningbranches_shell_2.png",[],{"type":413,"tag":429,"props":3365,"children":3366},{},[3367,3369,3375],{"type":419,"value":3368},"We know how to identify the outdated branches but we need a command to delete them which is the ",{"type":413,"tag":422,"props":3370,"children":3372},{"className":3371},[],[3373],{"type":419,"value":3374},"git branch -D",{"type":419,"value":3376}," command. Now we only need a script to associate the output and input of these two commands to automate the deletion.",{"type":413,"tag":429,"props":3378,"children":3379},{},[3380,3382,3389,3391,3397,3399,3406],{"type":419,"value":3381},"You can find on Stackoverflow some posts like ",{"type":413,"tag":902,"props":3383,"children":3386},{"href":3384,"rel":3385},"https://stackoverflow.com/questions/7726949/remove-tracking-branches-no-longer-on-remote",[906],[3387],{"type":419,"value":3388},"this one",{"type":419,"value":3390}," that show different solutions using bash that work perfectly but I thought it would be interesting to try to script that using another shell. Indeed I recently started to use a shell called ",{"type":413,"tag":902,"props":3392,"children":3395},{"href":3393,"rel":3394},"https://github.com/nushell/nushell",[906],[3396],{"type":419,"value":243},{"type":419,"value":3398}," which is a pretty powerful yet simple cross-platform shell. It is still in preview at the time of writing but if you have not heard of it I suggest you read the ",{"type":413,"tag":902,"props":3400,"children":3403},{"href":3401,"rel":3402},"https://www.jonathanturner.org/2019/08/introducing-nushell.html",[906],[3404],{"type":419,"value":3405},"introduction post",{"type":419,"value":3407}," of Jonathan Turner.",{"type":413,"tag":414,"props":3409,"children":3411},{"id":3410},"lets-script-that-with-nushell",[3412],{"type":419,"value":3413},"Let's script that with nushell!",{"type":413,"tag":429,"props":3415,"children":3416},{},[3417,3419,3424,3426,3432],{"type":419,"value":3418},"Enough of talking, let's script.\nTo start with, we can use the nu lines command to create a table from the lines of the ",{"type":413,"tag":422,"props":3420,"children":3422},{"className":3421},[],[3423],{"type":419,"value":3344},{"type":419,"value":3425}," output (we added an extra ",{"type":413,"tag":422,"props":3427,"children":3429},{"className":3428},[],[3430],{"type":419,"value":3431},"*/*",{"type":419,"value":3433}," argument as we are only interested in posts branches).",{"type":413,"tag":429,"props":3435,"children":3436},{},[3437],{"type":413,"tag":888,"props":3438,"children":3442},{"alt":3439,"className":3440,"src":3441,"width":1697},"List git branches in table in the terminal.",[892,893],"/posts/images/cleaningbranches_shell_3.png",[],{"type":413,"tag":429,"props":3444,"children":3445},{},[3446,3448,3454,3456,3462],{"type":419,"value":3447},"Then we can split the different lines into columns that we can name with the ",{"type":413,"tag":422,"props":3449,"children":3451},{"className":3450},[],[3452],{"type":419,"value":3453},"split column",{"type":419,"value":3455}," command. We use spaces to correctly split a line and the option ",{"type":413,"tag":422,"props":3457,"children":3459},{"className":3458},[],[3460],{"type":419,"value":3461},"--collapse-empty",{"type":419,"value":3463}," to remove the empty columns.",{"type":413,"tag":429,"props":3465,"children":3466},{},[3467],{"type":413,"tag":888,"props":3468,"children":3472},{"alt":3469,"className":3470,"src":3471,"width":1697},"List git branches in table with columns by property in the terminal.",[892,893],"/posts/images/cleaningbranches_shell_4.png",[],{"type":413,"tag":429,"props":3474,"children":3475},{},[3476,3478,3483],{"type":419,"value":3477},"We then just have to filter the table to get only the lines with the Status ",{"type":413,"tag":422,"props":3479,"children":3481},{"className":3480},[],[3482],{"type":419,"value":3352},{"type":419,"value":746},{"type":413,"tag":429,"props":3485,"children":3486},{},[3487],{"type":413,"tag":888,"props":3488,"children":3492},{"alt":3489,"className":3490,"src":3491,"width":1697},"Filter on git branches gone in the terminal.",[892,893],"/posts/images/cleaningbranches_shell_5.png",[],{"type":413,"tag":429,"props":3494,"children":3495},{},[3496],{"type":419,"value":3497},"And the final script:",{"type":413,"tag":456,"props":3499,"children":3503},{"className":3500,"code":3501,"language":3502,"meta":401,"style":401},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git branch -vl '*/*' | lines | split column \" \" BranchName Hash Status --collapse-empty | where Status == '[gone]' | each { |it| git branch -D $it.BranchName }\n","bash",[3504],{"type":413,"tag":422,"props":3505,"children":3506},{"__ignoreMap":401},[3507],{"type":413,"tag":465,"props":3508,"children":3509},{"class":467,"line":468},[3510,3514,3519,3524,3529,3533,3538,3543,3548,3552,3557,3562,3567,3571,3576,3581,3586,3591,3595,3600,3604,3609,3613,3617,3621,3625,3630,3635,3639,3643,3648,3653,3657,3662,3667,3672],{"type":413,"tag":465,"props":3511,"children":3512},{"style":478},[3513],{"type":419,"value":241},{"type":413,"tag":465,"props":3515,"children":3516},{"style":819},[3517],{"type":419,"value":3518}," branch",{"type":413,"tag":465,"props":3520,"children":3521},{"style":819},[3522],{"type":419,"value":3523}," -vl",{"type":413,"tag":465,"props":3525,"children":3526},{"style":484},[3527],{"type":419,"value":3528}," '",{"type":413,"tag":465,"props":3530,"children":3531},{"style":819},[3532],{"type":419,"value":3431},{"type":413,"tag":465,"props":3534,"children":3535},{"style":484},[3536],{"type":419,"value":3537},"'",{"type":413,"tag":465,"props":3539,"children":3540},{"style":484},[3541],{"type":419,"value":3542}," |",{"type":413,"tag":465,"props":3544,"children":3545},{"style":478},[3546],{"type":419,"value":3547}," lines",{"type":413,"tag":465,"props":3549,"children":3550},{"style":484},[3551],{"type":419,"value":3542},{"type":413,"tag":465,"props":3553,"children":3554},{"style":478},[3555],{"type":419,"value":3556}," split",{"type":413,"tag":465,"props":3558,"children":3559},{"style":819},[3560],{"type":419,"value":3561}," column",{"type":413,"tag":465,"props":3563,"children":3564},{"style":484},[3565],{"type":419,"value":3566}," \"",{"type":413,"tag":465,"props":3568,"children":3569},{"style":484},[3570],{"type":419,"value":3566},{"type":413,"tag":465,"props":3572,"children":3573},{"style":819},[3574],{"type":419,"value":3575}," BranchName",{"type":413,"tag":465,"props":3577,"children":3578},{"style":819},[3579],{"type":419,"value":3580}," Hash",{"type":413,"tag":465,"props":3582,"children":3583},{"style":819},[3584],{"type":419,"value":3585}," Status",{"type":413,"tag":465,"props":3587,"children":3588},{"style":819},[3589],{"type":419,"value":3590}," --collapse-empty",{"type":413,"tag":465,"props":3592,"children":3593},{"style":484},[3594],{"type":419,"value":3542},{"type":413,"tag":465,"props":3596,"children":3597},{"style":478},[3598],{"type":419,"value":3599}," where",{"type":413,"tag":465,"props":3601,"children":3602},{"style":819},[3603],{"type":419,"value":3585},{"type":413,"tag":465,"props":3605,"children":3606},{"style":819},[3607],{"type":419,"value":3608}," ==",{"type":413,"tag":465,"props":3610,"children":3611},{"style":484},[3612],{"type":419,"value":3528},{"type":413,"tag":465,"props":3614,"children":3615},{"style":819},[3616],{"type":419,"value":3352},{"type":413,"tag":465,"props":3618,"children":3619},{"style":484},[3620],{"type":419,"value":3537},{"type":413,"tag":465,"props":3622,"children":3623},{"style":484},[3624],{"type":419,"value":3542},{"type":413,"tag":465,"props":3626,"children":3627},{"style":478},[3628],{"type":419,"value":3629}," each",{"type":413,"tag":465,"props":3631,"children":3632},{"style":819},[3633],{"type":419,"value":3634}," {",{"type":413,"tag":465,"props":3636,"children":3637},{"style":484},[3638],{"type":419,"value":3542},{"type":413,"tag":465,"props":3640,"children":3641},{"style":478},[3642],{"type":419,"value":268},{"type":413,"tag":465,"props":3644,"children":3645},{"style":484},[3646],{"type":419,"value":3647},"|",{"type":413,"tag":465,"props":3649,"children":3650},{"style":478},[3651],{"type":419,"value":3652}," git",{"type":413,"tag":465,"props":3654,"children":3655},{"style":819},[3656],{"type":419,"value":3518},{"type":413,"tag":465,"props":3658,"children":3659},{"style":819},[3660],{"type":419,"value":3661}," -D",{"type":413,"tag":465,"props":3663,"children":3664},{"style":588},[3665],{"type":419,"value":3666}," $it",{"type":413,"tag":465,"props":3668,"children":3669},{"style":819},[3670],{"type":419,"value":3671},".BranchName",{"type":413,"tag":465,"props":3673,"children":3674},{"style":819},[3675],{"type":419,"value":3676}," }\n",{"type":413,"tag":414,"props":3678,"children":3680},{"id":3679},"make-it-a-git-alias",[3681],{"type":419,"value":3682},"Make it a git alias.",{"type":413,"tag":429,"props":3684,"children":3685},{},[3686,3688,3694,3696,3701],{"type":419,"value":3687},"We can integrate this script into our git commands by creating a git alias. Let's say I want to create the alias ",{"type":413,"tag":422,"props":3689,"children":3691},{"className":3690},[],[3692],{"type":419,"value":3693},"bcl",{"type":419,"value":3695}," for branch clean up, we only need to add the following to our ",{"type":413,"tag":422,"props":3697,"children":3699},{"className":3698},[],[3700],{"type":419,"value":1584},{"type":419,"value":558},{"type":413,"tag":456,"props":3703,"children":3705},{"className":1588,"code":3704,"language":1590,"meta":401,"style":401},"[alias]\n    bcl = !nu \\\"D:\\\\gitalias_bcl.nu\\\"\n",[3706],{"type":413,"tag":422,"props":3707,"children":3708},{"__ignoreMap":401},[3709,3724],{"type":413,"tag":465,"props":3710,"children":3711},{"class":467,"line":468},[3712,3716,3720],{"type":413,"tag":465,"props":3713,"children":3714},{"style":484},[3715],{"type":419,"value":1602},{"type":413,"tag":465,"props":3717,"children":3718},{"style":819},[3719],{"type":419,"value":1607},{"type":413,"tag":465,"props":3721,"children":3722},{"style":484},[3723],{"type":419,"value":1612},{"type":413,"tag":465,"props":3725,"children":3726},{"class":467,"line":490},[3727],{"type":413,"tag":465,"props":3728,"children":3729},{"style":819},[3730],{"type":419,"value":3731},"    bcl = !nu \\\"D:\\\\gitalias_bcl.nu\\\"\n",{"type":413,"tag":429,"props":3733,"children":3734},{},[3735,3737,3743,3745,3751],{"type":419,"value":3736},"where ",{"type":413,"tag":422,"props":3738,"children":3740},{"className":3739},[],[3741],{"type":419,"value":3742},"gitalias_bcl.nu",{"type":419,"value":3744}," is the nu script file we created earlier (it's located here in the ",{"type":413,"tag":422,"props":3746,"children":3748},{"className":3747},[],[3749],{"type":419,"value":3750},"D://",{"type":419,"value":3752}," drive but can be created anywhere).",{"type":413,"tag":429,"props":3754,"children":3755},{},[3756,3758,3764],{"type":419,"value":3757},"Now we can simply do a ",{"type":413,"tag":422,"props":3759,"children":3761},{"className":3760},[],[3762],{"type":419,"value":3763},"git bcl",{"type":419,"value":3765}," to clean our outdated local git branches.",{"type":413,"tag":429,"props":3767,"children":3768},{},[3769],{"type":413,"tag":888,"props":3770,"children":3774},{"alt":3771,"className":3772,"src":3773,"width":3332},"List oudated git branches  in the terminal.",[892,893],"/posts/images/cleaningbranches_shell_6.png",[],{"type":413,"tag":429,"props":3776,"children":3777},{},[3778],{"type":419,"value":3779},"That's it, nothing revolutionary but that was the opportunity to automate the boring task of deleting outdated local branches while playing with nushell.",{"type":413,"tag":1627,"props":3781,"children":3782},{},[3783],{"type":419,"value":1631},{"title":401,"searchDepth":490,"depth":490,"links":3785},[3786,3787,3788,3789],{"id":3220,"depth":490,"text":3223},{"id":3295,"depth":490,"text":3298},{"id":3410,"depth":490,"text":3413},{"id":3679,"depth":490,"text":3682},"content:1.posts:6.cleaning-git-branches.md","1.posts/6.cleaning-git-branches.md",1716749600623]