diff --git a/docs/architecture/devops-for-aspnet-developers/actions-build.md b/docs/architecture/devops-for-aspnet-developers/actions-build.md new file mode 100644 index 0000000000000..cd6eb2b82124d --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/actions-build.md @@ -0,0 +1,205 @@ +--- +title: DevOps with .NET and GitHub Actions - Build a .NET Web App +description: Start your journey of DevOps with .NET and GitHub Actions by building a .NET web app +author: colindembovsky +ms.date: 03/04/2021 +--- +# Build a .NET web app using GitHub Actions + +[GitHub Actions](https://github.com/features/actions) allow you to automate workflows in response to events that are triggered in GitHub. A common workflow is Continuous Integration (CI), but Actions can automate other processes. For example, sending welcome emails when people join a repository. + +To explore moving code to the cloud, you'll build a GitHub Actions workflow file. The workflow file will be used for the Simple Feed Reader app you've already deployed to Azure App Service. + +In this article, you will: +> [!div class="checklist"] +> +> * Learn the basic structure of a GitHub Action workflow YAML file. +> * Use a template to create a basic build workflow that builds the .NET app and executes unit tests. +> * Publish the compiled app so that it's ready for deployment. + +## Workflow structure + +Workflows are defined in YAML files, and contain several common nodes: + +- a `name` +- a trigger, defined by an `on` section +- one or more `job` sections composed of one or more `steps` +- optional attributes such as `environment` variables + +Jobs are run on *runners*. You can use *hosted runners*, which are spun up by GitHub during the workflow and then thrown away. Hosted runners are great because you don't have to maintain your own build infrastructure. For workflows that require a specific build environment, or for running workflows on a private network, you can also use *private* runners. To create a private runner, install the runner on any machine that supports .NET. + +Each `job` will specify what runner GitHub should use to execute the `steps`. You can also specify dependencies between jobs using the `needs` attribute. Deployment jobs can also specify an `environment` to target. + +The `steps` node can be as easy as inline commands, or they can be actions. Most CI workflows will have a combination of `run` steps (for executing scripts) and actions. Individual actions are pulled into the workflow by referencing the GitHub Action repository (and optionally a tag or commit hash for specific versions) and specifying any parameters using the `with` keyword. + +> [!TIP] +> For more information, see [GitHub Actions YAML syntax](https://docs.github.com/actions/reference/workflow-syntax-for-github-actions). + +## Create a basic build workflow + +A primary principle of effective DevOps is to "build once, and deploy many times". You'll start by creating a workflow to build a basic .NET app. In the next step, you'll publish the output to prepare for deployment. + +1. Navigate to your GitHub repository and select the **Actions** tab. +1. GitHub detects that there's .NET code in the repository and suggests a .NET workflow template. Select **Set up this workflow** to create a new YAML workflow file: + + ![Creating a new workflow](./media/actions/build/new-action.jpg) + + **Figure 1**: Creating a new workflow. + +1. Commit the file onto the `main` branch. Since you've defined a trigger condition for *commits to main*, this commit should trigger the workflow to run. + + ![Commit the YAML file](./media/actions/build/commit-workflow.jpg) + + **Figure 2**: Commit the YAML file. + +1. Select the **Actions** tab again. You should see a running workflow. Once the workflow has completed, you should see a successful run. + + ![Successful build view](./media/actions/build/build-action-success.jpg) + + **Figure 3**: Successful build view. + +1. Opening the logs, you can see that the .NET build succeeded and the tests ran and passed. + + ![Checking the logs](./media/actions/build/build-action-success-logs.jpg) + + **Figure 4**: Checking the logs. + +> [!NOTE] +> If any of the tests fail, the workflow will fail. + +## Dissect the workflow file + +Let's examine the workflow YAML file you have so far: + +```yml +name: .NET + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal +``` + +Notice the following things: + +1. There's a `name` that names the workflow. +1. The `on` object specifies when this workflow should run. This workflow has two events that trigger it: `push` to `main` and `pull_request` to `main`. Each time someone commits to `main` or creates a pull request (PR) to `main`, this workflow will execute. +1. There's a single `job` called `build`. This build should run on a hosted agent. `ubuntu_latest` specifies the most recent Ubuntu hosted agent. +1. There are five steps: + 1. `actions/checkout@v2` is an action that checks out the code in the repository onto the runner. + 1. `actions/setup-dotnet@v1` is an action that sets up the .NET CLI. This step also specifies a `name` attribute for the logs and the `dotnet-version` parameter within the `with` object. + 1. Three `run` steps that execute `dotnet restore`, `dotnet build`, and `dotnet test`. `name` attributes are also specified for these `run` steps to make the logs look pretty. + +## Publish the output + +Now that you've successfully built and tested the code, add steps that publish the output so you can deploy the web app. + +1. Navigate to the *.github/workflows/dotnet.yml* file and select the pencil icon to edit it. + + ![Edit the YAML file](./media/actions/build/click-edit.jpg) + + **Figure 5**: Edit the YAML file. + +1. Add the following `Publish` step below the `Test` step. The step runs the `dotnet publish` command to publish the web app: + + ```yml + - name: Test + run: dotnet test --no-build --verbosity normal # <-- this is the current bottom line + + - name: Publish + run: dotnet publish SimpleFeedReader/SimpleFeedReader.csproj -c Release -o website + ``` + +1. This publishes the web app to a folder on the hosted agent. Now you'll want to *upload* the site as a build artifact that can be deployed to Azure. To complete this activity, you'll use an existing action. +1. On the list of actions in the **Actions Helper** pane on the right, search for `artifact`. Select on the `Upload a Build Artifact (By actions)` action. + + ![Accessing the Actions helper](./media/actions/build/search-upload-artifact.jpg) + + **Figure 6**: Accessing the snippet helper. + +1. Edit the version to `v2.2.2` to display a sample snippet. Select the clipboard icon to copy the snippet and paste it into the workflow below the publish step. + + ![Copying a snippet](./media/actions/build/copy-snippet.jpg) + + **Figure 7**: Copying a snippet. + +1. Edit the YAML for this step to look as follows: + + ```yml + - name: Upload a Build Artifact + uses: actions/upload-artifact@v2.2.2 + with: + name: website + path: SimpleFeedReader/website/** + if-no-files-found: error + ``` + +1. Commit the file. +1. Once the workflow completes, you'll see the artifact from the **Home** tab: + + ![Viewing artifacts in the summary page](./media/actions/build/view-uploaded-artifact.jpg) + + **Figure 8**: Viewing artifacts in the summary page. + +### Final workflow file + +The final workflow file should look something like this: + +```yml +name: .NET + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal + - name: Publish + run: dotnet publish SimpleFeedReader/SimpleFeedReader.csproj -c Release -o website + - name: Upload a Build Artifact + uses: actions/upload-artifact@v2.2.2 + with: + name: website + path: SimpleFeedReader/website/** + if-no-files-found: error +``` + +>[!div class="step-by-step"] +>[Previous](actions-vs-pipelines.md) +>[Next](actions-deploy.md) diff --git a/docs/architecture/devops-for-aspnet-developers/actions-codeql.md b/docs/architecture/devops-for-aspnet-developers/actions-codeql.md new file mode 100644 index 0000000000000..afe84c3b5b340 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/actions-codeql.md @@ -0,0 +1,192 @@ +--- +title: DevOps with .NET and GitHub Actions - Secure code with CodeQL +description: Add security scanning to your .NET code with GitHub Actions and CodeQL +author: colindembovsky +ms.date: 03/04/2021 +--- + +# Secure .NET Code with CodeQL and GitHub Actions + +[CodeQL](https://codeql.github.com/docs/codeql-overview/about-codeql/) is a static code analysis engine that can automate security and quality checks. With CodeQL, you can perform *variant analysis*, which uses known vulnerabilities as seeds to find similar issues. CodeQL is part of [GitHub Advanced Security](https://docs.github.com/github/getting-started-with-github/about-github-advanced-security) that includes: + +> [!div class="checklist"] +> +> * Code scanning—find potential security vulnerabilities in your code. +> * Secret scanning—detect secrets and tokens that are committed. +> * Dependency scanning—detect vulnerabilities in packages that you consume. + +CodeQL [supports some of the most popular programming languages and compilers](https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/): + +- C/C++ +- Java +- C# +- Python +- Go +- JavaScript +- TypeScript + +CodeQL is a powerful language and security professionals can create custom queries using CodeQL. However, teams can benefit immensely from the large open-source collection of queries that the security community has created without having to write any custom CodeQL. + +In this article, you'll set up a GitHub workflow that will scan code in your repository using CodeQL. You will: + +> [!div class="checklist"] +> +> * Create a code scanning action. +> * Edit the workflow file to include custom scan settings. +> * See scanning results. + +> [!NOTE] +> To see security alerts for your repository, you must be a repository owner. + +## Create the code scanning workflow + +You can use a starter workflow for code scanning by navigating to the **Security** tab of your repository. + +1. Navigate to your GitHub repository and select the **Security** > **Code Scanning Alerts**. The top recommended workflow should be CodeQL Analysis. Select **Set up this workflow**. + + ![Create a new code scanning workflow](./media/actions/codeql/setup-workflow.jpg) + + **Figure 1:** Create a new code scanning workflow. + +1. A new workflow file is created in your *.github/workflows* folder. +1. Select **Start Commit** on the upper right to save the default workflow. You can commit to the `main` branch. + + ![Commit the file](./media/actions/codeql/start-commit.jpg) + + **Figure 2:** Commit the file. + +1. Select the **Actions** tab. In the left-hand tree, you'll see a **CodeQL** node. Select this node to filter for CodeQL workflow runs. + + ![View the CodeQL workflow runs](./media/actions/codeql/codeql-run.jpg) + + **Figure 3:** View the CodeQL workflow runs. + +Take a look at the workflow file while it runs. If you remove the comments from the file, you'll see the following YAML: + +```yml +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '40 14 * * 6' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 +``` + +Notice the following things: + +1. The workflow `name` is `CodeQL`. +1. This workflow triggers on `push` and `pull_request` events to the `main` branch. There's also a `cron` trigger. The `cron` trigger lets you define a schedule for triggering this workflow and is randomly generated for you. In this case, this workflow will run at 14:40 UTC every Saturday. + + > [!TIP] + > If you edit the workflow file and hover over the cron expression, a tooltip will show you the English text for the cron expression. + +1. There's a single job called `analyze` that runs on the `ubuntu-latest` hosted agent. +1. This workflow defines a `strategy` with a `matrix` on the array of `language`. In this case, there's only `csharp`. If the repository contained other languages, you could add them to this array. This causes the job to "fan out" and create an instance per value of the matrix. +1. There are four steps, starting with `checkout`. +1. The second step initializes the CodeQL scanner for the `language` this job is going to scan. CodeQL intercepts calls to the compiler to build a database of the code while the code is being built. +1. The `Autobuild` step will attempt to automatically build the source code using common conventions. If this step fails, you can replace it with your own custom build steps. +1. After building, the CodeQL analysis is performed, where suites of queries are run against the code database. +1. The run should complete successfully. However, there appear to be no issues. + + ![No results to the initial scan](./media/actions/codeql/no-results.jpg) + + **Figure 4:** No results to the initial scan. + +## Customize CodeQL settings + +The CodeQL scan isn't reporting any security issues. That's expected with this basic sample. CodeQL can also scan for *quality* issues. The current workflow is using the default `security-extended` suite. You can add quality scanning in by adding a configuration file to customize the scanning suites. In this step, you'll configure CodeQL to use the `security-and-quality` suites. + +> [!INFORMATION] +> For other CodeQL configuration options, see [Configuring CodeQL code scanning in your CI system](https://docs.github.com/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-codeql-code-scanning-in-your-ci-system). + +1. Navigate to the *.github* folder in the **Code** tab and select **Add File**: + + ![Create a new file](./media/actions/codeql/create-new-file.jpg) + + **Figure 5:** Create a new file. + +1. Enter *codeql/codeql-config.yml* as the name. This creates the file in a folder. Paste in the following code: + + ```yml + name: "Security and Quality" + + queries: + - uses: security-and-quality + ``` + + ![Create the CodeQL config file](./media/actions/codeql/codeql-config.jpg) + + **Figure 6:** Create the CodeQL configuration file. + +1. Select **Commit to main** at bottom of the editor to commit the file. +1. Edit the CodeQL workflow to use the new configuration file. Navigate to *.github/workflows/codeql-analysis.yml* and select the pencil icon. Add a new property to the `with` section as shown below: + + ```yml + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + config-file: ./.github/codeql/codeql-config.yml # <-- add this line + ``` + +1. Select **Start Commit** and commit to the `main` branch. + +## Review the security alerts + +> [!IMPORTANT] +> You must be a repository owner to view security alerts. +> +> This sample repository is small. As such, it doesn't contain any major security or quality issues. However, "real world" repositories will likely have some issues. + +When the last CodeQL workflow run completes, you should see two issues in the **Security** tab: + +![View security alerts](./media/actions/codeql/security-alerts.jpg) + +**Figure 7:** View security alerts. + +1. Select the first alert to open it. +1. In this case, the alert is for a generated file that isn't committed to the repository. For that reason, the preview is unavailable. +1. Notice the tags that are applied. These tags can be used for filtering issues. +1. Select **Show more** under the rule information to show help and recommendations. + + ![Open an alert](./media/actions/codeql/alert.jpg) + + **Figure 8:** Open an alert. + +1. Selecting **Dismiss** will open options for dismissing this issue: + + ![Dismiss an alert](./media/actions/codeql/dismiss.jpg) + + **Figure 9:** Dismiss an alert. + +>[!div class="step-by-step"] +>[Previous](actions-deploy.md) +>[Next](monitoring.md) diff --git a/docs/architecture/devops-for-aspnet-developers/actions-deploy.md b/docs/architecture/devops-for-aspnet-developers/actions-deploy.md new file mode 100644 index 0000000000000..e352e0b081c62 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/actions-deploy.md @@ -0,0 +1,513 @@ +--- +title: DevOps with .NET and GitHub Actions - Deploy a .NET Web App to Azure Web Apps +description: Deploy a .NET app to Azure App Service, the first step for DevOps with .NET and GitHub Actions. +author: colindembovsky +ms.date: 03/04/2021 +--- +# Deploy a .NET web app using GitHub Actions + +> [!WARNING] +> Please complete the [Build](actions-build.md) tutorial before starting this lab. + +In this article, you'll: +> [!div class="checklist"] +> +> * Learn about Environments in GitHub Actions. +> * Create two environments and specify environment protection rules. +> * Create environment secrets for managing environment-specific configuration. +> * Extend the workflow YAML file to add deployment steps. +> * Add a manual dispatch trigger. + +## Environments + +Now that you've published an artifact that's *potentially deployable*, you'll add *deployment* jobs to the workflow. There's nothing special about a deployment job, other than the fact that it references an *environment*. Environments are *logical* constructs that allow you to specify environment protection rules, such as approvals, on any group of resources that you're targeting. + +In this walkthrough, you'll be deploying to two environments: `PRE-PROD` and `PROD`. In a typical development lifecycle, you'll want to deploy the latest code to a *soft* environment (typically `DEV`) that is expected to be a bit unstable. You'll use `PRE-PROD` as this *soft* environment. The "higher" environments (like `UAT` and `PROD`) are *harder* environments that are expected to be more stable. To enforce this, you can build protection rules into higher environments. You'll configure an approval protection rule on the `PROD` environment: whenever a deployment job targets an environment with an approval rule, it will pause until approval is granted before executing. + +GitHub environments are *logical*. They represent the physical (or virtual) resources that you're deploying to. In this case, the `PRE-PROD` is just a deployment slot on the Azure Web App. `PROD` is the production slot. The `PRE-PROD` deployment job will deploy the published .NET app to the staging slot. The `PROD` deployment job will swap the slots. + +Once you have these steps in place, you'll update the workflow to handle environment-specific configuration using environment secrets. + +> [!NOTE] +> For more information, see [GitHub Actions - Environments](https://docs.github.com/actions/reference/environments). + +## Azure authentication + +To perform actions such as deploying code to an Azure resource, you need the correct permissions. For deployment to Azure Web Apps, you can use a publishing profile. If you want to deploy to a staging slot, then you'll need the publishing profile for the slot too. Instead, you can use a service principal (SPN) and assign permission to this service principal. You can then authenticate using credentials for the SPN before using any commands that the SPN has permissions to perform. + +Once you have an SPN, you'll create a [repository secret](https://docs.github.com/actions/reference/encrypted-secrets) to securely store the credentials. You can then refer to the secret whenever you need to authenticate. The secret is encrypted and once it has been saved, can never be viewed or edited (only deleted or re-created). + +### Create an SPN + +1. In your terminal or Cloud Shell, run the following command to create a service principal with contributor permissions to the web app you created earlier: + + ```azurecli + az ad sp create-for-rbac --name "{sp-name}" --sdk-auth --role contributor \ + --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{webappname} + ``` + +1. The command should output JSON that has credentials embedded: + + ```json + { + "clientId": "", + "clientSecret": "", + "subscriptionId": "", + "tenantId": "", + ... + } + ``` + +1. Make sure to record the `clientId`, `clientSecret`, `subscription`, and `tenantId`. You can also leave the terminal open for copy/paste later. + +### Create a repository secret + +1. Now you're going to create an encrypted secret to store the credentials. You'll create this secret at the repository level. +1. Navigate to GitHub and select your repository **Settings** tab. Then select **Secrets**. Select **New repository secret**: + + ![Create a secret](./media/actions/deploy/add-repo-secret.jpg) + + **Figure 1**: Create a secret. + +1. Copy and paste the JSON from the `az ad sp create-for-rbac` command into the body of the secret. You can create this JSON by hand too if you have the relevant fields for your SPN. The secret should be named `AZURE_CREDENTIALS`. Select **Add secret** to save the new secret: + + ![Add Azure credentials](./media/actions/deploy/azure-credentials.jpg) + + **Figure 2**: Add Azure credentials. + +1. You'll consume this secret in a workflow in later steps. To access it, use the variable notation `${{}}`. In this case, `${{ AZURE_CREDENTIAL }}` will be populated with the JSON you saved. + +## Add environments + +[Environments](https://docs.github.com/actions/reference/environments) are used as a *logical boundary*. You can add approvals to environments to ensure quality. You can also track deployments to environments and specify environment-specific values (secrets) for configuration. + +For this example, you're going to split the actual Azure environment into two *logical* environments called `PRE-PROD` and `PROD`. When you deploy the web app, you'll deploy to the staging slot of the Azure web app, represented by the `PRE-PROD` environment. When you're ready to deploy to `PROD`, you'll just perform a slot swap. + +In this case, the only difference between the environments is the slot that you're deploying to. In real life, there would typically be different web apps (and separate web app plans), separate resource groups, and even separate subscriptions. Typically, there's an SPN per environment. You may want to override the `AZURE_CREDENTIAL` value that you saved as a repository secret by creating it as an *environment secret*. + +> [!NOTE] +> Precedence works from Environment to repository. If a targeted environment has a secret called `MY_SECRET`, then that value is used. If not, the repository value of `MY_SECRET` (if any) is used. + +1. Select **Settings** and then **Environments** in your repository. Select **New Environment**: + + ![Create an environment](./media/actions/deploy/new-env.jpg) + + **Figure 3**: Create an environment. + +1. Enter `PRE-PROD` and select **Configure environment**: + + ![Name the environment](./media/actions/deploy/pre-prod-env.jpg) + + **Figure 4**: Name the environment. + +1. Since deploying to a staging slot doesn't affect the web app, you can safely deploy to the slot without requiring an approval first. A reviewer could be added if desired. For this example, leave the Environment protection rules empty. + + > [!NOTE] + > If you target an environment in a workflow and it does not exist, an "empty" environment is created automatically. The environment would look exactly the same as the `PRE-PROD` environment - it would exist, but would not have any protection rules enabled. + +1. Select **Environments** again and again select **New Environment**. Now enter `PROD` as the name and select **Configure environment**. + +1. Check the **Required reviewers** rule and add yourself as a reviewer. Don't forget to select **Save protection rules**: + + ![Add protection rules](./media/actions/deploy/env-protection-rule.jpg) + + **Figure 5**: Add protection rules. + +## Deploy to staging + +You can now add additional jobs to the workflow to deploy to the environments! You'll start by adding a deployment to the `PRE-PROD` environment, which in this case is the web app staging slot. + +1. Navigate to the *.github/workflows/dotnet.yml* file and select the pencil icon to edit the file. +1. You're going to use the web app name a few times in this workflow, and will need the name of the resource group too. You'll define the app and resource group names as variables. With the variables, you can maintain the values in one place in the workflow file. +1. Add this snippet below the `on` block and above the `jobs` block: + + ```yml + env: + app-name: "" + rg-name: "" + + jobs: # <-- this is the existing jobs line + ``` + + > [!WARNING] + > You'll need to replace `` with the actual name of your web app, and `` with the actual name of your resource group. + +1. Add a new job below the `build` job as follows: + + ```yml + if-no-files-found: error # <-- last line of build job: insert below this line + + deploy_staging: + needs: build + runs-on: ubuntu-latest + + environment: + name: PRE-PROD + url: ${{ steps.deploywebapp.outputs.webapp-url }} + + steps: + - name: Download a Build Artifact + uses: actions/download-artifact@v2.0.8 + with: + name: website + path: website + + - name: Login via Azure CLI + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Deploy web app + id: deploywebapp + uses: azure/webapps-deploy@v2 + with: + app-name: ${{ env.app-name }} + slot-name: staging + package: website + + - name: az cli logout + run: az logout + ``` + + The preceding workflow defines several steps: + + 1. You're creating a new job called `deploy_staging`. + 1. You specify a dependency using `needs`. This job needs the `build` job to complete successfully before it starts. + 1. This job also runs on the latest Ubuntu hosted agent, as specified with the `runs-on` attribute. + 1. You specify that this job is targeting the `PRE-PROD` environment using the `environment` object. You also specify the `url` property. This URL will be displayed in the workflow diagram, giving users an easy way to navigate to the environment. The value of this property is set as the `output` of the `step` with `id` `deploywebapp`, which is defined below. + 1. You're executing a `download-artifact` step to download the artifact (compiled web app) from the `build` job. + 1. You then `login` to Azure using the `AZURE_CREDENTIALS` secret you saved earlier. Note the `${{ }}` notation for dereferencing variables. + 1. You then perform a `webapp-deploy`, specifying the `app-name`, `slot-name`, and path to the downloaded artifact (`package`). This action also defines an `output` parameter that you use to set the `url` of the environment above. + 1. Finally, you execute a `logout` to log out of the Azure context. + +1. Commit the file. +1. When the run completes, you should see two successful jobs. The URL for the `PRE-PROD` stage has been set and selecting it will navigate you to your web app staging slot: + + ![Deployment to PRE-PROD is successful](./media/actions/deploy/deploy-to-staging-completed.jpg) + + **Figure 6**: Deployment to PRE-PROD is successful. + +1. Notice how the staging slot's direct URL contains `-staging`: + + ![The staging slot running](./media/actions/deploy/deployed-to-staging.jpg) + + **Figure 7**: The staging slot running. + +1. You can also now see deployments. Navigate to `https://{your repository url}/deployments` to view your deployments: + + ![View deployments](./media/actions/deploy/deployments.jpg) + + **Figure 8**: View deployments. + +## Deploy to production + +Now that you've deployed successfully to `PRE-PROD`, you'll want to deploy to `PROD`. Deployment to `PROD` will be slightly different since you don't need to copy the website again - you just need to swap the `staging` slot with the production slot. You'll do this using an Azure CLI (`az`) command. + +1. Navigate to the *.github/workflows/dotnet.yml* file and select the pencil icon to edit the file. +1. Add a new job below the `deploy_staging` job as follows: + + ```yml + run: az logout # <-- last line of previous job: insert below this line + + deploy_prod: + needs: deploy_staging + runs-on: ubuntu-latest + + environment: + name: PROD + url: ${{ steps.slot_swap.outputs.url }} + + steps: + - name: Login via Azure CLI + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Swap staging slot into production + id: slot_swap + run: | + az webapp deployment slot swap -g ${{ env.rg-name }} -n ${{ env.app-name }} -s staging + url=$(az webapp show -g ${{ env.rg-name }} -n ${{ env.app-name }} --query "defaultHostName" -o tsv) + echo "::set-output name=url::http://$url" + + - name: az cli logout + run: az logout + ``` + + The deployment to the `PROD` environment workflow specifies several steps: + + 1. Once again, you specify a new job `deploy_prod` that `needs` `deploy_staging` to complete before starting. + 1. You're targeting the `PROD` environment this time. Also, the `url` value is different from before. + 1. For the steps, you don't need to download the artifact since you're just going to perform a slot swap. You start by executing a `login` to the Azure context. + 1. The `Swap staging slot into production` step is a multi-line `run` command (note the use of the pipe symbol `|`). You also specify an `id` for this step so that you can refer to it (you refer to it in the `url` property of the `environment`). The first line executes the slot swap using the variables you defined above in the workflow. The second line uses an `az webapp show` command to extract the URL of the target web app. This final line uses `::set-output` in an echo to create an output variable for this task, setting the value to the web app URL. + + > [!NOTE] + > The URL *must* start with `http://` or `https://` or it won't render. + +1. Commit the file. +1. Let the workflow run for a couple minutes until it has deployed to `PRE-PROD`. At this point, the workflow will pause and wait for the required approval since you're targeting the `PROD` environment, which requires an approval as defined earlier: + + ![Waiting for an approval](./media/actions/deploy/waiting-for-approval.jpg) + + **Figure 9**: Waiting for an approval. + +1. Select **Review deployments**, select the **PROD** checkbox, optionally add a comment, and then select **Approve and deploy** to start the `PROD` job. + + ![Approve the PROD deployment](./media/actions/deploy/approval.jpg) + + **Figure 10**: Approve the PROD deployment. + +1. The deployment should only take a few seconds. Once it has completed, the URL for the `PROD` environment will update. + + ![PROD deployment completed](./media/actions/deploy/prod-deploy-complete.jpg) + + **Figure 11**: PROD deployment completed. + +1. Selecting the `PROD` URL will navigate you to the `PROD` site. + + ![The PROD site](./media/actions/deploy/deployed-to-prod.jpg) + + **Figure 12**: The PROD site. + +## Add a manual queue option + +You now have an end-to-end build and deploy workflow, including approvals. One more change you can make is to add a manual trigger to the workflow so that the workflow can be triggered from within the **Actions** tab of the repository. + +1. Navigate to the *.github/workflows/dotnet.yml* file and select the pencil icon to edit the file. +1. Add a new trigger between `on` and `push` on lines 3 and 4: + + ```yml + on: + workflow_dispatch: # <-- this is the new line + push: + ``` + +1. The `workflow_dispatch` trigger displays a `Run workflow` button in the **Actions** tab of the repository—*but only if the trigger is defined in the default branch*. However, once this trigger is defined in the workflow, you can select the branch for the run. +1. Commit the file. +1. To see the **Run workflow** button, select the **Actions** tab. Select the `.NET` workflow in the list of workflows. At the top of the list of runs, you'll see the **Run workflow** button. If you select it, you can choose the branch to run the workflow against and queue it: + + ![Manual dispatch](./media/actions/deploy/manual-dispatch.jpg) + + **Figure 13**: Manual dispatch. + +## Handle environment configuration + +Your workflow is deploying the same binary to each environment. This concept is important to ensure that the binaries you test in one environment are the same that you deploy to the next. However, environments typically have different settings like database connection strings. You want to ensure that the `DEV` app is using `DEV` settings and the `PROD` app is using `PROD` settings. + +For this simple app, there's no database connection string. However, there's an example configuration setting that you can modify for each environment. If you open the *simple-feed-reader/SimpleFeedReader/appsettings.json* file, you'll see that the configuration includes a setting for the Header text on the Index page: + +```json + "UI": { + "Index": { + "Header": "Simple News Reader" + } + }, +``` + +To show how environment configuration can be handled, you're going to add a secret to each environment and then substitute that value into the settings as you deploy. + +### Add environment secrets + +1. On your repository, select **Settings** > **Environments** > **PRE-PROD**. +1. Select **Add secret** and add a secret called `index_header` with the value `PRE PROD News Reader`. Select **Add secret**. + + ![Add an environment secret](./media/actions/deploy/add-env-secret.jpg) + + **Figure 14**: Add an environment secret. + +1. Repeat these steps to add a secret called `index_header` with the value `PROD News Reader` for the `PROD` environment. +1. If you select **Settings** > **Secrets** in the repository, you'll see the changes. They should look something like this: + + ![View secrets](./media/actions/deploy/env-secrets.jpg) + + **Figure 15**: View secrets. + +### Update the workflow to handle configuration + +1. Navigate to the *.github/workflows/dotnet.yml* file and select the pencil icon to edit the file. +1. Add the following step before the `az cli logout` step in the `deploy_staging` job: + + ```yml + - name: Update config + uses: Azure/appservice-settings@v1 + with: + app-name: ${{ env.app-name }} + slot-name: staging + app-settings-json: | + [ + { + "name": "UI:Index:Header", + "value": "${{ secrets.INDEX_HEADER }}", + "slotSetting": true + } + ] + + - name: az cli logout # <-- this exists already + ``` + +1. Add almost the same code to the `deploy_prod` job above its `az cli logout` step. The only difference is that you don't specify a `slot-name`, since you're targeting the production slot: + + ```yml + - name: Update config + uses: Azure/appservice-settings@v1 + with: + app-name: ${{ env.app-name }} + app-settings-json: | + [ + { + "name": "UI:Index:Header", + "value": "${{ secrets.INDEX_HEADER }}", + "slotSetting": true + } + ] + + - name: az cli logout # <-- this exists already + ``` + +1. Commit the file. +1. Let the workflow run and approve the deployment to `PROD` once the approval is reached. +1. You should see the following headers on the index page for both sites: + + ![Settings changed in the environments](./media/actions/deploy/settings-in-both-envs.jpg) + + **Figure 16**: Settings changed in the environments. + +## Final workflow file + +The final workflow file should look like this: + +```yml +name: .NET + +on: + workflow_dispatch: + inputs: + reason: + description: 'The reason for running the workflow' + required: true + default: 'Manual build from GitHub UI' + push: + branches: [ main ] + pull_request: + branches: [ main ] + +env: + app-name: "cd-simplefeedreader" + rg-name: "cd-dotnetactions" + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: 'Print manual run reason' + if: ${{ github.event_name == 'workflow_dispatch' }} + run: | + echo 'Reason: ${{ github.event.inputs.reason }}' + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 2.1.x + - name: Restore dependencies + run: dotnet restore + - name: Build + run: dotnet build --no-restore + - name: Test + run: dotnet test --no-build --verbosity normal + - name: Publish + run: dotnet publish SimpleFeedReader/SimpleFeedReader.csproj -c Release -o website + - name: Upload a Build Artifact + uses: actions/upload-artifact@v2.2.2 + with: + name: website + path: SimpleFeedReader/website/** + if-no-files-found: error + + deploy_staging: + needs: build + runs-on: ubuntu-latest + + environment: + name: STAGING + url: ${{ steps.deploywebapp.outputs.webapp-url }} + + steps: + - name: Download a Build Artifact + uses: actions/download-artifact@v2.0.8 + with: + name: website + path: website + + - name: Login via Azure CLI + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Deploy web app + id: deploywebapp + uses: azure/webapps-deploy@v2 + with: + app-name: ${{ env.app-name }} + slot-name: staging + package: website + + - name: Update config + uses: Azure/appservice-settings@v1 + with: + app-name: ${{ env.app-name }} + slot-name: staging + app-settings-json: | + [ + { + "name": "UI:Index:Header", + "value": "${{ secrets.INDEX_HEADER }}", + "slotSetting": true + } + ] + + - name: az cli logout + run: az logout + + deploy_prod: + needs: deploy_staging + runs-on: ubuntu-latest + + environment: + name: PROD + url: ${{ steps.slot_swap.outputs.url }} + + steps: + - name: Login via Azure CLI + uses: azure/login@v1 + with: + creds: ${{ secrets.AZURE_CREDENTIALS }} + + - name: Swap staging slot into production + id: slot_swap + run: | + az webapp deployment slot swap -g ${{ env.rg-name }} -n ${{ env.app-name }} -s staging + url=$(az webapp show -g ${{ env.rg-name }} -n ${{ env.app-name }} --query "defaultHostName" -o tsv) + echo "::set-output name=url::http://$url" + + - name: Update config + uses: Azure/appservice-settings@v1 + with: + app-name: ${{ env.app-name }} + app-settings-json: | + [ + { + "name": "UI:Index:Header", + "value": "${{ secrets.INDEX_HEADER }}", + "slotSetting": true + } + ] + + - name: az cli logout + run: az logout +``` + +>[!div class="step-by-step"] +>[Previous](actions-build.md) +>[Next](actions-codeql.md) diff --git a/docs/architecture/devops-for-aspnet-developers/actions-index.md b/docs/architecture/devops-for-aspnet-developers/actions-index.md new file mode 100644 index 0000000000000..c507d6a763c62 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/actions-index.md @@ -0,0 +1,57 @@ +--- +title: Continuous integration and deployment with GitHub Actions overview +description: Learn how to create a continuous deployment pipeline with GitHub Actions and .NET DevOps +author: colindembovsky +ms.date: 03/30/2021 +uid: azure/devops/github-actions +--- +# Continuous integration and deployment with GitHub Actions + +GitHub has long been the home for millions of open-source developers around the globe. Most developers associate source control with GitHub. However, GitHub is an evolving platform that can be used for more than just synchronizing Git repositories. + +## GitHub Actions + +GitHub Actions is a workflow engine that can automate workflows for nearly all events that occur on GitHub. Actions is a great solution for Continuous Integration/Continuous Deployment (CI/CD) pipelines. + +In this section of articles, you'll learn how to create an Actions workflow. The workflow will build, test, and deploy a .NET web app to Azure Web Apps. + +> [!NOTE] +> Before you begin, complete the **Publish the app's code to GitHub** and **Disconnect local Git deployment** sections of the [Continuous integration and deployment with Azure DevOps](cicd.md) section to publish your code to GitHub. Then proceed to the [Build](actions-build.md) article. + +In the [Build](actions-build.md) article, you'll create the initial workflow to build and test the .NET app. You'll: + +> [!div class="checklist"] +> +> * Learn the basic structure of a GitHub Action workflow YAML file. +> * Use a template to create a basic build workflow that builds a .NET app and executes unit tests. +> * Publish the compiled app so that it's ready for deployment. + +In the [Deploy](actions-build.md) article, you'll: + +> [!div class="checklist"] +> +> * Learn about environments in GitHub Actions. +> * Create two environments and specify environment protection rules. +> * Create environment secrets for managing environment-specific configuration. +> * Extend the workflow YAML file to add deployment steps. +> * Add a manual dispatch trigger. + +## Secure code with CodeQL + +In addition to building and deploying code, [GitHub Advanced Security](https://docs.github.com/github/getting-started-with-github/about-github-advanced-security) offers tools for "shifting left" with security. That is, integrating security early on in the software delivery lifecycle. [CodeQL](https://codeql.github.com/docs/codeql-overview/about-codeql/) is a code scanning language that runs queries to find potential vulnerabilities or quality issues in your code. CodeQL is run using an Actions workflow. + +In the [CodeQL](actions-codeql.md) article, you'll: + +> [!div class="checklist"] +> +> * Create a Code Scanning Action. +> * Edit the workflow file to include custom scan settings. +> * See scanning results. + +## Compare and contrast GitHub Actions and Azure Pipelines + +GitHub Actions and Azure Pipelines have a common lineage and are similar in many respects. However, you should understand the differences before selecting a platform for building, testing, and deploying apps. In the [Comparison](actions-vs-pipelines.md) article, you'll deep dive into these platforms and compare and contrast them. You'll also learn how to select the correct platform for your CI/CD needs. + +>[!div class="step-by-step"] +>[Previous](cicd.md) +>[Next](actions-vs-pipelines.md) diff --git a/docs/architecture/devops-for-aspnet-developers/actions-vs-pipelines.md b/docs/architecture/devops-for-aspnet-developers/actions-vs-pipelines.md new file mode 100644 index 0000000000000..6bbb89b022a8e --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/actions-vs-pipelines.md @@ -0,0 +1,134 @@ +--- +title: DevOps with .NET and GitHub Actions - Compare GitHub Actions with Azure Pipelines +description: GitHub Actions and Azure Pipelines compared and contrasted for decision makers +author: colindembovsky +ms.date: 03/04/2021 +--- + +# Compare and contrast GitHub Actions and Azure Pipelines + +[GitHub Actions](https://docs.github.com/actions) and [Azure Pipelines](/azure/devops/pipelines/get-started/what-is-azure-pipelines) have a common history. In fact, the Actions agent is a fork of the Pipelines agent. There are many similarities between GitHub Actions and Azure Pipelines and it's worth comparing and contrasting them. + +## Pipelines as code + +Before you compare GitHub Actions and Azure Pipelines, you should consider the benefits of *pipelines as code*. Pipelines as code: + +> [!div class="checklist"] +> +> * Benefit from standard source control practices (such as code reviews via pull request and versioning). +> * Can be audited for changes just like any other files in the repository. +> * Don’t require accessing a separate system or UI to edit. +> * Can fully codify the build, test, and deploy process for code. +> * Can usually be templatized to empower teams to create standard processes across multiple repositories. + +> [!NOTE] +> The term "pipelines" can also be referred to by several different interchangeable words: *pipeline*, *workflow*, and *build* are common terms. In this article, references to *Azure Pipelines* are referring to [YAML Pipelines](/azure/devops/pipelines/get-started/pipelines-get-started?view=azure-devops&preserve-view=true#define-pipelines-using-yaml-syntax), and not the older UI-based [Classic Pipelines](/azure/devops/pipelines/get-started/pipelines-get-started?view=azure-devops&preserve-view=true#define-pipelines-using-the-classic-interface). + +## Agents and runners + +Before you examine pipelines themselves, you should consider how these pipelines *execute*. Both GitHub Actions and Azure Pipelines are really *orchestration engines*. When a pipeline is triggered, the system finds an "agent" and tells the agent to execute the jobs defined in the pipeline file. + +Azure Pipelines run on *agents*. The agent is written in .NET, so it will run wherever .NET can run: Windows, macOS, and Linux. Agents can even run in containers. Agents are registered to a [pool](/azure/devops/pipelines/agents/pools-queues) in Azure Pipelines or to a repository or organization in GitHub. Agents can be *hosted* or *private*. + +GitHub Workflows execute on *runners*. The runner code is essentially a fork of the Azure Pipelines code, so it's very similar. It's also cross-platform and you can also use *hosted* or *self-hosted* runners. + +### Hosted agents and runners + +Hosted agents (Azure Pipelines) and hosted runners (GitHub) are agents that are spun up and managed by Azure DevOps or GitHub respectively. You don't need to maintain any build infrastructure. When a pipeline triggers that targets a hosted agent, an instance of the specified agent image is created. The job is run by the agent on the instance, and once the job completes, the instance is destroyed. The same applies for hosted runners running GitHub workflows. + +> [!NOTE] +> The list of software installed on Azure Pipeline images is listed in [this repository](https://github.com/actions/virtual-environments/tree/main/images). You can select the platform folder and examine the *README.md* files. You can find information on [GitHub hosted runners](https://docs.github.com/actions/reference/specifications-for-github-hosted-runners). + +### Private agents and self-hosted runners + +There are times when you can't use hosted images. For example, when you: + +- Require SDKs or other software that isn't installed on the images. +- Need to access resources that aren't public (such as an internal SonarQube server or an internal Artifactory instance). +- Need to deploy to private networks. +- Need to install licenses for third-party software required for building your code. +- Need more storage or memory than is provided to the hosted agent images. +- Need more time than the maximum build time limit for hosted agents. + +> [!IMPORTANT] +> It's possible to install tools and SDKs when running pipelines on hosted agents. If the install steps don't take long, this is viable. However, if the tools/software take a long time to install, then you may be better off with a private agent or self-hosted runner, since the install steps will need to execute for every run of the workflow. + +### Azure DevOps agents + +Every Azure DevOps account has a hosted pool with a single agent that can run one job at a time. Also included is a set number of free build minutes. You may purchase additional "hosted pipelines" in Azure DevOps. When you purchase an additional hosted pipeline, you're really removing the build minutes limit and adding *concurrency*. One pipeline can run one job at a time. Two pipelines can run two jobs simultaneously, and so on. + +### Comparison of agents + +|Feature|GitHub|Azure Pipelines|Links| +|-------|------|---------------|-----| +|Hosted agents for public repos/projects|Free|[No free minutes](https://devblogs.microsoft.com/devops/change-in-azure-pipelines-grant-for-public-projects/) for public projects|[Azure Pipelines](/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml&preserve-view=true#capabilities-and-limitations) [GitHub](https://github.com/features/actions)| +|Hosted agents for private repos/projects|2,000 minutes free per month, 3,000 minutes for Pro and Team licenses, 50,000 minutes for Enterprise license. Additional minutes may be purchased.|One free parallel job that can run for up to 60 minutes each time, until you've used 1,800 minutes (30 hours) per month. You can pay for additional capacity per parallel job. Paid parallel jobs remove the monthly time limit and allow you to run each job for up to 360 minutes (6 hours).|| +|Cross-platform|Yes|Yes|| +|Scale set agents|No|Yes| [Azure virtual machine scale set agents](/azure/devops/pipelines/agents/scale-set-agents?view=azure-devops&preserve-view=true)| + +## Comparison of GitHub Actions and Azure Pipelines + +Azure Pipelines (YAML pipelines) provide a mature set of features. Some of the features include: + +* Approvals +* Artifact storage +* Deployment jobs +* Environments +* Gates +* Stages +* Templates +* Triggers +* Variable groups + +For a full list of Azure Pipelines features, refer to the [Feature availability](/azure/devops/pipelines/get-started/pipelines-get-started?view=azure-devops&preserve-view=true#feature-availability) table. + +GitHub Actions are evolving rapidly and provide features such as triggers for almost all GitHub events, artifact storage, environments and environment rules, starter templates, and matrices. Read more about the entire feature set refer [GitHub Actions](https://docs.github.com/actions). + +### Feature comparison + +The following table is current as of March 2021. + +|Feature|Description|GitHub Actions|Azure Pipelines| +|-------|-----------|--------------|---------------| +|Approvals|Define approval conditions before moving further in the pipeline|Yes|Yes| +|Artifacts|Upload, store, and download artifacts from jobs|Yes|Yes| +|Caching|Cache folders or files for subsequent runs|Yes|Yes| +|Conditions|Specify conditions for steps or jobs|Yes|Yes| +|Container Jobs|Run jobs inside a container|Yes|Yes| +|Demands|Specify demands that must be met to match jobs to agents|No|Yes| +|Dependencies|Specify dependencies between jobs or stages|Yes|Yes| +|Deployment Groups|A logical set of target machines for deployments|No|Yes| +|Deployment Jobs|Job that targets a deployment group|No|Yes| +|Environments|A collection of resources to target or a logical environment|Yes|Yes| +|Gates|Automatic collection and evaluation of signals to control continuation|No|Yes| +|Jobs|Sequence of steps that are executed on an agent|Yes|Yes| +|Service Containers|Manage the lifecycle of a containerized service instance available during a job|Yes|Yes| +|Service Connections|Abstract credentials to external systems|No|Yes| +|Stages|Organize jobs in a pipeline|No|Yes| +|Templates|Define reusable, parameterized building blocks for steps, jobs, or variables|No|Yes| +|Starter Templates|Defines a starter workflow based on the type of code detected in a repository|Yes|No| +|Triggers|Set of events that cause the pipeline to trigger|Yes|Yes| +|Variables|Variables that can be passed in, statically or dynamically defined|Yes|Yes| +|Variable Groups|Store values for use across multiple pipelines|No|Yes| + +## Recommendation table for common scenarios + +The following table shows some common scenarios and platform recommendations for each. As always, there will be exceptions. Consider your exact scenario carefully. + +|Requirement|Platform| +|-----------|--------| +|I need to create reusable templates to standardize how jobs are executed across multiple teams|Azure Pipelines| +|I need to have automated gates control pipeline progress|Azure Pipelines| +|I need to define multiple stages|Azure Pipelines| +|I need multiple jobs to target the same environment|Azure Pipelines| +|I need to model multiple, complex environments|Azure Pipelines| +|I need to use the same environments across multiple projects/repos|Azure Pipelines| +|I have repos that aren't in GitHub|Azure Pipelines| +|I need to create custom tasks that aren't open-source|Azure Pipelines| +|I need a simple workflow for building and deploying open-source repositories to a small set of environments|GitHub Actions| +|I need to model workflows for scenarios other than CI/CD. For example, custom alerts on pull requests|GitHub Actions| +|I need to create custom tasks that are open-source|Both| + +>[!div class="step-by-step"] +>[Previous](actions-index.md) +>[Next](actions-build.md) diff --git a/docs/architecture/devops-for-aspnet-developers/cicd.md b/docs/architecture/devops-for-aspnet-developers/cicd.md new file mode 100644 index 0000000000000..0934b16888aff --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/cicd.md @@ -0,0 +1,328 @@ +--- +title: Continuous integration and deployment - DevOps for ASP.NET Core Developers +author: CamSoper +description: Continuous integration and deployment in DevOps for ASP.NET Core Developers +ms.author: scaddie +ms.date: 10/24/2018 +ms.custom: "devx-track-csharp, mvc, seodec18" +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/cicd +--- +# Continuous integration and deployment with Azure DevOps + +> [!NOTE] +> This section details continuous integration and deployment with Azure DevOps. You can achieve that with GitHub Actions as well. GitHub Actions is a workflow engine built into GitHub that can also be used for continuous integration and deployment. To follow the guide for building and deploying to Azure using GitHub, complete the **Publish the app's code to GitHub** and **Disconnect local Git deployment** sections below and then proceed to the [GitHub Actions section](actions-index.md). + +In the previous chapter, you created a local Git repository for the Simple Feed Reader app. In this chapter, you'll publish that code to a GitHub repository and construct an Azure DevOps Services pipeline using Azure Pipelines. The pipeline enables continuous builds and deployments of the app. Any commit to the GitHub repository triggers a build and a deployment to the Azure Web App's staging slot. + +In this section, you'll complete the following tasks: + +> [!div class="checklist"] +> +> * Publish the app's code to GitHub +> * Disconnect local Git deployment +> * Create an Azure DevOps organization +> * Create a team project in Azure DevOps organization +> * Configure a self-hosted agent if necessary +> * Create a build definition +> * Create a release pipeline +> * Commit changes to GitHub and automatically deploy to Azure +> * Examine the Azure Pipelines pipeline + +## Publish the app's code to GitHub + +1. Open a browser window, and navigate to `https://github.com`. +1. Click the **+** drop-down in the header, and select **New repository**: + + ![GitHub New Repository option](media/cicd/github-new-repo.png) + +1. Select your account in the **Owner** drop-down, and enter *simple-feed-reader* in the **Repository name** textbox. +1. Click the **Create repository** button. +1. Open your local machine's command shell. Navigate to the directory in which the *simple-feed-reader* Git repository is stored. +1. Rename the existing *origin* remote to *upstream*. Execute the following command: + + ```console + git remote rename origin upstream + ``` + +1. Add a new *origin* remote pointing to your copy of the repository on GitHub. Execute the following command: + + ```console + git remote add origin https://github.com//simple-feed-reader/ + ``` + +1. Publish your local Git repository to the newly created GitHub repository. Execute the following command: + + ```console + git push -u origin main + ``` + +1. Open a browser window, and navigate to `https://github.com//simple-feed-reader/`. Validate that your code appears in the GitHub repository. + +## Disconnect local Git deployment + +Remove the local Git deployment with the following steps. Azure Pipelines (an Azure DevOps service) both replaces and augments that functionality. + +1. Open the [Azure portal](https://portal.azure.com/), and navigate to the *staging (mywebapp\/staging)* Web App. The Web App can be quickly located by entering *staging* in the portal's search box: + + ![staging Web App search term](media/cicd/portal-search-box.png) + +1. Click **Deployment Center**. A new panel appears. Click **Disconnect** to remove the local Git source control configuration that was added in the previous chapter. Confirm the removal operation by clicking the **Yes** button. +1. Navigate to the *mywebapp* App Service. As a reminder, the portal's search box can be used to quickly locate the App Service. +1. Click **Deployment Center**. A new panel appears. Click **Disconnect** to remove the local Git source control configuration that was added in the previous chapter. Confirm the removal operation by clicking the **Yes** button. + +## Create an Azure DevOps organization + +1. Open a browser, and navigate to the [Azure DevOps organization creation page](https://go.microsoft.com/fwlink/?LinkId=307137). +1. Select **New organization** +1. Confirm the information, and then select **Continue**. +1. Sign in to your organization at any time, `https://dev.azure.com/{yourorganization}` + +## Create a team project in Azure DevOps organization + +1. Choose the organization, and then select **New project**. +1. Enter the project name as *MyFirstProject* and select the **Visibility** as *Private* +1. Select **Create project**. + +For more information, see [Create a project](/azure/devops/organizations/projects/create-project?view=azure-devops&tabs=preview-page&preserve-view=true#create-a-project) + +## Configure a self-hosted agent if necessary + +To build your code or deploy your software using Azure Pipelines, you need at least one agent. In Azure Pipelines, you can run parallel jobs on either **Microsoft-hosted** or **self-hosted** agent. But with the recent change in Azure Pipelines free grant of parallel jobs is temporarily disable for the public projects.For more details, refer [Configure and pay for parallel jobs](/azure/devops/pipelines/licensing/concurrent-jobs?view=azure-devops&tabs=ms-hosted&preserve-view=true). + +Go to **Organization Settings** and then **Pipelines** > **Parallel jobs**. If you see value **0** under **Microsoft-hosted** that means you need a **Self-hosted** agent to run your pipeline. + +![MS-hosted agent](media/cicd/azure-devops-ms-hosted-agent.png) + +You can create that by following details mentioned in [Self-hosted agents](/azure/devops/pipelines/agents/agents?view=azure-devops&tabs=browser&preserve-view=true#install). After successful configuration, you'll be able to see available agent under **Organization Settings** > **Agent pools** > **{youragentname}** + +![Self-hosted agent](media/cicd/azure-devops-self-hosted-agent.png) + +## Configure the Azure Pipelines pipeline + +There are three distinct steps to complete. Completing the steps in the following three sections results in an operational DevOps pipeline. + +### Grant Azure DevOps access to the GitHub repository + +1. In your project, navigate to the **Pipelines** page. Then choose the action to create a new pipeline: + + ![Setup Build button](media/cicd/azure-devops-create-pipeline.png) + +1. Use `Use the classic editor` to create the pipeline. + + ![Use classic editor](media/cicd/azure-devops-classic-editor.png) + +1. Select the **GitHub** option from the **Select a source** section:: + + ![Select a source - GitHub](media/cicd/azure-devops-select-source.png) + +1. Authorization is required before Azure DevOps can access your GitHub repository. Enter * GitHub connection* in the **Connection name** textbox. For example: + + ![GitHub connection name](media/cicd/azure-devops-authz.png) + +1. If two-factor authentication is enabled on your GitHub account, a personal access token is required. In that case, click the **Authorize with a GitHub personal access token** link. See the [official GitHub personal access token creation instructions](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) for help. Only the *repo* scope of permissions is needed. Otherwise, click the **Authorize using OAuth** button. +1. When prompted, sign in to your GitHub account. Then select Authorize to grant access to your Azure DevOps organization. If successful, a new service endpoint is created. +1. Click the ellipsis button next to the **Repository** button. Select the */simple-feed-reader* repository from the list. Click the **Select** button. +1. Select the default branch (*main*) from the **Default branch for manual and scheduled builds** drop-down. Click the **Continue** button. The template selection page appears. + +### Create the build definition + +1. From the template selection page, enter *ASP.NET Core* in the search box: + + ![ASP.NET Core search on template page](media/cicd/azure-devops-template-selection.png) + +1. The template search results appear. Hover over the **ASP.NET Core** template, and click the **Apply** button. +1. The **Tasks** tab of the build definition appears. Select the self-hosted **Agent pool** if you have created that in the earlier step. + + ![Select Self-hosted agent pool](media/cicd/azure-devops-build-agent-pool.png) + + > [!NOTE] + > If you are using MS-hosted agent then select the *Hosted > Azure Pipelines* from drop down. + +1. Click the **Triggers** tab. +1. Check the **Enable continuous integration** box. Under the **Branch filters** section, confirm that the **Type** drop-down is set to *Include*. Set the **Branch specification** drop-down to *main*. + + ![Enable continuous integration settings](media/cicd/azure-devops-enable-ci.png) + + These settings cause a build to trigger when any change is pushed to the default branch (*main*) of the GitHub repository. Continuous integration is tested in the [Commit changes to GitHub and automatically deploy to Azure](#commit-changes-to-github-and-automatically-deploy-to-azure) section. + +1. Click the **Save & queue** button, and select the **Save** option: + + ![Save button](media/cicd/azure-devops-save-build.png) + +1. The following modal dialog appears: + + ![Save build definition - modal dialog](media/cicd/azure-devops-save-modal.png) + + Use the default folder of *\\*, and click the **Save** button. + +### Create the release pipeline + +1. Click the **Releases** tab of your team project. Click the **New pipeline** button. + + ![Releases tab - New definition button](media/cicd/azure-devops-create-release.png) + + The template selection pane appears. + +1. From the template selection page, enter *App Service Deployment* in the search box: + + ![Release pipeline template search box](media/cicd/azure-devops-select-template.png) + +1. The template search results appear. Hover over the **Azure App Service Deployment with Slot** template, and click the **Apply** button. The **Pipeline** tab of the release pipeline appears. + + ![Release pipeline Pipeline tab](media/cicd/azure-devops-new-release-pipeline.png) + +1. Click the **Add** button in the **Artifacts** box. The **Add artifact** panel appears: + + ![Release pipeline - Add artifact panel](media/cicd/azure-devops-release-add-artifacts.png) + +1. Select the **Build** tile from the **Source type** section. This type allows for the linking of the release pipeline to the build definition. +1. Select *MyFirstProject* from the **Project** drop-down. +1. Select the build definition name, *MyFirstProject-ASP.NET Core-CI*, from the **Source (Build definition)** drop-down. +1. Select *Latest* from the **Default version** drop-down. This option builds the artifacts produced by the latest run of the build definition. +1. Replace the text in the **Source alias** textbox with *Drop*. +1. Click the **Add** button. The **Artifacts** section updates to display the changes. +1. Click the lightning bolt icon to enable continuous deployments: + + ![Release pipeline Artifacts - lightning bolt icon](media/cicd/azure-devops-artifacts-lightning-bolt.png) + + With this option enabled, a deployment occurs each time a new build is available. +1. A **Continuous deployment trigger** panel appears to the right. Click the toggle button to enable the feature. It isn't necessary to enable the **Pull request trigger**. +1. Click the **Add** drop-down in the **Build branch filters** section. Choose the **Build Definition's default branch** option. This filter causes the release to trigger only for a build from the GitHub repository's default branch (*main*). +1. Click the **Save** button. Click the **OK** button in the resulting **Save** modal dialog. +1. Click the **Stage 1** box. An **Stage** panel appears to the right. Change the *Stage 1* text in the **Stage name** textbox to *Production*. + + ![Release pipeline - Stage name textbox](media/cicd/azure-devops-environment-name-textbox.png) + +1. Click the **1 phase, 2 tasks** link in the **Production** box: + + ![Release pipeline - Production environment link.png](media/cicd/azure-devops-production-link.png) + + The **Tasks** tab of the environment appears. +1. Click the **Deploy Azure App Service to Slot** task. Its settings appear in a panel to the right. +1. Select the Azure subscription associated with the App Service from the **Azure subscription** drop-down. Once selected, click the **Authorize** button. +1. Select *Web App* from the **App type** drop-down. +1. Select *mywebapp/* from the **App service name** drop-down. +1. Select *AzureTutorial* from the **Resource group** drop-down. +1. Select *staging* from the **Slot** drop-down. +1. Select **Run on agent*** under **Tasks**. On the right pane, you'll see **Agent Job**. +1. Select the self-hosted **Agent pool** if you have created that in the earlier step. + + ![Select Self-hosted agent](media/cicd/azure-devops-release-select-agent-pool.png) + + > [!NOTE] + > If you are using MS-hosted agent then select the *Hosted > Azure Pipelines* from drop down. + +1. Click the **Save** button. +1. Hover over the default release pipeline name. Click the pencil icon to edit it. Use *MyFirstProject-ASP.NET Core-CD* as the name. + + ![Release pipeline name](media/cicd/azure-devops-release-definition-name.png) + +1. Click the **Save** button. + +## Commit changes to GitHub and automatically deploy to Azure + +1. Open *SimpleFeedReader.sln* in Visual Studio. +1. In Solution Explorer, open *Pages\Index.cshtml*. Change `

