Skip to content

Commit 069054c

Browse files
GeekTrainerCopilot
andcommitted
Simplify deploy exercises: single deploy with branch rulesets
Replace staging/production dual-environment pattern with a single deploy workflow gated by branch rulesets. Add manual deploy workflow for rollbacks. This reduces workshop complexity while teaching the same CI/CD concepts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b0580fa commit 069054c

3 files changed

Lines changed: 134 additions & 135 deletions

File tree

‎content/github-actions/6-deploy-azure.md‎

Lines changed: 40 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ With CI in place, it's time for CD — continuous deployment or continuous deliv
77

88
## Scenario
99

10-
With the prototype built, the shelter is ready to share their application with the world! They want to ensure last minute testing is done on the application before it's deployed to production.
10+
With the prototype built, the shelter is ready to share their application with the world! They want to deploy automatically whenever code is pushed to `main` — but only after CI passes.
1111

1212
## Background
1313

@@ -19,26 +19,12 @@ Secrets are exactly that - secret. These are passwords and other values you don'
1919

2020
Variables, on the other hand, are designed to be public values. They're settings like URLs or names, or other values that aren't sensitive. Variables can be both read and written. Use variables whenever you need the ability to configure a value outside a workflow.
2121

22-
### Environments
22+
### Protecting production
2323

24-
There's many approaches to deployment of an application. A classic is a **staging** > **production** setup, where **staging** is as close to mimicking the real world as possible, and **production** is, well, the actual application. By using this strategy it allows for any last checks to be performed before opening the doors to the public.
24+
There are several strategies for ensuring only validated code reaches production. In a later exercise we'll configure **branch rulesets** to require CI checks and pull request reviews before code can be merged to `main`. Since our deploy workflow only triggers on pushes to `main`, this creates a natural gate: code must pass CI and be reviewed before it can be deployed.
2525

26-
Typically each environment will have its own configuration - its own server, URLs, databases, etc. Deploying to each will typically require different configurations. Actions supports this through the use of environments. With an environment you can create a set of secrets or variables for each environment, ensuring the right ones are used at the right time.
27-
28-
Environments can have deployment rules, which allow you to control when a workflow is allowed to use a particular environment. Sticking with the staging/production approach, you'll typically have a broader set of team members who have permissions to deploy to staging, but limit those who can deploy to production. In our scenario, we're going to allow anyone to deploy to staging, but you'll be the only one who's allowed to deploy to production.
29-
30-
## Create your environments
31-
32-
1. Navigate to your repository on GitHub.
33-
2. Select **Settings** > **Environments**.
34-
3. Select **New environment**, name it `staging`, and select **Configure environment**. No additional rules are needed for now — select **Save protection rules**.
35-
4. Return to **Settings** > **Environments** and select **New environment** again.
36-
5. Name it `production` and select **Configure environment**.
37-
6. Under **Deployment protection rules**, check **Required reviewers**.
38-
7. Add yourself as a required reviewer and select **Save protection rules**.
39-
40-
> [!NOTE]
41-
> In the next steps, `azd` will automatically configure OIDC credentials and store them as secrets in your repository. You don't need to manually create any Azure credentials.
26+
> [!TIP]
27+
> GitHub also supports **environments** with deployment protection rules (like manual approval gates). Environments are a powerful option when you need separate staging and production deployments — but for this workshop, branch rulesets give us the same safety with less setup. See the [environments documentation][environments-docs] to explore that approach on your own.
4228
4329
## Install and initialize azd
4430

@@ -51,14 +37,28 @@ Let's set up the Azure Developer CLI and scaffold the infrastructure for our pro
5137
curl -fsSL https://aka.ms/install-azd.sh | bash
5238
```
5339

54-
3. Initialize the project by running:
40+
3. Log in to Azure:
41+
42+
```bash
43+
azd auth login
44+
```
45+
46+
Follow the device code flow — open the URL shown, enter the code, and sign in with your Azure account.
47+
48+
4. Initialize the project by running:
5549

5650
```bash
5751
azd init --from-code
5852
```
5953

60-
4. Follow the prompts, accepting the defaults provided by the tool. When asked for a namespace, choose something unique (this will be used to name your Azure resources).
61-
5. Explore the generated `infra/` directory. You'll see Bicep files (`.bicep`) that define the Azure resources for your application:
54+
5. Follow the prompts, accepting the defaults provided by the tool.
55+
6. By default, `azd` generates infrastructure in memory at deploy time. To customize the infrastructure, persist it to disk by running:
56+
57+
```bash
58+
azd infra gen
59+
```
60+
61+
7. Explore the generated `infra/` directory. You'll see Bicep files (`.bicep`) that define the Azure resources for your application:
6262
6363
```bash
6464
ls infra/
@@ -95,12 +95,11 @@ The generated Bicep files define the Azure Container Apps that will host the cli
9595

