Salesforce, Python, SQL, & other ways to put your data where you need it

Need event music? 🎸

Live and recorded jazz, pop, and meditative music for your virtual conference / Zoom wedding / yoga class / private party with quality sound and a smooth technical experience

Deploying a built webapp onto Azure App Service with ADO Release Pipelines

18 Mar 2023 🔖 web development minimum viable build beginner devops git azure
💬 EN

Table of Contents

In this series, we’ve:

  1. Coded a tiny webserver.
  2. Added unit tests.
  3. Git-tracked our codebase in Azure DevOps (“ADO”) Repos and set up proper editing hygiene rules.
  4. Taught ADO Pipelines to “build” our codebase into a ready-to-run webserver runtime codebase every time Git detects we’ve edited the codebase.
  5. Told ADO Pipelines not to bother doing so if our unit tests fail.

All that’s left is to let the world see our amazing website! Let’s do that today.

See the sample codebase on GitHub.

To prepare, we used Azure PowerShell or the Azure CLI to:

  1. Organize exactly where in Azure our webservers will live (“Resource Group”).
  2. Rent nonproduction and production webservers from Azure.
  3. Set up an Azure Active Directory (“AAD”) identity (“Application Registration” + “Service Principal”) that’s allowed (“RBAC Role Assignment”) to manipulate the Azure webservers we rented.
  4. Told ADO how to log into Azure (“Service Connection”) using that AAD identity.

Prerequisites

  1. Have an account in Azure and Azure DevOps. You can get one:
  2. Make sure you’ve set up an “organization” and “project” in ADO (steps 1-5 of the next section of this article walk you through creating an organization and project).
  3. Create/find an Azure resource group (I called mine “my-hello-web-rg“), rent nonproduction and production webservers from Azure (I called mine “my-first-webapp-nonprod” and “my-first-webapp-prod” inside “my-first-app-service-plan“), set up AAD and RBAC, and tell ADO how to use AAD+RBAC (I called mine “my-first-service-connection“).
  4. Preferably, you’d have worked through – or at least read and looked at the sample codebases for – the tiny local webserver, local unit tests, ADO Git-editing hygiene, ADO “build” CI/CD pipeline, and ADO “test+build” CI/CD pipeline exercises before beginning this one. It’s not strictly necessary, but it’ll lay a great foundation for understanding.

Visit your placeholder websites

Before we get started, let’s take a baseline and double-check that while we correctly rented 2 webservers, there’s nothing on the live sites but placeholder content from Microsoft Azure.

  1. In a web browser, visit something along the lines of https://my-first-webapp-nonprod.azurewebsites.net – changing “my-first-webapp-nonprod” to whatever name you chose for the non-production webhost you rented from Azure.
    • If this is the first time anyone has ever visited this URL, it may take a minute or two to respond.
  2. Note that the website greets you with Microsoft Azure’s logo and says, “Your web app is running and waiting for your content.”
  3. Repeat for your the production website you rented (mine is “my-first-webapp-prod“), and note that it also gives you a placeholder message from Azure saying you haven’t yet put any content on your web site.

Importing my sample codebase into ADO Repos

  1. Log into Azure.
  2. Click into “Azure DevOps Organizations” from the Azure home screen.
  3. Click “My Azure DevOps Organizations.”
  4. Click into an ADO Organization you created earlier, or click the “Create new organization” button if you don’t have any yet.
    • You should be taken to a website like https://dev.azure.com/YOUR-ADO-ORG-NAME/.
  5. Click into an ADO Project you created earlier, or click the “New project” button if you don’t have any yet.
    • You should be taken to a website like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/.
  6. In the left-hand navigation, click on “Repos.”
    • Alternatively, visit a URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_code/, making appropriate org & project name substitutions.
  7. Up at the top, where the navigation breadcrumb says something like “YOUR-ADO-ORG-NAME / YOUR-ADO-PROJECT-NAME / Repos / Files / SOME-REPOSITORY-NAME, click SOME-REPOSITORY-NAME to expose a dropdown picklist letting you choose a different repository or create a new one.
  8. Click “Import repository.” In the flyout panel at right:
    • Set “Repository type” to “Git.”
    • Set “Clone URL” to “https://github.com/kkgthb/web-site-nodejs-04-ado-tests.git.”
    • Set “Name” to whatever you’d like to name your new repository.
    • Click the “Import button in the bottom right corner of the flyout panel.
  9. This would be a great time to protect the main branch of your new repository from direct edits, forcing you to use new branches and pull requests instead.