Simple Feed Reader - V3

` to `

Simple Feed Reader - V4

`. +1. Press **Ctrl**+**Shift**+**B** to build the app. +1. Commit the file to the GitHub repository. Use either the **Changes** page in Visual Studio's *Team Explorer* tab, or execute the following using the local machine's command shell: + + ```console + git commit -a -m "upgraded to V4" + ``` + +1. Push the change in the default branch (*main*) to the *origin* remote of your GitHub repository. In the following command, replace the placeholder `{BRANCH}` with the default branch (use `main`): + + ```console + git push origin {BRANCH} + ``` + + The commit appears in the GitHub repository's default branch (*main*). You'll be able to see the commit history in `https://github.com//simple-feed-reader/commits/main`. + + The build is triggered, since continuous integration is enabled in the build definition's **Triggers** tab: + + ![enable continuous integration](media/cicd/enable-ci.png) + +1. Navigate to the **Pipelines**. You'll see the CI pipeline details and monitor each steps if you drill down **Jobs** details. + + ![Trigger build pipeline](media/cicd/azure-devops-pipepine-build.png) + +1. Similarly, go to the **Releases** tab to see the details of CD pipeline. You can always drill down further to see more details of each step. + + ![Release pipeline](media/cicd/azure-devops-release-pipeline-run.png) + +1. Once the build succeeds, a deployment to Azure occurs. Navigate to the app in the browser. Notice that the "V4" text appears in the heading: + + ![updated app](media/cicd/updated-app-v4.png) + +## Examine the Azure Pipelines pipeline + +### Build definition + +A build definition was created with the name *MyFirstProject-ASP.NET Core-CI*. Upon completion, the build produces a *.zip* file including the assets to be published. The release pipeline deploys those assets to Azure. + +The build definition's **Tasks** tab lists the individual steps being used. There are five build tasks. + +![build definition tasks](media/cicd/azure-devops-build-definition-tasks.png) + +1. **Restore** — Executes the `dotnet restore` command to restore the app's NuGet packages. The default package feed used is nuget.org. +1. **Build** — Executes the `dotnet build --configuration release` command to compile the app's code. This `--configuration` option is used to produce an optimized version of the code, which is suitable for deployment to a production environment. Modify the *BuildConfiguration* variable on the build definition's **Variables** tab if, for example, a debug configuration is needed. +1. **Test** — Executes the `dotnet test --configuration release --logger trx --results-directory ` command to run the app's unit tests. Unit tests are executed within any C# project matching the ***/*Tests/*.csproj* glob pattern. Test results are saved in a *.trx* file at the location specified by the `--results-directory` option. If any tests fail, the build fails and isn't deployed. + + > [!NOTE] + > To verify the unit tests work, modify *SimpleFeedReader.Tests\Services\NewsServiceTests.cs* to purposefully break one of the tests. For example, change `Assert.True(result.Count > 0);` to `Assert.False(result.Count > 0);` in the `Returns_News_Stories_Given_Valid_Uri` method. Commit and push the change to GitHub. The build is triggered and fails. The build pipeline status changes to **failed**. Revert the change, commit, and push again. The build succeeds. + +1. **Publish** — Executes the `dotnet publish --configuration release --output ` command to produce a *.zip* file with the artifacts to be deployed. The `--output` option specifies the publish location of the *.zip* file. That location is specified by passing a [predefined variable](/azure/devops/pipelines/build/variables) named `$(build.artifactstagingdirectory)`. That variable expands to a local path, such as *c:\agent\_work\1\a*, on the build agent. +1. **Publish Artifact** — Publishes the *.zip* file produced by the **Publish** task. The task accepts the *.zip* file location as a parameter, which is the predefined variable `$(build.artifactstagingdirectory)`. The *.zip* file is published as a folder named *drop*. + +Click the build definition's **Summary** link to view a history of builds with the definition: + +![Screenshot showing build definition history](media/cicd/build-definition-summary.png) + +On the resulting page, click the individual build for more details. + +![Screenshot showing build definition summary page](media/cicd/azure-devops-build-definition-summary.png) + +A summary of this specific build is displayed. Click the **published** link, and notice the *drop* folder produced by the build is listed: + +![Screenshot showing build definition artifacts - drop folder](media/cicd/azure-devops-build-artifacts.png) + +![Build Artifacts](media/cicd/azure-devops-artifacts.png) + +Use the ellipsis and click on **Downloads artifacts** links to inspect the published artifacts. + +### Release pipeline + +A release pipeline was created with the name *MyFirstProject-ASP.NET Core-CD*: + +![Screenshot showing release pipeline overview](media/cicd/azure-devops-release-pipeline.png) + +The two major components of the release pipeline are the **Artifacts** and the **Stages**. Clicking the box in the **Artifacts** section reveals the following panel: + +![Screenshot showing release pipeline artifacts](media/cicd/azure-devops-release-definition-tasks.png) + +The **Source (Build definition)** value represents the build definition to which this release pipeline is linked. The *.zip* file produced by a successful run of the build definition is provided to the *Production* environment for deployment to Azure. Click the *1 phase, 2 tasks* link in the *Production* environment box to view the release pipeline tasks: + +![Screenshot showing release pipeline tasks](media/cicd/release-definition-tasks.png) + +The release pipeline consists of two tasks: *Deploy Azure App Service to Slot* and *Manage Azure App Service - Slot Swap*. Clicking the first task reveals the following task configuration: + +![Screenshot showing release pipeline tasks](media/cicd/release-definition-tasks.png) + +The Azure subscription, service type, web app name, resource group, and deployment slot are defined in the deployment task. The **Package or folder** textbox holds the *.zip* file path to be extracted and deployed to the *staging* slot of the *mywebapp\* web app. + +Clicking the slot swap task reveals the following task configuration: + +![Screenshot showing release pipeline slot swap task](media/cicd/release-definition-task2.png) + +The subscription, resource group, service type, web app name, and deployment slot details are provided. The **Swap with Production** check box is checked. Consequently, the bits deployed to the *staging* slot are swapped into the production environment. + +## Additional reading + +* [Create your first pipeline with Azure Pipelines](/azure/devops/pipelines/get-started-yaml) +* [Build and .NET Core project](/azure/devops/pipelines/languages/dotnet-core) +* [Deploy a web app with Azure Pipelines](/azure/devops/pipelines/targets/webapp) + +>[!div class="step-by-step"] +>[Previous](deploying-to-app-service.md) +>[Next](actions-index.md) diff --git a/docs/architecture/devops-for-aspnet-developers/deploying-to-app-service.md b/docs/architecture/devops-for-aspnet-developers/deploying-to-app-service.md new file mode 100644 index 0000000000000..35790c5309d25 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/deploying-to-app-service.md @@ -0,0 +1,261 @@ +--- +title: Deploy an app to App Service - DevOps for ASP.NET Core Developers +author: CamSoper +description: Deploy an ASP.NET Core app to Azure App Service, the first step for DevOps for ASP.NET Core Developers. +ms.author: casoper +ms.custom: "devx-track-csharp, mvc, seodec18, devx-track-azurecli" +ms.date: 10/24/2018 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/deploy-to-app-service +--- +# Deploy an app to App Service + +[Azure App Service](/azure/app-service/) is Azure's web hosting platform. Deploying a web app to Azure App Service can be done manually or by an automated process. This section of the guide discusses deployment methods that can be triggered manually or by script using the command line, or triggered manually using Visual Studio. + +In this section, you'll accomplish the following tasks: + +> [!div class="checklist"] +> +> * Download and build the sample app. +> * Create an Azure App Service Web App using the Azure Cloud Shell. +> * Deploy the sample app to Azure using Git. +> * Deploy a change to the app using Visual Studio. +> * Add a staging slot to the web app. +> * Deploy an update to the staging slot. +> * Swap the staging and production slots. + +## Download and test the app + +The app used in this guide is a pre-built ASP.NET Core app, [Simple Feed Reader](https://github.com/dotnet-architecture/simple-feed-reader/). It's an ASP.NET Core Razor Pages app that uses the `Microsoft.SyndicationFeed.ReaderWriter` API to retrieve an RSS/Atom feed and display the news items in a list. + +Feel free to review the code, but it's important to understand that there's nothing special about this app. It's just a simple ASP.NET Core app for illustrative purposes. + +From a command shell, download the code, build the project, and run it as follows. + +> [!Note] +> Linux/macOS users should make appropriate changes for paths, e.g., using forward slash (`/`) rather than back slash (`\`).* + +1. Clone the code to a folder on your local machine. + + ```console + git clone https://github.com/dotnet-architecture/simple-feed-reader/ + ``` + +2. Change your working folder to the *simple-feed-reader* folder that was created. + + ```console + cd .\simple-feed-reader\SimpleFeedReader + ``` + +3. Restore the packages, and build the solution. + + ```dotnetcli + dotnet build + ``` + +4. Run the app. + + ```dotnetcli + dotnet run + ``` + + ![The dotnet run command is successful](./media/deploying-to-app-service/dotnet-run.png) + +5. Open a browser and navigate to `http://localhost:5000`. The app allows you to type or paste a syndication feed URL and view a list of news items. + + ![The app displaying the contents of an RSS feed](./media/deploying-to-app-service/app-in-browser.png) + +6. Once you're satisfied the app is working correctly, shut it down by pressing **Ctrl**+**C** in the command shell. + +## Create the Azure App Service Web App + +To deploy the app, you'll need to create an App Service [Web App](/azure/app-service/app-service-web-overview). After creation of the Web App, you'll deploy to it from your local machine using Git. + +1. Sign in to the [Azure Cloud Shell](https://shell.azure.com/bash). Note: When you sign in for the first time, Cloud Shell prompts to create a storage account for configuration files. Accept the defaults or provide a unique name. + +2. Use the Cloud Shell for the following steps. + + a. Declare a variable to store your web app's name. The name must be unique to be used in the default URL. Using the `$RANDOM` Bash function to construct the name guarantees uniqueness and results in the format `webappname99999`. + + ```console + webappname=mywebapp$RANDOM + ``` + + b. Create a resource group. Resource groups provide a means to aggregate Azure resources to be managed as a group. + + ```azurecli + az group create --location centralus --name AzureTutorial + ``` + + The `az` command invokes the [Azure CLI](/cli/azure/). The CLI can be run locally, but using it in the Cloud Shell saves time and configuration. + + c. Create an App Service plan in the S1 tier. An App Service plan is a grouping of web apps that share the same pricing tier. The S1 tier isn't free, but it's required for the staging slots feature. + + ```azurecli + az appservice plan create --name $webappname --resource-group AzureTutorial --sku S1 + ``` + + d. Create the web app resource using the App Service plan in the same resource group. + + ```azurecli + az webapp create --name $webappname --resource-group AzureTutorial --plan $webappname + ``` + + e. Set the deployment branch to `main` in the `appsettings` configuration. + + ```azurecli + az webapp config appsettings set --name $webappname --resource-group AzureTutorial --settings DEPLOYMENT_BRANCH=main + ``` + + f. Set the deployment credentials. These deployment credentials apply to all the web apps in your subscription. Don't use special characters in the user name. + + ```azurecli + az webapp deployment user set --user-name REPLACE_WITH_USER_NAME --password REPLACE_WITH_PASSWORD + ``` + + g. Configure the web app to accept deployments from local Git and display the *Git deployment URL*. **Note this URL for reference later**. + + ```azurecli + echo Git deployment URL: $(az webapp deployment source config-local-git --name $webappname --resource-group AzureTutorial --query url --output tsv) + ``` + + h. Display the *web app URL*. Browse to this URL to see the blank web app. **Note this URL for reference later**. + + ```console + echo Web app URL: http://$webappname.azurewebsites.net + ``` + +3. Using a command shell on your local machine, navigate to the web app's project folder (for example, *.\simple-feed-reader\SimpleFeedReader*). Execute the following commands to set up Git to push to the deployment URL: + + a. Add the remote URL to the local repository. + + ```console + git remote add azure-prod GIT_DEPLOYMENT_URL + ``` + + b. Push the local default branch (*main*) to the *azure-prod* remote's deployment branch (*main*). + + ```console + git push azure-prod main + ``` + + You'll be prompted for the deployment credentials you created earlier. Observe the output in the command shell. Azure builds the ASP.NET Core app remotely. + +4. In a browser, navigate to the *Web app URL* and note the app has been built and deployed. Additional changes can be committed to the local Git repository with `git commit`. These changes are pushed to Azure with the preceding `git push` command. + +## Deployment with Visual Studio + +> [!Note] +> This section applies to Windows only. Linux and macOS users should make the change described in step 2 below. Save the file, and commit the change to the local repository with `git commit`. Finally, push the change with `git push`, as in the first section.* + +The app has already been deployed from the command shell. Let's use Visual Studio's integrated tools to deploy an update to the app. Behind the scenes, Visual Studio accomplishes the same thing as the command line tooling, but within Visual Studio's familiar UI. + +1. Open *SimpleFeedReader.sln* in Visual Studio. +2. In Solution Explorer, open *Pages\Index.cshtml*. Change `

