Week 14 - Infrastructure as Code

Why use Infrastructure as Code

IaC concepts

Azure Bicep

Bicep in practice

Deploy Bicep from CI/CD

Practice

Assignment

Gotchas & Pitfalls

Glossary: Week 14

Career relevance: Week 14

History of IaC

Slides (PDF)

Assignment

The Scenario

Your team still creates Azure resources by clicking through the portal. That worked for one environment; it does not work for three. Drift shows up, nobody can reproduce last week's setup, and the final-project capstone will need infrastructure you can re-deploy from a file.

Chapters 3–4 already taught you to author a storage account + nested container as a module. This assignment does not ask you to copy that work from the reference repo. Your fork starts with that Chapter 4 end state already in place. Your job is to extend it (environments via parameters, a second nested container), prove a deploy with what-if, tear down, and write it up.

The required work is entirely Bicep. Optional CI evidence (Task 6) does not affect whether you pass.

<aside> πŸ“ If a task feels unfamiliar, work through Practice first. Practice Exercises 1 to 5 harden the authoring, drift, and module skills on the reference clone; Exercise 6 keeps the Deploy Bicep from CI/CD workflow on this assignment fork.

</aside>

How to start

Fork the cohort hand-in repo c55-data-week-14 into your own GitHub account (Chapter 5 already walked this if you planted AZURE_CREDENTIALS and bicep.yml early). The repo README covers Codespaces and the HYF-tenant az login details.

  1. Fork c55-data-week-14 into your own GitHub account (skip if you already did in Chapter 5).
  2. Clone your fork locally (or open it in Codespaces).
  3. Skim main.bicep and modules/storage.bicep: they should already look like your Chapter 4 end state (thin main, module, storage account, nested raw container, @secure()).
  4. Add your name to the top of README.md, so a reviewer can tell whose fork they opened.
  5. Work through the tasks below, then hand in as described in Submission.

Do not replace the starter by pasting from azure-bicep-reference *-solution branches. Extend what is already in the fork.

Before you deploy:

az login
export CLASS_RG=rg-hyf-students   # replace if your teacher gave a different name
az bicep version || az bicep install

Confirm az account show points at the shared HYF subscription. You deploy into $CLASS_RG; students cannot create resource groups themselves.

If it names a different subscription, or an N/A(tenant level account) entry, you are pointed somewhere else. List what you have and pick the shared one:

az account list --all --output table
az account set --subscription "<the shared HYF subscription>"

Anyone with a personal Azure for Students subscription will hit this: the CLI keeps one default across every tenant you have signed into, and it is not always the one you want.

Project structure

c55-data-week-14/
β”œβ”€β”€ .hyf/
β”‚   └── test.sh                # static auto-grader (bash .hyf/test.sh)
β”œβ”€β”€ main.bicep                 # starter (Ch4 end state) β€” Tasks 1–2: extend
β”œβ”€β”€ modules/
β”‚   └── storage.bicep          # starter: storage + nested raw β€” extend
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ deploy_succeeded.txt   # Task 3: az deployment group create output
β”‚   β”œβ”€β”€ what_if.txt            # Task 3: az deployment group what-if output
β”‚   β”œβ”€β”€ portal_confirm.md      # Task 3: portal confirmation notes + teardown line
β”‚   └── optional/              # Task 6: optional CI what-if evidence
β”œβ”€β”€ WRITEUP.md                 # Task 4: half-page teammate write-up
β”œβ”€β”€ AI_ASSIST.md               # Task 5: one LLM use you critically reviewed
└── README.md                  # assignment-repo README

Locked surface: storage account + nested blob containers only. Do not invent Postgres, Key Vault, Container Apps, ACR, or Databricks resources.

Task 1: environments via parameters (required)

Add an environment parameter (for example dev or prod) and set an Environment tag on the storage account from that parameter (pass tags through the module if needed). Same idea as Practice Exercise 2 / Chapter 2: one template, many environments.

  1. Deploy with environment=dev (and your unique storageName).
  2. Run az deployment group what-if with the same storageName and environment=prod. You should see a tag modification, not a new storage account.
  3. Deploy the prod parameter set (or leave dev if you prefer; the important part is the parameter + tag wiring and a real what-if later in Task 3).

Keep the existing @secure() dummy param: pass it at deploy time; never commit the value.

Task 2: second nested container (required)