Telling Azure Pipelines to build a runtime when code changes

Tip: If you want to actually understand why I’m having you do these steps, read the “Making Azure DevOps Pipelines build a Hello World webapp from Git-tracked source code changes” article from earlier in this series.

  1. In the left-hand navigation of Azure DevOps, click on “Pipelines.”
  2. Beneath that, click “Pipelines.”
    • (It takes you to a URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_build.)
  3. Click “New Pipeline(upper right) if it’s not your first, or “Create Pipeline(center) if it is your first pipeline.
  4. Select the “Azure Repos Git” option.
  5. Enter the name of the repository you created when you imported a copy of my codebase.
  6. Select the “Existing Azure Pipelines YAML file” option.
  7. Set the “Path” to “/cicd/my-azure-build-pipeline.yml” by choosing it from the dropdown picklist.
  8. Click “Continue.”
  9. In the upper right corner above the YAML editor, click the “Run” button.
    • (It takes you to a URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_build/results?buildId=SOME-NUMBER&view=results.)
  10. In the subsection of the page titled “Jobs,” wait for the most recent job changes status from “Running” to “Success.”

Telling Azure Pipelines when and how to deploy our runtime to websites

Create a new “classic” (non-YAML) release pipeline

  1. In the left-hand navigation of Azure DevOps, click on “Pipelines.”
  2. Beneath that, click “Releases.”
    • (It takes you to a URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_release.)
  3. Click “New pipeline.”.
  4. Close the flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.
  5. Up toward the top of the screen, center-left, just to the right of “All Pipelines > New release pipeline,” hover over “New release pipeline” and click it to make it editable. Backspace it out and type something like “My First Release Pipeline” instead.

Trigger releases upon artifact build

  1. Toward the left side of the flowchart, in the box labeled “Artifacts,” click the “Add” button.
  2. In the box labeled “Source (build pipeline)” in the right-side flyout pane, use the picklist to click the pipeline you just created. By default, the pipeline is named the same as the repository you created when you imported my sample code.
  3. Leave “Default version” at “Latest.”
  4. Change “Source alias” to “MyBuiltWebsite.”
    • Hit Tab or click in the whitespace in the right-side flyout pane to make extra sure that your web browser logs the new text you typed into “Source alias.”
  5. Click the “Add” button toward the bottom of the right-side flyout pane.
  6. In the upper-right corner of the smaller box inside the “Artifacts” box on your flowchart that’s labeled “MyBuiltWebsite,” click the lightning bolt in a circle icon (hover-tooltip: “Continuous deployment trigger”).
  7. In the right-side flyout pane, click the toggle under “Continuous deployment” trigger to enable it.
    • (Leave the toggle under “Pull request trigger” disabled.)
  8. Close the flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.

Add a nonproduction release stage

  1. Toward the center of the flowchart, in the box labeled “Stages,” click the “Add” button and then “New stage” in its dropdown.
  2. In the right-side flyout pane, select the “Deploy a Node.js app to Azure App Service” option and click the “Apply” button that appears to the right of it when you hover over or click on it.
  3. Change “Stage name” to something meaningful. I’m going to name mine “nonprod-release.”
  4. Close the flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.

Configure your nonproduction release stage

  1. In the smaller box inside the “Stages” box on your flowchart that’s labeled “nonprod-release(or whatever you named your stage), click the link labeled “1 job, 1 task.”
  2. In the box labeled “Azure subscription” in the right-side pane, use the picklist to select the ADO Service Connection you set up as a prerequisite to this article. I found mine labeled “my-first-service-connection” beneath a label of “Available Azure service connections.”
  3. Change “App type” to “Web App on Linux.”
  4. Change “App service name” to the name of your non-production webapp host you rented form Azure. I named mine “my-first-webapp-nonprod.”
  5. In “Startup command,” enter “node ./server.js”.
  6. At left, click the “Run on agent step of the tasks beneath “nonprod-release” to change the right-side data entry pane to different settings.
  7. In the right-side pane, change “Agent pool” to “Azure Pipelines” and then in the “Agent Specification” box that appears below it, choose “ubuntu-latest.”
  8. At left, click the “Deploy Azure App Service step of the tasks beneath “nonprod-release” to change the right-side data entry pane to different settings.
  9. In the right-side pane, change “Package or folder” to “$(System.DefaultWorkingDirectory)/MyBuiltWebsite/MyBuiltWebsite”.
  10. Change “Runtime Stack” to “18 LTS (NODE|18-lts).”
  11. Click the “Save” button toward the upper-right corner of the screen to save the work you’ve done on your pipeline thus far.
  12. Leave “Folder” as “\” and click “OK” in the “Save” popup.