Simple Feed Reader

` to `

Simple Feed Reader - V2

`. +3. Press **Ctrl**+**Shift**+**B** to build the app. +4. In Solution Explorer, right-click on the project and click **Publish**. + + ![Screenshot showing Right-click, Publish](./media/deploying-to-app-service/publish.png) +5. Visual Studio can create a new App Service resource, but this update will be published over the existing deployment. In the **Pick a publish target** dialog, select **App Service** from the list on the left, and then select **Select Existing**. Click **Publish**. +6. In the **App Service** dialog, confirm that the Microsoft or Organizational account used to create your Azure subscription is displayed in the upper right. If it's not, click the drop-down and add it. +7. Confirm that the correct Azure **Subscription** is selected. For **View**, select **Resource Group**. Expand the **AzureTutorial** resource group and then select the existing web app. Click **OK**. + + ![Screenshot showing Publish App Service dialog](./media/deploying-to-app-service/publish-dialog.png) + +Visual Studio builds and deploys the app to Azure. Browse to the web app URL. Validate that the `

` element modification is live. + +![The app with the changed title](./media/deploying-to-app-service/app-v2.png) + +## Deployment slots + +Deployment slots support the staging of changes without impacting the app running in production. Once the staged version of the app is validated by a quality assurance team, the production and staging slots can be swapped. The app in staging is promoted to production in this manner. The following steps create a staging slot, deploy some changes to it, and swap the staging slot with production after verification. + +1. Sign in to the [Azure Cloud Shell](https://shell.azure.com/bash), if not already signed in. +2. Create the staging slot. + + a. Create a deployment slot with the name *staging*. + + ```azurecli + az webapp deployment slot create --name $webappname --resource-group AzureTutorial --slot staging + ``` + + b. Set the deployment branch to `main` in the `appsettings` configuration. + + ```azurecli + az webapp config appsettings set --name $webappname --resource-group AzureTutorial --slot staging --settings DEPLOYMENT_BRANCH=main + ``` + + c. Configure the staging slot to use deployment from local Git and get the **staging** deployment URL. **Note this URL for reference later**. + + ```azurecli + echo Git deployment URL for staging: $(az webapp deployment source config-local-git --name $webappname --resource-group AzureTutorial --slot staging --query url --output tsv) + ``` + + d. Display the staging slot's URL. Browse to the URL to see the empty staging slot. **Note this URL for reference later**. + + ```console + echo Staging web app URL: http://$webappname-staging.azurewebsites.net + ``` + +3. In a text editor or Visual Studio, modify *Pages/Index.cshtml* again so that the `