Keep the nested raw container. Add a second nested blob container named curated under the same account's default blob service (parent:), still in modules/storage.bicep.

After deploy, both containers should appear under the storage account in the portal.

Task 3: deploy evidence (required)

With Tasks 1–2 in the template:

  1. Deploy with az deployment group create --resource-group "$CLASS_RG" ... and save output showing provisioningState: Succeeded to docs/deploy_succeeded.txt.
  2. Run az deployment group what-if --resource-group "$CLASS_RG" ... and save the output to docs/what_if.txt. A tag or container change is ideal: for example deploy with environment=dev, then preview environment=prod and capture the ~ tags.Environment: "dev" => "prod" line. Do not chase a clean "no change": your containers will keep printing ~ with - property lines no matter what, as explained in Reading a noisy preview.
  3. In the Azure portal, open $CLASS_RG, confirm the storage account and both containers (raw and curated), and note the deployment under Deployments. Write two or three sentences in docs/portal_confirm.md.
  4. After you have captured the evidence above, tear down and record it: add a final line to docs/portal_confirm.md saying what you deleted and when, for example Teardown: deleted sthyf<yourname> (and both containers) on 2026-08-14. If your role blocked the delete, say that instead and name who you asked.

<aside> πŸ’‘ Attempting the optional Task 6? Do it before this teardown step. Task 6 previews a tag or SKU change on the live account, so it needs the account to still exist. Tear down once, after the CI evidence is captured.

</aside>

Extra guidelines

<aside> πŸ’‘ Using AI to help: Paste your main.bicep / module (no secrets) and ask an LLM how to wire an Environment tag or a second nested container. Diff the suggestion, then run what-if yourself before you deploy. (⚠️ no real data, no PII)

</aside>

Task 4: write-up (required)

Fill in WRITEUP.md (about half a page): what you extended, why environment tags and a second container matter, and how deploying as code differs from clicking through the portal.

Task 5: AI assist report (required)

Fill in AI_ASSIST.md with:

Critical review is the point: an unedited paste does not pass this task.

Task 6: optional CI preview (bonus)

This builds on Deploy Bicep from CI/CD and does not affect whether the assignment passes. Do it after Tasks 1–2 and after you capture the Task 3 evidence, but before the Task 3 teardown: the preview below runs against the live account, so it needs the account to still exist.

If your Key Vault secret is not ready yet, still keep the workflow file committed; live runs wait on azure-credentials-week14-<yourname>.

Out-of-week optional (not graded here): Bonus - AI-assisted data enrichment if you want an LLM pipeline step on a small, PII-free table.

Deliverables

<aside> ⚠️ Never commit an Azure key, connection string, or database password. Use @secure() parameters or Key Vault references. A leaked secret is an automatic fail and a real-world security incident.

</aside>

What good looks like

How you will be evaluated

Your teacher reviews the PR against the required tasks above. In practice they check:

Optional CI evidence is bonus only; it does not decide pass/fail. Point weights stay with your teacher (they are not published in this chapter on purpose).

Submission

  1. From the repo root, run bash .hyf/test.sh and fix anything it flags. The grader is static only (it cannot see your Azure subscription); your teacher still reviews the live deploy and the docs/ evidence. A fresh starter should clear Level 2 baseline; environment tags and curated are the extension points.
  2. Create a git branch week14/your-name in your fork.
  3. Commit your work with a clear message.
  4. Push the branch and open a Pull Request against your cohort's assignment repo. Share the PR URL with your teacher once you are ready for review.

Your PR description is checked too. The repo ships .github/PULL_REQUEST_TEMPLATE.md, and a PR body check fails the pull request when the description is missing any of these headings:

## What I built
## How to review
## How to run
## What reviewers should see
## Self-check

GitHub fills that template in automatically only when you open the PR from the website, or with gh pr create and no --body. Open it through the API or with gh pr create --body "...", which is what most AI tools do, and the template is skipped silently. If the check goes red, click Edit on the description, paste the template, and fill it in: editing re-runs the check on its own, with no new commit needed.

<aside> πŸ’‘ If you added the optional bicep.yml, its what-if check may show red on this hand-in PR. That is expected and does not count against you: secrets do not cross from your fork to the cohort repo, so azure/login cannot sign in there. Your green evidence comes from the in-fork PR in Task 6.

</aside>