Add a production release stage

  1. Toward the left side of the flowchart, in the box labeled “Artifacts,” click the smaller box labeled “MyBuiltWebsite.” You don’t have to edit it – we just want to make sure that our “nonprod-release stage isn’t the actively selected box for our next step.
  2. Toward the center of the flowchart, in the box labeled “Stages,” click the “Add” button and then “New stage” in its dropdown.
  3. In the right-side flyout pane, select the “Deploy a Node.js app to Azure App Service” option and click the “Apply” button that appears to the right of it when you hover over or click on it.
  4. Change “Stage name” to something meaningful. I’m going to name mine “prod-release.”
  5. Close the flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.

Do special production-release-only stage configuration

  1. Along the left-hand edge of the smaller box inside the “Stages” box on your flowchart that’s labeled “prod-release(or whatever you named your second stage), click the oval icon consisting of a lightning bolt above a person (hover-tooltip: “Pre-deployment conditions”).
  2. In the right-side flyout pane labeled “Pre-deployment conditions,” expand the “Triggers” section of the pane.
  3. Change “Select trigger” from the “After release” option to the Manual only option.
  4. Below that, click the toggle to the right of “Pre-deployment approvals” trigger to enable it.
    • (Leave the toggle by “Gates” disabled.)
  5. Search for yourself and click yourself to add yourself as an approver.
    • (In an enterprise setting, of course, you could have a totally different set of approvers, and it may even be an Azure Active Directory group of people, not a bunch of individuals’ names.)
  6. Close the flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.

Configure your production release stage

  1. In the smaller box inside the “Stages” box on your flowchart that’s labeled “prod-release(or whatever you named your second stage), click the link labeled “1 job, 1 task.”
  2. Continue with all the remaining steps you followed since “1 job, 1 task” for nonproduction above under “configure your nonproduction release stage,” only make sure that when you change “App service name,” this time you choose the name of your production webapp host you rented form Azure.
    • I named mine “my-first-webapp-prod.”
  3. After you finish up with the “Runtime Stack” step, be sure to click the “Save” button toward the upper-right corner of the screen to save the work you’ve done on your pipeline thus far.

Running the build and nonproduction release pipelines by editing code

  1. In the left-hand navigation of Azure DevOps, click on “Repos” and then “Files.” Click on the README.md file and click the “Edit” button in the upper-right corner above the file’s contents.
  2. Add some text anywhere in the readme, just so you’ll have changed something.
  3. Click the “Commit” button in the upper-right corner above the file editor panel.
  4. In the flyout panel at right:
    • Change “Branch name” from “main” to “small-branch.”
    • Check the box next to “Create a pull request.”
    • Click the “Commit” button in the lower-right corner.
  5. In the “New pull request” page, edit the Title and Description if you’d like and click the “Create” button at bottom-right. (Note: the “new pull request” page will live at some URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME/pullrequestcreate?sourceRef=small-branch&targetRef=main&sourceRepositoryId=SOME-BIG-HEXIDECIMAL-NUMBER&targetRepositoryId=SOME-BIG-HEXIDECIMAL-NUMBER.)
  6. In the page titled after the “Title” you chose for the pull request, toward the upper-right, click the “Approve” button. (Note: the “pull request” will get its own URL like https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME/pullrequest/SOME-INTEGER.)
  7. Once you’ve done so, you should be able to click a “Complete” button next to “Approve.” Click it.
  8. In the flyout panel at right, leave the settings as they are (including deleting the “small-branch” branch after merging) and click the “Complete merge” button at the bottom-right.
  9. You’ll stay on the pull request page but see a green “Completed” tag in the upper left under its title.
  10. Go back to look at your README (https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME?path=/README.md) and note that your changes are in the “main” branch’s copy of the README.