9696
## Create the CD workflow
9797

98-
By default, `azd pipeline config` generates a simple workflow that deploys on every push to `main`. That works for getting started, but we want staged deployments with approval gates. The good news: if you create the workflow file *first*, `azd` will detect it and configure credentials around your custom workflow instead of generating the default.
98+
By default, `azd pipeline config` generates a simple workflow that deploys on every push to `main`. That works for getting started, but we want a workflow that only deploys **after CI passes**. If you create the workflow file *first*, `azd` will detect it and configure credentials around your custom workflow instead of generating the default.
9999

100100
Let's create a workflow that:
101101
- Only deploys **after CI passes** — using [`workflow_run`][workflow-run-docs]
102-
- Deploys to **staging** first, automatically
103-
- Requires **manual approval** before deploying to **production**
102+
- Can also be **triggered manually** via `workflow_dispatch`
104103
- Prevents **conflicting deployments** with concurrency controls
105104
106105
1. Create a new file at `.github/workflows/azure-dev.yml`.
@@ -121,40 +120,11 @@ Let's create a workflow that:
121120
contents: read
122121
123122
jobs:
124-
deploy-staging:
123+
deploy:
125124
runs-on: ubuntu-latest
126125
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
127-
environment: staging
128126
concurrency:
129-
group: deploy-${{ github.ref }}-staging
130-
cancel-in-progress: true
131-
132-
steps:
133-
- uses: actions/checkout@v4
134-
135-
- name: Install azd
136-
uses: Azure/setup-azd@v2
137-
138-
- name: Log in with Azure (Federated Credentials)
139-
run: |
140-
azd auth login \
141-
--client-id "${{ vars.AZURE_CLIENT_ID }}" \
142-
--federated-credential-provider "github" \
143-
--tenant-id "${{ vars.AZURE_TENANT_ID }}"
144-
145-
- name: Provision and deploy to staging
146-
run: azd up --environment staging --no-prompt
147-
env:
148-
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
149-
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
150-
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
151-
152-
deploy-production:
153-
runs-on: ubuntu-latest
154-
needs: deploy-staging
155-
environment: production
156-
concurrency:
157-
group: deploy-${{ github.ref }}-production
127+
group: deploy-production
158128
cancel-in-progress: false
159129
160130
steps:
@@ -170,8 +140,8 @@ Let's create a workflow that:
170140
--federated-credential-provider "github" \
171141
--tenant-id "${{ vars.AZURE_TENANT_ID }}"
172142
173-
- name: Provision and deploy to production
174-
run: azd up --environment production --no-prompt
143+
- name: Provision and deploy
144+
run: azd up --no-prompt
175145
env:
176146
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
177147
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
@@ -185,23 +155,14 @@ Let's walk through the key parts:
185155
- **`permissions: id-token: write`** — In the [Running Tests][running-tests] module you set `contents: read`. Here, `id-token: write` is added because the workflow needs to request OIDC tokens from Azure. This is how passwordless authentication works — no stored credentials, just short-lived tokens.
186156
- **`vars.*`** — Variables like `${{ vars.AZURE_CLIENT_ID }}` reference **repository variables** that `azd pipeline config` will create for you in the next step.
187157
- **`workflow_run`** triggers this workflow whenever the **Run Tests** workflow completes on `main`. The `if` condition ensures it only proceeds when tests **succeeded** — or when triggered manually via `workflow_dispatch`.
188-
- **`environment: staging`** and **`environment: production`** link each job to the GitHub Environments you created earlier. The production environment will trigger the approval gate you configured.
189-
- **`needs: deploy-staging`** on the production job creates the sequential flow: staging must succeed before production is offered for review.
190-
- **`concurrency`** groups prevent conflicting deployments to the same environment. Note `cancel-in-progress: false` on production to avoid accidentally cancelling an active deployment.
191-
- **`azd up`** provisions infrastructure and deploys your application in one command, targeted at a specific environment.
158+
- **`concurrency`** prevents conflicting deployments. Note `cancel-in-progress: false` to avoid accidentally cancelling an active deployment.
159+
- **`azd up`** provisions infrastructure and deploys your application in one command.
192160