` element reads `

Simple Feed Reader - V3

` and save the file. + +4. Commit the file to the local Git repository, using either the **Changes** page in Visual Studio's *Team Explorer* tab, or by entering the following using the local machine's command shell: + + ```console + git commit -a -m "upgraded to V3" + ``` + +5. Using the local machine's command shell, add the staging deployment URL as a Git remote and push the committed changes: + + a. Add the remote URL for staging to the local Git repository. + + ```console + git remote add azure-staging + ``` + + b. Push the local default branch (*main*) to the *azure-staging* remote's deployment branch (*main*). + + ```console + git push azure-staging main + ``` + + Wait while Azure builds and deploys the app. + +6. To verify that V3 has been deployed to the staging slot, open two browser windows. In one window, navigate to the original web app URL. In the other window, navigate to the staging web app URL. The production URL serves V2 of the app. The staging URL serves V3 of the app. + + ![Screenshot comparing the browser windows](./media/deploying-to-app-service/ready-to-swap.png) + +7. In the Cloud Shell, swap the verified/warmed-up staging slot into production. + + ```azurecli + az webapp deployment slot swap --name $webappname --resource-group AzureTutorial --slot staging + ``` + +8. Verify that the swap occurred by refreshing the two browser windows. + + ![Comparing the browser windows after the swap](./media/deploying-to-app-service/swapped.png) + +## Summary + +In this section, the following tasks were completed: + +* Downloaded and built the sample app. +* Created an Azure App Service Web App using the Azure Cloud Shell. +* Deployed the sample app to Azure using Git. +* Deployed a change to the app using Visual Studio. +* Added a staging slot to the web app. +* Deployed an update to the staging slot. +* Swapped the staging and production slots. + +In the next section, you'll learn how to build a DevOps pipeline with Azure Pipelines. + +## Additional reading + +* [Web Apps overview](/azure/app-service/app-service-web-overview) +* [Build a .NET Core and SQL Database web app in Azure App Service](/azure/app-service/app-service-web-tutorial-dotnetcore-sqldb) +* [Configure deployment credentials for Azure App Service](/azure/app-service/app-service-deployment-credentials) +* [Set up staging environments in Azure App Service](/azure/app-service/web-sites-staged-publishing) + +>[!div class="step-by-step"] +>[Previous](tools-and-downloads.md) +>[Next](cicd.md) diff --git a/docs/architecture/devops-for-aspnet-developers/index.md b/docs/architecture/devops-for-aspnet-developers/index.md new file mode 100644 index 0000000000000..67a790dc60631 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/index.md @@ -0,0 +1,107 @@ +--- +title: DevOps for ASP.NET Core Developers +author: CamSoper +description: A guide that provides end-to-end guidance on building a DevOps pipeline for an ASP.NET Core app hosted in Azure. +ms.author: casoper +ms.date: 04/13/2021 +ms.custom: "devx-track-csharp, mvc, seodec18" +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/index +--- +# DevOps for ASP.NET Core Developers + +[![Cover Image](./media/cover-large.png)](https://aka.ms/devopsbook) + +**EDITION v1.1.0** + +Refer [changelog](https://aka.ms/devops-ebook-changelog) for the book updates and community contributions. + +This guide is available as a [downloadable PDF e-book](https://aka.ms/devopsbook). + +PUBLISHED BY + +Microsoft Developer Division, .NET, and Visual Studio product teams + +A division of Microsoft Corporation + +One Microsoft Way + +Redmond, Washington 98052-6399 + +Copyright © 2021 by Microsoft Corporation + +All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher. + +This book is provided "as-is" and expresses the author's views and opinions. The views, opinions, and information expressed in this book, including URL and other Internet website references, may change without notice. + +Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is intended or should be inferred. + +Microsoft and the trademarks listed at on the "Trademarks" webpage are trademarks of the Microsoft group of companies. + +Mac and macOS are trademarks of Apple Inc. + +The Docker whale logo is a registered trademark of Docker, Inc. Used by permission. + +All other marks and logos are property of their respective owners. + +## Credits + +Authors: + +> [Cam Soper](https://twitter.com/camsoper) +> +> [Scott Addie](https://twitter.com/scottaddie) +> +> [Colin Dembovsky](https://twitter.com/colindembovsky) + +## Welcome + +Welcome to the Azure Development Lifecycle guide for .NET! This guide introduces the basic concepts of building a development lifecycle around Azure using .NET tools and processes. After finishing this guide, you'll reap the benefits of a mature DevOps toolchain. + +## Who this guide is for + +You should be an experienced ASP.NET Core developer (200-300 level). You don't need to know anything about Azure, as we'll cover that in this introduction. This guide may also be useful for DevOps engineers who are more focused on operations than development. + +This guide targets Windows developers. However, Linux and macOS are fully supported by .NET Core. To adapt this guide for Linux/macOS, watch for callouts for Linux/macOS differences. + +## What this guide doesn't cover + +This guide is focused on an end-to-end continuous deployment experience for .NET developers. It's not an exhaustive guide to all things Azure, and it doesn't focus extensively on .NET APIs for Azure services. The emphasis is all around continuous integration, deployment, monitoring, and debugging. Near the end of the guide, recommendations for next steps are offered. Included in the suggestions are Azure platform services that are useful to ASP.NET Core developers. + +## What's in this guide + +### [Tools and downloads](xref:azure/devops/tools-and-downloads) + +Learn where to acquire the tools used in this guide. + +### [Deploy to App Service](xref:azure/devops/deploy-to-app-service) + +Learn the various methods for deploying an ASP.NET Core app to Azure App Service. + +### [Continuous integration and deployment with Azure DevOps](xref:azure/devops/cicd) + +Build an end-to-end continuous integration and deployment solution for your ASP.NET Core app with GitHub, Azure DevOps Services, and Azure. + +### [Continuous integration and deployment with GitHub Actions](xref:azure/devops/github-actions) + +Build an end-to-end continuous integration and deployment solution for your ASP.NET Core app with GitHub, GitHub Actions, and Azure, including code scanning for security and quality using CodeQL. + +### [Monitor and debug](xref:azure/devops/monitor) + +Use Azure's tools to monitor, troubleshoot, and tune your application. + +### [Next steps](xref:azure/devops/next-steps) + +Other learning paths for the ASP.NET Core developer learning Azure. + +## Additional introductory reading + +If this is your first exposure to cloud computing, these articles explain the basics. + +* [What is Cloud Computing?](https://azure.microsoft.com/overview/what-is-cloud-computing/) +* [Examples of Cloud Computing](https://azure.microsoft.com/overview/examples-of-cloud-computing/) +* [What is IaaS?](https://azure.microsoft.com/overview/what-is-iaas/) +* [What is PaaS?](https://azure.microsoft.com/overview/what-is-paas/) + +>[!div class="step-by-step"] +>[Next](tools-and-downloads.md) diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success-logs.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success-logs.jpg new file mode 100644 index 0000000000000..9a9bf69c406cb Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success-logs.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success.jpg new file mode 100644 index 0000000000000..ce2c63da72ecc Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/build-action-success.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/click-edit.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/click-edit.jpg new file mode 100644 index 0000000000000..679807e767738 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/click-edit.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/commit-workflow.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/commit-workflow.jpg new file mode 100644 index 0000000000000..0f333eff5fab4 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/commit-workflow.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/copy-snippet.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/copy-snippet.jpg new file mode 100644 index 0000000000000..243aae76e328e Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/copy-snippet.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/new-action.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/new-action.jpg new file mode 100644 index 0000000000000..a3a5fce20afc3 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/new-action.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/search-upload-artifact.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/search-upload-artifact.jpg new file mode 100644 index 0000000000000..de7618cc2dfec Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/search-upload-artifact.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/build/view-uploaded-artifact.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/build/view-uploaded-artifact.jpg new file mode 100644 index 0000000000000..3ef8255a9e49c Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/build/view-uploaded-artifact.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/alert.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/alert.jpg new file mode 100644 index 0000000000000..9ebbec9af3429 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/alert.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-config.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-config.jpg new file mode 100644 index 0000000000000..49966cd27958a Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-config.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-run.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-run.jpg new file mode 100644 index 0000000000000..2ca7f8d5e9ab3 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/codeql-run.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/create-new-file.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/create-new-file.jpg new file mode 100644 index 0000000000000..4c82696349566 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/create-new-file.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/dismiss.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/dismiss.jpg new file mode 100644 index 0000000000000..020201158b5cd Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/dismiss.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/no-results.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/no-results.jpg new file mode 100644 index 0000000000000..d3d70984d3b5a Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/no-results.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/security-alerts.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/security-alerts.jpg new file mode 100644 index 0000000000000..b6fe346171311 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/security-alerts.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/setup-workflow.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/setup-workflow.jpg new file mode 100644 index 0000000000000..5cb1d432e4f6d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/setup-workflow.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/start-commit.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/start-commit.jpg new file mode 100644 index 0000000000000..e21082cd0c3e3 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/codeql/start-commit.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-env-secret.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-env-secret.jpg new file mode 100644 index 0000000000000..759a4bb7e1957 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-env-secret.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-repo-secret.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-repo-secret.jpg new file mode 100644 index 0000000000000..62ae491540b4d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/add-repo-secret.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/approval.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/approval.jpg new file mode 100644 index 0000000000000..26a4fde4942e9 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/approval.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/azure-credentials.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/azure-credentials.jpg new file mode 100644 index 0000000000000..e70d012bbc265 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/azure-credentials.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deploy-to-staging-completed.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deploy-to-staging-completed.jpg new file mode 100644 index 0000000000000..555c977a2a1b1 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deploy-to-staging-completed.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-prod.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-prod.jpg new file mode 100644 index 0000000000000..7de4c9a8421ae Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-prod.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-staging.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-staging.jpg new file mode 100644 index 0000000000000..6acf67cc3b51d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployed-to-staging.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployments.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployments.jpg new file mode 100644 index 0000000000000..fc5bd96002a26 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/deployments.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-protection-rule.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-protection-rule.jpg new file mode 100644 index 0000000000000..746ccaae3a7d7 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-protection-rule.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-secrets.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-secrets.jpg new file mode 100644 index 0000000000000..a8a4e308280ce Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/env-secrets.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/manual-dispatch.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/manual-dispatch.jpg new file mode 100644 index 0000000000000..57c622a844a0c Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/manual-dispatch.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/new-env.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/new-env.jpg new file mode 100644 index 0000000000000..1cfdf9f3c281d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/new-env.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/pre-prod-env.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/pre-prod-env.jpg new file mode 100644 index 0000000000000..7a7ae63825ffc Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/pre-prod-env.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/prod-deploy-complete.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/prod-deploy-complete.jpg new file mode 100644 index 0000000000000..5db34cafb6885 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/prod-deploy-complete.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/settings-in-both-envs.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/settings-in-both-envs.jpg new file mode 100644 index 0000000000000..e2cb6b489a843 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/settings-in-both-envs.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/waiting-for-approval.jpg b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/waiting-for-approval.jpg new file mode 100644 index 0000000000000..f501a357eef56 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/actions/deploy/waiting-for-approval.jpg differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts-lightning-bolt.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts-lightning-bolt.png new file mode 100644 index 0000000000000..97392e4765493 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts-lightning-bolt.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts.png new file mode 100644 index 0000000000000..a4db47d2c042a Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-artifacts.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-authz.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-authz.png new file mode 100644 index 0000000000000..564ea8d1a989e Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-authz.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-agent-pool.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-agent-pool.png new file mode 100644 index 0000000000000..ad8712bdc13d6 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-agent-pool.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-artifacts.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-artifacts.png new file mode 100644 index 0000000000000..6e5871a48de8b Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-artifacts.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-summary.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-summary.png new file mode 100644 index 0000000000000..e047018202f5b Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-summary.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-tasks.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-tasks.png new file mode 100644 index 0000000000000..2e133717f040f Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-build-definition-tasks.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-classic-editor.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-classic-editor.png new file mode 100644 index 0000000000000..a78f7538cf010 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-classic-editor.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-pipeline.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-pipeline.png new file mode 100644 index 0000000000000..c41904a3e4c97 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-pipeline.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-release.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-release.png new file mode 100644 index 0000000000000..18853e97fb3e5 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-create-release.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-enable-ci.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-enable-ci.png new file mode 100644 index 0000000000000..e1868eeb68155 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-enable-ci.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-environment-name-textbox.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-environment-name-textbox.png new file mode 100644 index 0000000000000..f14ece36fb47a Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-environment-name-textbox.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-ms-hosted-agent.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-ms-hosted-agent.png new file mode 100644 index 0000000000000..a6e9d185621a1 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-ms-hosted-agent.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-new-release-pipeline.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-new-release-pipeline.png new file mode 100644 index 0000000000000..d0451f845173e Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-new-release-pipeline.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-pipepine-build.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-pipepine-build.png new file mode 100644 index 0000000000000..9fa38586a29ee Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-pipepine-build.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-production-link.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-production-link.png new file mode 100644 index 0000000000000..94a8c8344d239 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-production-link.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-add-artifacts.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-add-artifacts.png new file mode 100644 index 0000000000000..509a391b97739 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-add-artifacts.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-name.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-name.png new file mode 100644 index 0000000000000..953e501f198b6 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-name.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-tasks.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-tasks.png new file mode 100644 index 0000000000000..4d4ebbda82ce0 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-definition-tasks.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline-run.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline-run.png new file mode 100644 index 0000000000000..d5b5e7f7a7f8b Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline-run.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline.png new file mode 100644 index 0000000000000..47de90f08bf4c Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-pipeline.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-select-agent-pool.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-select-agent-pool.png new file mode 100644 index 0000000000000..1cd57a670b3fa Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-release-select-agent-pool.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-build.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-build.png new file mode 100644 index 0000000000000..3ab7389d58305 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-build.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-modal.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-modal.png new file mode 100644 index 0000000000000..a9a1ef012b67e Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-save-modal.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-source.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-source.png new file mode 100644 index 0000000000000..4954c126022ee Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-source.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-template.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-template.png new file mode 100644 index 0000000000000..82de216e3cc84 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-select-template.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-self-hosted-agent.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-self-hosted-agent.png new file mode 100644 index 0000000000000..63623efb6c52f Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-self-hosted-agent.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-template-selection.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-template-selection.png new file mode 100644 index 0000000000000..3113a3ac32f34 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/azure-devops-template-selection.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/build-definition-summary.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/build-definition-summary.png new file mode 100644 index 0000000000000..2aa572e6cc695 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/build-definition-summary.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/enable-ci.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/enable-ci.png new file mode 100644 index 0000000000000..158a3a0545cd4 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/enable-ci.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/github-new-repo.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/github-new-repo.png new file mode 100644 index 0000000000000..b2fcaf5624221 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/github-new-repo.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/portal-search-box.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/portal-search-box.png new file mode 100644 index 0000000000000..028d7ec92fba2 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/portal-search-box.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-task2.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-task2.png new file mode 100644 index 0000000000000..e2372d7a569ff Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-task2.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-tasks.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-tasks.png new file mode 100644 index 0000000000000..491be934bc277 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/release-definition-tasks.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cicd/updated-app-v4.png b/docs/architecture/devops-for-aspnet-developers/media/cicd/updated-app-v4.png new file mode 100644 index 0000000000000..365c31a0c3d3d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cicd/updated-app-v4.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/cover-large.png b/docs/architecture/devops-for-aspnet-developers/media/cover-large.png new file mode 100644 index 0000000000000..7929e7a272537 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/cover-large.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-in-browser.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-in-browser.png new file mode 100644 index 0000000000000..1dc62dffbdcc8 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-in-browser.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-v2.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-v2.png new file mode 100644 index 0000000000000..db070ad92ba3a Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/app-v2.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/dotnet-run.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/dotnet-run.png new file mode 100644 index 0000000000000..36655be17901d Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/dotnet-run.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish-dialog.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish-dialog.png new file mode 100644 index 0000000000000..9783ebbdfd837 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish-dialog.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish.png new file mode 100644 index 0000000000000..8b301f1a8fda2 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/publish.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/ready-to-swap.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/ready-to-swap.png new file mode 100644 index 0000000000000..779597416302b Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/ready-to-swap.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/swapped.png b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/swapped.png new file mode 100644 index 0000000000000..37f8b86915a39 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/deploying-to-app-service/swapped.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/alerts.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/alerts.png new file mode 100644 index 0000000000000..4f1038605acd0 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/alerts.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights-overview.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights-overview.png new file mode 100644 index 0000000000000..7b22035bf5007 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights-overview.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights.png new file mode 100644 index 0000000000000..12434a0964ee9 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/app-insights.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/log-stream.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/log-stream.png new file mode 100644 index 0000000000000..b65ab37053233 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/log-stream.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/logging.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/logging.png new file mode 100644 index 0000000000000..cec2f4b2ad68f Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/logging.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights-done.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights-done.png new file mode 100644 index 0000000000000..d208be06bcf8f Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights-done.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights.png new file mode 100644 index 0000000000000..9cf9222902318 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/new-app-insights.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/overview.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/overview.png new file mode 100644 index 0000000000000..2589c1dc57cc1 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/overview.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/media/monitoring/wizards.png b/docs/architecture/devops-for-aspnet-developers/media/monitoring/wizards.png new file mode 100644 index 0000000000000..6bc4e4c92b956 Binary files /dev/null and b/docs/architecture/devops-for-aspnet-developers/media/monitoring/wizards.png differ diff --git a/docs/architecture/devops-for-aspnet-developers/monitoring.md b/docs/architecture/devops-for-aspnet-developers/monitoring.md new file mode 100644 index 0000000000000..b37512f591803 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/monitoring.md @@ -0,0 +1,147 @@ +--- +title: Monitor and debug - DevOps for ASP.NET Core Developers +author: CamSoper +description: Monitoring and debugging your code as part of a DevOps solution with ASP.NET Core and Azure +ms.author: casoper +ms.custom: "devx-track-csharp, mvc, seodec18" +ms.date: 07/10/2019 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/monitor +--- +# Monitor and debug + +Having deployed the app and built a DevOps pipeline, it's important to understand how to monitor and troubleshoot the app. + +In this section, you'll complete the following tasks: + +> [!div class="checklist"] +> +> * Find basic monitoring and troubleshooting data in the Azure portal +> * Learn how Azure Monitor provides a deeper look at metrics across all Azure services +> * Connect the web app with Application Insights for app profiling +> * Turn on logging and learn where to download logs +> * Stream logs in real time +> * Learn where to set up alerts +> * Learn about remote debugging Azure App Service web apps. + +## Basic monitoring and troubleshooting + +App Service web apps are easily monitored in real time. The Azure portal renders metrics in easy-to-understand charts and graphs. + +1. Open the [Azure portal](https://portal.azure.com), and then navigate to the *mywebapp\* App Service. + +1. The **Overview** tab displays useful "at-a-glance" information, including graphs displaying recent metrics. + + ![Screenshot showing overview panel](./media/monitoring/overview.png) + + * **Http 5xx**: Count of server-side errors, usually exceptions in ASP.NET Core code. + * **Data In**: Data ingress coming into your web app. + * **Data Out**: Data egress from your web app to clients. + * **Requests**: Count of HTTP requests. + * **Average Response Time**: Average time for the web app to respond to HTTP requests. + + Several self-service tools for troubleshooting and optimization are also found on this page. + + ![Screenshot showing self-service tools](./media/monitoring/wizards.png) + + * **Diagnose and solve problems** is a self-service troubleshooter. + * **Application Insights** is for profiling performance and app behavior, and is discussed later in this section. + * **App Service Advisor** makes recommendations to tune your app experience. + +## Advanced monitoring + +[Azure Monitor](/azure/monitoring-and-diagnostics/) is the centralized service for monitoring all metrics and setting alerts across Azure services. Within Azure Monitor, administrators can granularly track performance and identify trends. Each Azure service offers its own [set of metrics](/azure/monitoring-and-diagnostics/monitoring-supported-metrics#microsoftwebsites-excluding-functions) to Azure Monitor. + +## Profile with Application Insights + +[Application Insights](/azure/application-insights/app-insights-overview) is an Azure service for analyzing the performance and stability of web apps and how users use them. The data from Application Insights is broader and deeper than that of Azure Monitor. The data can provide developers and administrators with key information for improving apps. Application Insights can be added to an Azure App Service resource without code changes. + +1. Open the [Azure portal](https://portal.azure.com), and then navigate to the *mywebapp\* App Service. +1. From the **Overview** tab, click the **Application Insights** tile. + + ![Application Insights tile](./media/monitoring/app-insights.png) + +1. Select the **Create new resource** radio button. Use the default resource name, and select the location for the Application Insights resource. The location doesn't need to match that of your web app. + + ![Application Insights setup](./media/monitoring/new-app-insights.png) + +1. For **Runtime/Framework**, select **ASP.NET Core**. Accept the default settings. +1. Select **OK**. If prompted to confirm, select **Continue**. +1. After the resource has been created, click the name of Application Insights resource to navigate directly to the Application Insights page. + + ![New Application Insights resource is ready](./media/monitoring/new-app-insights-done.png) + +As the app is used, data accumulates. Select **Refresh** to reload the blade with new data. + +![Application Insights overview tab](./media/monitoring/app-insights-overview.png) + +Application Insights provides useful server-side information with no additional configuration. To get the most value from Application Insights, [instrument your app with the Application Insights SDK](/azure/application-insights/app-insights-asp-net-core). When properly configured, the service provides end-to-end monitoring across the web server and browser, including client-side performance. For more information, see the [Application Insights documentation](/azure/application-insights/app-insights-overview). + +## Logging + +Web server and app logs are disabled by default in Azure App Service. Enable the logs with the following steps: + +1. Open the [Azure portal](https://portal.azure.com), and navigate to the *mywebapp\* App Service. +1. In the menu to the left, scroll down to the **Monitoring** section. Select **Diagnostics logs**. + + ![Diagnostic logs link](./media/monitoring/logging.png) + +1. Turn on **Application Logging (Filesystem)**. If prompted, click the box to install the extensions to enable app logging in the web app. +1. Set **Web server logging** to **File System**. +1. Enter the **Retention Period** in days. For example, 30. +1. Click **Save**. + +ASP.NET Core and web server (App Service) logs are generated for the web app. They can be downloaded using the FTP/FTPS information displayed. The password is the same as the deployment credentials created earlier in this guide. The logs can be [streamed directly to your local machine with PowerShell or Azure CLI](/azure/app-service/web-sites-enable-diagnostic-log#download). Logs can also be [viewed in Application Insights](/azure/app-service/web-sites-enable-diagnostic-log#how-to-view-logs-in-application-insights). + +## Log streaming + +App and web server logs can be streamed in real time through the portal. + +1. Open the [Azure portal](https://portal.azure.com), and navigate to the *mywebapp\* App Service. +1. In the menu to the left, scroll down to the **Monitoring** section and select **Log stream**. + + ![Screenshot showing log stream link](./media/monitoring/log-stream.png) + +Logs can also be [streamed via Azure CLI or Azure PowerShell](/azure/app-service/web-sites-enable-diagnostic-log#streamlogs), including through the Cloud Shell. + +## Alerts + +Azure Monitor also provides [real time alerts](/azure/monitoring-and-diagnostics/insights-alerts-portal) based on metrics, administrative events, and other criteria. + +> [!NOTE] +> Currently alerting on web app metrics is only available in the Alerts (classic) service. + +The [Alerts (classic) service](/azure/monitoring-and-diagnostics/monitor-quick-resource-metric-alert-portal) can be found in Azure Monitor or under the **Monitoring** section of the App Service settings. + +![Alerts (classic) link](./media/monitoring/alerts.png) + +## Live debugging + +Azure App Service can be [debugged remotely with Visual Studio](/azure/app-service/web-sites-dotnet-troubleshoot-visual-studio#remotedebug) when logs don't provide enough information. However, remote debugging requires the app to be compiled with debug symbols. Debugging shouldn't be done in production, except as a last resort. + +## Conclusion + +In this section, you completed the following tasks: + +> [!div class="checklist"] +> +> * Find basic monitoring and troubleshooting data in the Azure portal +> * Learn how Azure Monitor provides a deeper look at metrics across all Azure services +> * Connect the web app with Application Insights for app profiling +> * Turn on logging and learn where to download logs +> * Stream logs in real time +> * Learn where to set up alerts +> * Learn about remote debugging Azure App Service web apps. + +## Additional reading + +* [Troubleshooting ASP.NET Core on Azure App Service and IIS](/aspnet/core/test/troubleshoot-azure-iis) +* [Common errors reference for Azure App Service and IIS with ASP.NET Core](/aspnet/core/host-and-deploy/azure-iis-errors-reference) +* [Monitor Azure web app performance with Application Insights](/azure/application-insights/app-insights-azure-web-apps) +* [Enable diagnostics logging for web apps in Azure App Service](/azure/app-service/web-sites-enable-diagnostic-log) +* [Troubleshoot a web app in Azure App Service using Visual Studio](/azure/app-service/web-sites-dotnet-troubleshoot-visual-studio) +* [Create classic metric alerts in Azure Monitor for Azure services - Azure portal](/azure/monitoring-and-diagnostics/insights-alerts-portal) + +>[!div class="step-by-step"] +>[Previous](actions-codeql.md) +>[Next](next-steps.md) diff --git a/docs/architecture/devops-for-aspnet-developers/next-steps.md b/docs/architecture/devops-for-aspnet-developers/next-steps.md new file mode 100644 index 0000000000000..88dd2866bf160 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/next-steps.md @@ -0,0 +1,44 @@ +--- +title: Next steps - DevOps for ASP.NET Core Developers +author: CamSoper +description: Additional learning paths for DevOps for ASP.NET Core Developers. +ms.author: casoper +ms.custom: "devx-track-csharp, mvc, seodec18" +ms.date: 10/24/2018 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/next-steps +--- +# Next steps + +In this guide, you created a DevOps pipeline for an ASP.NET Core sample app. Congratulations! We hope you enjoyed learning to publish ASP.NET Core web apps to Azure App Service and automate the continuous integration of changes. + +Beyond web hosting and DevOps, Azure has a wide array of Platform-as-a-Service (PaaS) services useful to ASP.NET Core developers. This section gives a brief overview of some of the most commonly used services. + +## Storage and databases + +[Redis Cache](/azure/redis-cache/) is high-throughput, low-latency data caching available as a service. It can be used for caching page output, reducing database requests, and providing ASP.NET Core session state across multiple instances of an app. + +[Azure Storage](/azure/storage/) is Azure's massively scalable cloud storage. Developers can take advantage of [Queue Storage](/azure/storage/queues/storage-queues-introduction) for reliable message queuing, and [Table Storage](/azure/storage/tables/table-storage-overview) is a NoSQL key-value store designed for rapid development using massive, semi-structured data sets. + +[Azure SQL Database](/azure/sql-database/) provides familiar relational database functionality as a service using the Microsoft SQL Server Engine. + +[Cosmos DB](/azure/cosmos-db/) globally distributed, multi-model NoSQL database service. Multiple APIs are available, including SQL API (formerly called DocumentDB), Cassandra, and MongoDB. + +## Identity + +[Azure Active Directory](/azure/active-directory/) and [Azure Active Directory B2C](/azure/active-directory-b2c/) are both identity services. Azure Active Directory is designed for enterprise scenarios and enables Azure AD B2B (business-to-business) collaboration, while Azure Active Directory B2C is intended business-to-customer scenarios, including social network sign-in. + +## Mobile + +[Notification Hubs](/azure/notification-hubs/) is a multi-platform, scalable push-notification engine to quickly send millions of messages to apps running on various types of devices. + +## Web infrastructure + +[Azure Container Service](/azure/aks/) manages your hosted Kubernetes environment, making it quick and easy to deploy and manage containerized apps without container orchestration expertise. + +[Azure Search](/azure/search/) is used to create an enterprise search solution over private, heterogenous content. + +[Service Fabric](/azure/service-fabric/) is a distributed systems platform that makes it easy to package, deploy, and manage scalable and reliable microservices and containers. + +>[!div class="step-by-step"] +>[Previous](monitoring.md) diff --git a/docs/architecture/devops-for-aspnet-developers/toc.yml b/docs/architecture/devops-for-aspnet-developers/toc.yml new file mode 100644 index 0000000000000..d62938126d973 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/toc.yml @@ -0,0 +1,27 @@ +- name: "DevOps for ASP.NET Core Developers" + href: index.md + items: + - name: Tools and downloads + href: tools-and-downloads.md + - name: Deploy an app to App Service + href: deploying-to-app-service.md + - name: Continuous integration and deployment (CI/CD) + items: + - name: Azure DevOps + href: cicd.md + - name: GitHub Actions + items: + - name: Overview + href: actions-index.md + - name: Comparison of GitHub Actions and Azure Pipelines + href: actions-vs-pipelines.md + - name: Basic build workflow + href: actions-build.md + - name: Deployment workflow + href: actions-deploy.md + - name: Secure .NET code with CodeQL + href: actions-codeql.md + - name: Monitor and debug + href: monitoring.md + - name: Next steps + href: next-steps.md diff --git a/docs/architecture/devops-for-aspnet-developers/tools-and-downloads.md b/docs/architecture/devops-for-aspnet-developers/tools-and-downloads.md new file mode 100644 index 0000000000000..c1ff040548821 --- /dev/null +++ b/docs/architecture/devops-for-aspnet-developers/tools-and-downloads.md @@ -0,0 +1,46 @@ +--- +title: Tools and downloads - DevOps for ASP.NET Core Developers +author: CamSoper +description: Tools and downloads required for DevOps for ASP.NET Core Developers. +ms.author: casoper +ms.custom: "devx-track-csharp, mvc, seodec18" +ms.date: 10/24/2018 +no-loc: [appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] +uid: azure/devops/tools-and-downloads +--- +# Tools and downloads + +Azure has several interfaces for provisioning and managing resources, such as the [Azure portal](https://portal.azure.com), [Azure CLI](/cli/azure/), [Azure PowerShell](/powershell/azure/overview), [Azure Cloud Shell](https://shell.azure.com/bash), and Visual Studio. This guide takes a minimalist approach and uses the Azure Cloud Shell whenever possible to reduce the steps required. However, the Azure portal must be used for some portions. + +## Prerequisites + +The following subscriptions are required: + +* Azure — If you don't have an account, [get a free trial](https://azure.microsoft.com/free/dotnet/). +* Azure DevOps Services — your Azure DevOps subscription and organization is created in Chapter 4. +* GitHub — If you don't have an account, [sign up for free](https://github.com/join). + +The following tools are required: + +* [Git](https://git-scm.com/downloads) — A fundamental understanding of Git is recommended for this guide. Review the [Git documentation](https://git-scm.com/doc), specifically [git remote](https://git-scm.com/docs/git-remote) and [git push](https://git-scm.com/docs/git-push). +* [.NET Core SDK](https://dotnet.microsoft.com/download/) — Version 2.1.300 or later is required to build and run the sample app. If Visual Studio is installed with the **.NET Core cross-platform development** workload, the .NET Core SDK is already installed. + + Verify your .NET Core SDK installation. Open a command shell, and run the following command: + + ```dotnetcli + dotnet --version + ``` + +## Recommended tools (Windows only) + +* [Visual Studio](https://visualstudio.microsoft.com)'s robust Azure tools provide a GUI for most of the functionality described in this guide. Any edition of Visual Studio will work, including the free Visual Studio Community Edition. The tutorials are written to demonstrate development, deployment, and DevOps both with and without Visual Studio. + + Confirm that Visual Studio has the following [workloads](/visualstudio/install/modify-visual-studio) installed: + + * ASP.NET and web development + * Azure development + * .NET Core cross-platform development + +>[!div class="step-by-step"] +>[Previous](index.md) +>[Next](deploying-to-app-service.md) diff --git a/docs/architecture/index.yml b/docs/architecture/index.yml index 8e6563871cb04..4830ad077487c 100644 --- a/docs/architecture/index.yml +++ b/docs/architecture/index.yml @@ -66,9 +66,9 @@ landingContent: - linkListType: concept links: - text: Containerized Docker application lifecycle with Microsoft platform and tools - url: containerized-lifecycle/index.md - - text: ASP.NET Core DevOps with Azure - url: /aspnet/core/azure/devops/ + url: containerized-lifecycle/index.md + - text: DevOps for ASP.NET Core Developers + url: devops-for-aspnet-developers/index.md # Card - title: Modernize desktop apps diff --git a/docs/architecture/toc.yml b/docs/architecture/toc.yml index c61454141752e..42e1787e66f78 100644 --- a/docs/architecture/toc.yml +++ b/docs/architecture/toc.yml @@ -13,6 +13,8 @@ href: blazor-for-web-forms-developers/ - name: Containerized Docker application lifecycle with Microsoft platform and tools href: containerized-lifecycle/ + - name: DevOps for ASP.NET Core Developers + href: devops-for-aspnet-developers/ - name: Modernize existing .NET applications with Azure cloud and Windows Containers href: modernize-with-azure-containers/ - name: "Modernizing desktop apps on Windows 10 with .NET 5"