Validating the automated pipelines ran correctly

  1. In the left-hand navigation of Azure DevOps, click on “Pipelines.”
  2. Beneath that, click “Pipelines.”
  3. In the “Recent” tab titled “Recently run pipelines,” you should see an entry, at the top of the list, from just a few minutes ago, likely named after your repository. Wait for the icon at the left of it to change from a blue spinning circle with a hover-tooltip of “Running” to a green checkmark circle with a hover-tooltip of “Success.”
  4. In the left-hand navigation of Azure DevOps, beneath “Pipelines,” click on “Releases.”
  5. In the list of pipelines, “My First Release Pipeline should have small text beneath it saying “nonprod-release(or whatever you named your first stage).
    • nonprod-release” will have a small spinning blue circle to the left of it while it runs, and a green checkmark circle to the left of it when it is finished.
    • Especially for your very first deploy to a webserver host that’s never had anything to deployed to it, a “release” stage can take quite a while, even with a very small application like this sample codebase. While writing this article, I waited 8 minutes for the “nonprod-release” stage of my release pipeline to run.
  6. At right, in the pane titled “My First Release Pipeline,” there should be a list of releases. Likely starting with “Release-1” at the bottom and sequentially numbered with more recent releases (that have bigger numbers) toward the top.
    • The topmost release in that list should have 2 icons under its “Stages” column – a “nonprod-release” icon and a “prod-release” icon (or whatever you named your stages).
      • The “nonprod-release” icon will be blue, have a spinning circle, and have a hover tooltip of “nonprod-release In progress” while the first stage of your release pipeline runs. Once it is finished, the color will change to green, circle icon will change to a checkmark, and hover tooltip will change to “nonprod-release Succeeded.”
      • The “prod-release” icon will be somewhat grayed out.
  7. (Note: If you click on the numbered release, you see more flowchart-looking logs. If you click on the “nonprod-release” icon, you see more technical-looking logs. But you don’t have to click on either, just yet.)

Visit your nonproduction website

  1. After “nonprod-release” has succeeded, in a web browser, visit something along the lines of https://my-first-webapp-nonprod.azurewebsites.net – changing “my-first-webapp-nonprod” to whatever name you chose for the non-production webhost you rented from Azure.
    • If this is the first time you have ever released / deployed content to this URL, it could take a moment for the content to change from Azure’s placeholder page to your own content.
    • If this is the first time you have ever visited this URL since releasing/deploying a round of content to it, the page could take a few seconds longer to load than you’d expect for such a tiny website.
  2. Take a look in the upper-left corner of the webpage you just visited: it should say “Hello World!

Running the production release pipeline manually

If you’re unhappy with the way your website looks on the nonproduction server, there’s no reason to bother releasing that codebase’s “built” artifact onto your production server.

Just ignore all of the “prod-release” buttons in the various “Releases” of My First Release Pipeline and keep editing your codebase (letting the “build” pipeline and the “nonproduction release” pipeline stage auto-run after each completed pull request or edit into the main branch of your Git repository) until there’s a release whose “nonprod-release” results you’re actually happy with when you visit the live nonproduction website.

  1. In the left-hand navigation of Azure DevOps, click on “Pipelines.”
  2. Beneath that, click “Releases.”
  3. In the list of pipelines, click “My First Release Pipeline to make sure it is exposed in the right-hand pane.
  4. At right, in the pane titled “My First Release Pipeline,” there should be a list of releases. Likely starting with “Release-1” at the bottom and sequentially numbered with more recent releases (that have bigger numbers) toward the top.
  5. From this list, find the most recent release with a successfully completed “nonprod-release” stage (see the far-right buttons under the “Stages” column of each release).
    • Hint: Although all releases with a successfully completed “nonprod-release” stage will have a green checkmark circle icon inside their button, only the one that is currently deployed onto your nonproduction webserver will be filled in with green (rather than white) and highlighted with a dark-green outline (rather than a gray outline) and have high-contrast text (rather than grayed-out text).
  6. Click the grayed-out “prod-release” icon immediately to the right of the intense-green “nonprod-release” icon you just found.
  7. In the list of tabs and buttons toward the top of the page below a navigational breadcrumb reading something like “My First Release Pipeline > Release-SOMENUMBER > prod-release,” click the “Deploy” button.
  8. In the flyout pane at right, click the “Deploy” button.
    • Before you do so, if you’d like, you could do things like make a comment about why you are happy with this release, or you could explore the flyout pane’s “Commits” tab to make sure you’re deploying a build from the codebase you think you’re deploying from.
  9. A blue clock icon should appear before the words “Pending approval” to the right of the navigational breadcrumb toward the top of the page. Within about 30 seconds, the main area of your browser should fill in with a note at left saying “Pre-deployment approvals” and an option at right reading “Pre-deployment” + “Approval pending,” with an “Approve” button at the far-right side of the screen.
  10. Click that “Approve” button.
  11. In the flyout pane at right, click the “Approve” button.
    • Before you do so, if you’d like, you could do things like make a second comment about why you are happy with this release and think it’s worthy of living on your production webserver.
  12. Close the approvals flyout pane on the right-hand side of the page by clicking its little “X” in the upper-right corner or by hitting Escape on your keyboard.
  13. Replacing the blue clock, a blue spinning circle icon should appear before the words “In progress” to the right of the navigational breadcrumb toward the top of the page.