193161
## Set up Azure authentication
194162

195-
Now let's authenticate with Azure and let `azd` configure the pipeline credentials. Because the workflow file already exists, `azd` will configure OIDC and variables around it rather than generating a new one.
196-
197-
1. Authenticate with Azure:
163+
Now let's let `azd` configure the pipeline credentials. Because the workflow file already exists, `azd` will configure OIDC and variables around it rather than generating a new one.
198164
199-
```bash
200-
azd auth login
201-
```
202-
203-
2. Follow the prompts to complete the authentication (a browser window will open for you to sign in).
204-
3. Configure the deployment pipeline:
165+
1. Configure the deployment pipeline:
205166
206167
```bash
207168
azd pipeline config
@@ -212,7 +173,7 @@ Now let's authenticate with Azure and let `azd` configure the pipeline credentia
212173
- Store the necessary secrets and variables in your repository automatically
213174
- Detect your existing workflow file and configure it
214175
215-
4. When prompted to commit and push your local changes, say **yes**.
176+
2. When prompted to commit and push your local changes, say **yes**.
216177
217178
> [!TIP]
218179
> After `azd pipeline config` completes, navigate to **Settings** > **Secrets and variables** > **Actions** > **Variables** tab to see the repository variables it created (like `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, etc.). These are the `vars.*` values your workflow references.
@@ -222,28 +183,25 @@ Now let's authenticate with Azure and let `azd` configure the pipeline credentia
222183
When you said **yes** to `azd pipeline config`'s commit prompt, it pushed your changes — including the workflow file. Let's verify everything is working.
223184
224185
1. Navigate to the **Actions** tab. The push will trigger the **Run Tests** workflow first.
225-
2. Once tests complete successfully, the **Deploy App** workflow will start automatically.
226-
3. Observe the pipeline stages:
227-
- **deploy-staging** proceeds automatically
228-
- After staging completes, **deploy-production** shows a **Waiting for review** badge
229-
4. Select **Review deployments** on the production job.
230-
5. Check the **production** environment and select **Approve and deploy**.
231-
6. Once the production deployment completes, expand the deploy step logs to find the application URLs.
232-
7. Open the client URL in your browser — you should see the pet shelter application live!
186+
2. Once tests complete successfully, the **Deploy App** workflow will start automatically (via the `workflow_run` trigger).
187+
3. Watch the deploy job run — it will provision Azure resources and deploy both the client and server applications.
188+
4. Once the deployment completes, expand the **Provision and deploy** step logs to find the application URLs.
189+
5. Open the client URL in your browser — you should see the pet shelter application live!
233190
234191
> [!TIP]
235192
> You can also find your deployment URLs by running `azd show` in the terminal.
236193
237194
## Summary and next steps
238195
239-
Congratulations! You've deployed the pet shelter application to Azure with a proper CI/CD pipeline:
196+
Congratulations! You've deployed the pet shelter application to Azure with a CI/CD pipeline:
240197

241198
- **CI-gated deployment** — CD only runs after CI passes, using `workflow_run`
242-
- **Staged environments** — staging deploys automatically, production requires approval
243199
- **OIDC authentication** — passwordless, short-lived tokens instead of stored credentials
244200
- **Concurrency controls** — preventing conflicting deployments
245201
- **azd integration**`azd pipeline config` configured credentials around your custom workflow
246202

203+
In a later exercise, we'll add **branch rulesets** to ensure code must pass CI and be reviewed before it can reach `main` — creating a natural production gate.
204+
247205
Next we'll [create custom actions][walkthrough-next] to reduce duplication and make our workflows more maintainable.
248206

249207
### Resources

0 commit comments

Comments
 (0)