Validating the manual pipeline ran correctly

  1. When your built codebase has deployed onto your production website (the very first deploy I ever did to my production website took 3 minutes to deploy), a green checkmark icon should replace the blue spinning circle icon and appear before the words “Succeeded” to the right of the navigational breadcrumb toward the top of the page.

Visit your production website

  1. In a web browser, visit something along the lines of https://my-first-webapp-prod.azurewebsites.net – changing “my-first-webapp-prod” to whatever name you chose for the production webhost you rented from Azure.
    • Note: If this is the first time you have ever released / deployed content to this URL, it could take a moment for the content to change from Azure’s placeholder page to your own content.
    • If this is the first time you have ever visited this URL since releasing/deploying a round of content to it, the page could take a few seconds longer to load than you’d expect for such a tiny website.
  2. Take a look in the upper-left corner of the webpage you just visited: it should say “Hello World!

Caution about old releases

When you are in the list of all “releases” for “My First Release Pipeline,” there’s not much keeping you from accidentally clicking one of the nonproduction or production icons under the “Status” column from an old release and deploying it to a nonproduction or production webserver again.

This is a blessing, because in a real-world setting, it also means it’s very easy to intentionally roll back to an older release when something you thought was doing to behave correctly doesn’t actually behave correctly.

But watch your step!


Build and release pipeline best practices

People can argue for days about the best way to build Azure DevOps pipelines for “building” codebases into webserver runtimes and for “releasing” / “deploying” them onto actual webservers.

The instructions I had you follow today, and back when we made a “build” pipeline, were pretty decent setups for learning from.

There are many choices one can make about whether to use ADO’s “YAML” pipelines all the way through or whether to use ADO’s or “classic” (point-and-click) pipelines for “releases.” (Frustratingly, at the time of writing this article, you don’t get a separate “Releases” management area in the ADO portal if you try to release with YAML pipelines.)

There are many choices about how exactly to make rules about when to let pipelines run (some architectures build out a runtime every commit to every branch with an open pull request into a branch like “main” and some even deploy those runtimes to very-short-lived webservers, rather than waiting to deploy code already merged into “main” onto a long-lived nonproduction webserver), what kinds of colleague-review processes to build out to slow things down (for example, I decided I’d only auto-deploy to a nonproduction webserver and leave production deploys manual – but large Silicon Valley companies have much more automated deployment-to-production processes), which ADO Pipelines options & tricks to use to implement such “slow down” processes, etc.

Building a pipeline that works well for your team is as complicated as writing software that works well for your team. Lots of choices can be “best practices” if they’re the best solution for your needs, although some fundamentals (like branch-protecting the main branch of your codebase and requiring all edits to it do be done by “pull review”) are always “good practice.”

Furthermore, I didn’t even touch on the concept that “deploying a built runtime into production isn’t the same as releasing the features therein, so deploying things to production doesn’t actually have to be intimidating” – there’s a whole world of “feature flags” down that rabbit hole.

Hopefully this was a great way to get started, hands-on, with your very first codebase-to-server CI/CD build + test + release/deploy pipeline in Azure DevOps!

Thanks for joining in, and let me know in the comments if you have questions or feedback.


Posts in this series

--- ---