-
Notifications
You must be signed in to change notification settings - Fork 11
feat(data-track/week-6): add Week 6 practice exercises #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| # HYF Data Track — Week 6 Practice Exercises | ||
|
|
||
| Five exercises that consolidate Week 6 (Azure fundamentals for data engineers): resource hierarchy, Blob Storage, Postgres connection strings, Container Apps Jobs, and cost awareness. | ||
|
|
||
| The Week 6 practice chapter is paper-based by design because the real value lives in live Azure runs against the shared infrastructure your teacher provisioned. These exercises are the Codespace-runnable counterpart: each one trains the *Python* and *diagnosis* muscle the assignment needs, so you arrive at the Azure portal with the thinking already done. | ||
|
|
||
| Work through them in order. None depend on each other, but the difficulty climbs gently. | ||
|
|
||
| ## Layout | ||
|
|
||
| | Folder | Topic | Concepts | | ||
| |---|---|---| | ||
| | [`exercise_1/`](exercise_1/) | Trace a Resource Group | Azure CLI output, resource hierarchy, idle billing | | ||
| | [`exercise_2/`](exercise_2/) | End-to-End Blob Verification | `azure-storage-blob`, upload-from-code, verify-from-CLI | | ||
| | [`exercise_3/`](exercise_3/) | Debug a Broken Connection String | URL parsing, Azure FQDN, SSL, port | | ||
| | [`exercise_4/`](exercise_4/) | Dry-Run a Container App Job | `az containerapp job create`, flag self-check | | ||
| | [`exercise_5/`](exercise_5/) | Cost Estimation Challenge | Pricing arithmetic, idle billing, saving from stopping | | ||
|
|
||
| ```text | ||
| week-6/ | ||
| ├── exercise_1/ | ||
| │ ├── az_resource_list_output.json # mock `az resource list` output | ||
| │ ├── exercise.py # starter with TODOs | ||
| │ ├── README.md | ||
| │ └── solutions/ | ||
| │ └── exercise.py # reference answer with # WHY notes | ||
| ├── exercise_2/ | ||
| │ ├── exercise.py # Azure-dependent; fails gracefully without env var | ||
| │ ├── .env.example | ||
| │ ├── requirements.txt | ||
| │ ├── README.md | ||
| │ └── solutions/ | ||
| │ └── exercise.py | ||
| ├── exercise_3/ | ||
| │ ├── exercise.py | ||
| │ ├── README.md | ||
| │ └── solutions/ | ||
| │ └── exercise.py | ||
| ├── exercise_4/ | ||
| │ ├── exercise.py | ||
| │ ├── README.md | ||
| │ └── solutions/ | ||
| │ └── exercise.py | ||
| └── exercise_5/ | ||
| ├── exercise.py | ||
| ├── README.md | ||
| └── solutions/ | ||
| └── exercise.py | ||
| ``` | ||
|
|
||
| ## Open in GitHub Codespaces | ||
|
|
||
| > 💻 [Open in GitHub Codespaces](https://github.com/codespaces/new/HackYourFuture/Learning-Resources?devcontainer_path=.devcontainer%2Fdata-track%2Fdevcontainer.json) | ||
|
|
||
| One Codespace covers all five exercises. From the Explorer, navigate into `data-track/week-6/exercise_N/`. | ||
|
|
||
| **Azure access needed?** | ||
|
|
||
| - Exercises 1, 3, 4, 5 run pure-Python with no Azure access required: the Codespace alone is enough. | ||
| - Exercise 2 needs the shared storage account's connection string. Ask your teacher; the starter prints the exact env-var name and exits cleanly if it is missing. | ||
| - Exercise 1 ships a representative mock of `az resource list` output. If you have Azure CLI installed and a shared resource group, you can drop in your own JSON to label the real environment. | ||
|
|
||
| ## Clone locally | ||
|
|
||
| ```bash | ||
| git clone https://github.com/HackYourFuture/Learning-Resources.git | ||
| cd Learning-Resources/data-track/week-6 | ||
| ``` | ||
|
|
||
| Each exercise folder ships its own `requirements.txt` (when needed) and a per-exercise README with detailed instructions. | ||
|
|
||
| ## Reference solutions (peek only after attempting) | ||
|
|
||
| Each `exercise_N/solutions/` folder holds the reference answer in-place. The original `# TODO` comments are preserved, and `# WHY ...:` notes sit underneath each non-obvious choice. | ||
|
|
||
| **Read the WHY notes, not just the code.** The reasoning is what carries into real projects. | ||
|
|
||
| Time-box yourself: 15 to 30 minutes of honest attempt before opening `solutions/`. You can diff your work against the reference: | ||
|
|
||
| ```bash | ||
| diff exercise_1/exercise.py exercise_1/solutions/exercise.py | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Exercise 1: Trace a Resource Group | ||
|
|
||
| Parse the output of `az resource list` and label every resource in the shared resource group: what it is, which chapter introduced it, and whether it bills you while it sits idle. | ||
|
|
||
| ## Setup | ||
|
|
||
| No extra dependencies. `exercise.py` uses only the standard library and reads `az_resource_list_output.json` next to it. | ||
|
|
||
| The JSON file is a representative mock of the shared `rg-weather-dev` resource group. If you have Azure access, replace it with your own: | ||
|
|
||
| ```bash | ||
| az resource list --resource-group <your-group> --output json > az_resource_list_output.json | ||
| ``` | ||
|
|
||
| ## Task | ||
|
|
||
| 1. Open `exercise.py` and fill in `TYPE_CATALOG` (TODO 1) so each `Microsoft.*` type maps to a short label and a Week 6 chapter number. | ||
| 2. Implement `bills_when_idle()` (TODO 2). Most managed Azure resources bill while idle because the underlying compute stays reserved for you. The clearest exceptions in this exercise are Container App Jobs (per-execution billing) and Log Analytics (per-GB ingestion). | ||
| 3. Implement `classify_resources()` (TODO 3) so it returns one dict per resource with `name`, `type_label`, `chapter`, `bills_idle`. Skip unknown types as `("unknown", None)` instead of crashing. | ||
| 4. Run `python3 exercise.py` and confirm the table matches the `# Expected output:` block at the bottom of the file. | ||
|
|
||
| ## Success criteria | ||
|
|
||
| - The script prints a 7-row table without errors. | ||
| - Five resources are labelled "yes" under "Bills idle?" (Storage, Postgres, Container Apps env, Container Registry, Key Vault). | ||
| - Two resources are labelled "no" (Container App Job, Log Analytics). | ||
|
|
||
| ## Stretch | ||
|
|
||
| - Add an eighth resource type to the JSON (e.g. `Microsoft.Network/publicIPAddresses`) and confirm your code labels it as `unknown` without crashing. | ||
| - Run `az resource list --resource-group <your-group> --output json` against your own shared group, save the file, and rerun the script to label your real environment. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| [ | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.Storage/storageAccounts/stweatherdev01", | ||
| "name": "stweatherdev01", | ||
| "type": "Microsoft.Storage/storageAccounts", | ||
| "location": "westeurope", | ||
| "kind": "StorageV2", | ||
| "sku": {"name": "Standard_LRS", "tier": "Standard"}, | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.DBforPostgreSQL/flexibleServers/pg-weather-dev", | ||
| "name": "pg-weather-dev", | ||
| "type": "Microsoft.DBforPostgreSQL/flexibleServers", | ||
| "location": "westeurope", | ||
| "sku": {"name": "Standard_B1ms", "tier": "Burstable"}, | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.App/managedEnvironments/env-weather-dev", | ||
| "name": "env-weather-dev", | ||
| "type": "Microsoft.App/managedEnvironments", | ||
| "location": "westeurope", | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.App/jobs/job-weather-ingest", | ||
| "name": "job-weather-ingest", | ||
| "type": "Microsoft.App/jobs", | ||
| "location": "westeurope", | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.ContainerRegistry/registries/acrweatherdev", | ||
| "name": "acrweatherdev", | ||
| "type": "Microsoft.ContainerRegistry/registries", | ||
| "location": "westeurope", | ||
| "sku": {"name": "Basic", "tier": "Basic"}, | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.KeyVault/vaults/kv-weather-dev", | ||
| "name": "kv-weather-dev", | ||
| "type": "Microsoft.KeyVault/vaults", | ||
| "location": "westeurope", | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| }, | ||
| { | ||
| "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-weather-dev/providers/Microsoft.OperationalInsights/workspaces/log-weather-dev", | ||
| "name": "log-weather-dev", | ||
| "type": "Microsoft.OperationalInsights/workspaces", | ||
| "location": "westeurope", | ||
| "tags": {"env": "dev", "owner": "data-track"} | ||
| } | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| """Exercise 1: Trace a resource group. | ||
|
|
||
| You will parse the JSON output of `az resource list` and label every resource | ||
| in the shared resource group: what it is, which chapter introduced it, and | ||
| whether it bills you while it sits idle. | ||
|
|
||
| This is the muscle you need before you create your own resources in the | ||
| assignment. Knowing what already exists prevents duplicates and wasted credits. | ||
| """ | ||
|
|
||
| import json | ||
| from pathlib import Path | ||
|
|
||
| # A sample `az resource list --resource-group rg-weather-dev --output json` payload | ||
| # ships next to this file. If you have Azure access, you can replace it with your own: | ||
| # az resource list --resource-group <your-group> --output json > my_resources.json | ||
| SAMPLE_PATH = Path(__file__).parent / "az_resource_list_output.json" | ||
|
|
||
|
|
||
| def load_resources(path: Path) -> list[dict]: | ||
| """Load the JSON array of resources from disk.""" | ||
| return json.loads(path.read_text()) | ||
|
|
||
|
|
||
| # TODO 1: Map each Azure resource type string (the value of the "type" field) to a | ||
| # short human label and the Week 6 chapter that introduced it. Cover at least | ||
| # the seven types that appear in az_resource_list_output.json: | ||
| # - Microsoft.Storage/storageAccounts -> ("Storage account", 3) | ||
| # - Microsoft.DBforPostgreSQL/flexibleServers -> ("Postgres server", 4) | ||
| # - Microsoft.App/managedEnvironments -> ("Container Apps env", 5) | ||
| # - Microsoft.App/jobs -> ("Container App Job", 5) | ||
| # - Microsoft.ContainerRegistry/registries -> ("Container Registry", 5) | ||
| # - Microsoft.KeyVault/vaults -> ("Key Vault", 6) | ||
| # - Microsoft.OperationalInsights/workspaces -> ("Log Analytics", 6) | ||
| TYPE_CATALOG: dict[str, tuple[str, int]] = { | ||
| # fill me in | ||
| } | ||
|
|
||
|
|
||
| # TODO 2: Decide which resource types bill you while idle (no requests, no jobs running). | ||
| # The honest answer is *most* managed Azure resources do, because the underlying | ||
| # compute, storage, or networking stays reserved for you. The clearest exceptions | ||
| # in this exercise: | ||
| # - Container App Job (Microsoft.App/jobs) bills per execution, not per hour. | ||
| # - Log Analytics workspace bills per GB ingested, not per hour. | ||
| # Return True for "bills while idle", False otherwise. | ||
| def bills_when_idle(resource_type: str) -> bool: | ||
| # fill me in | ||
| raise NotImplementedError | ||
|
|
||
|
|
||
| # TODO 3: For each resource in the list, produce a dict with these keys: | ||
| # name, type_label, chapter, bills_idle | ||
| # Skip resources whose type is not in TYPE_CATALOG (return them as "unknown" with | ||
| # chapter=None instead of crashing). The chapter-readiness check matters because | ||
| # a real shared RG will accumulate extra resources over time. | ||
| def classify_resources(resources: list[dict]) -> list[dict]: | ||
| # fill me in | ||
| raise NotImplementedError | ||
|
|
||
|
|
||
| def format_table(rows: list[dict]) -> str: | ||
| """Pretty-print the classification as a fixed-width table.""" | ||
| header = f"{'Name':<24} {'Type':<22} {'Chapter':<8} {'Bills idle?':<11}" | ||
| sep = "-" * len(header) | ||
| body = "\n".join( | ||
| f"{r['name']:<24} {r['type_label']:<22} {str(r['chapter'] or '-'):<8} {('yes' if r['bills_idle'] else 'no'):<11}" | ||
| for r in rows | ||
| ) | ||
| return f"{header}\n{sep}\n{body}" | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| resources = load_resources(SAMPLE_PATH) | ||
| rows = classify_resources(resources) | ||
| print(format_table(rows)) | ||
| idle_billers = sum(1 for r in rows if r["bills_idle"]) | ||
| print(f"\n{idle_billers} of {len(rows)} resources bill while idle.") | ||
|
|
||
| # Expected output (after you fill in the TODOs): | ||
| # | ||
| # Name Type Chapter Bills idle? | ||
| # -------------------------------------------------------------------- | ||
| # stweatherdev01 Storage account 3 yes | ||
| # pg-weather-dev Postgres server 4 yes | ||
| # env-weather-dev Container Apps env 5 yes | ||
| # job-weather-ingest Container App Job 5 no | ||
| # acrweatherdev Container Registry 5 yes | ||
| # kv-weather-dev Key Vault 6 yes | ||
| # log-weather-dev Log Analytics 6 no | ||
| # | ||
| # 5 of 7 resources bill while idle. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| """Exercise 1: Trace a resource group. | ||
|
|
||
| You will parse the JSON output of `az resource list` and label every resource | ||
| in the shared resource group: what it is, which chapter introduced it, and | ||
| whether it bills you while it sits idle. | ||
|
|
||
| This is the muscle you need before you create your own resources in the | ||
| assignment. Knowing what already exists prevents duplicates and wasted credits. | ||
| """ | ||
|
|
||
| import json | ||
| from pathlib import Path | ||
|
|
||
| # A sample `az resource list --resource-group rg-weather-dev --output json` payload | ||
| # ships next to this file. If you have Azure access, you can replace it with your own: | ||
| # az resource list --resource-group <your-group> --output json > my_resources.json | ||
| SAMPLE_PATH = Path(__file__).parent.parent / "az_resource_list_output.json" | ||
|
|
||
|
lassebenni marked this conversation as resolved.
|
||
|
|
||
| def load_resources(path: Path) -> list[dict]: | ||
| """Load the JSON array of resources from disk.""" | ||
| return json.loads(path.read_text()) | ||
|
|
||
|
|
||
| # TODO 1: Map each Azure resource type string (the value of the "type" field) to a | ||
| # short human label and the Week 6 chapter that introduced it. Cover at least | ||
| # the seven types that appear in az_resource_list_output.json: | ||
| # - Microsoft.Storage/storageAccounts -> ("Storage account", 3) | ||
| # - Microsoft.DBforPostgreSQL/flexibleServers -> ("Postgres server", 4) | ||
| # - Microsoft.App/managedEnvironments -> ("Container Apps env", 5) | ||
| # - Microsoft.App/jobs -> ("Container App Job", 5) | ||
| # - Microsoft.ContainerRegistry/registries -> ("Container Registry", 5) | ||
| # - Microsoft.KeyVault/vaults -> ("Key Vault", 6) | ||
| # - Microsoft.OperationalInsights/workspaces -> ("Log Analytics", 6) | ||
| TYPE_CATALOG: dict[str, tuple[str, int]] = { | ||
| "Microsoft.Storage/storageAccounts": ("Storage account", 3), | ||
| "Microsoft.DBforPostgreSQL/flexibleServers": ("Postgres server", 4), | ||
| "Microsoft.App/managedEnvironments": ("Container Apps env", 5), | ||
| "Microsoft.App/jobs": ("Container App Job", 5), | ||
| "Microsoft.ContainerRegistry/registries": ("Container Registry", 5), | ||
| "Microsoft.KeyVault/vaults": ("Key Vault", 6), | ||
| "Microsoft.OperationalInsights/workspaces": ("Log Analytics", 6), | ||
| } | ||
| # WHY a dict keyed by the literal "type" string: the Azure CLI returns this exact | ||
| # value, so a plain lookup with .get(resource["type"]) handles every resource in | ||
| # one line and degrades gracefully for unknown types via the default. | ||
|
|
||
|
|
||
| # TODO 2: Decide which resource types bill you while idle (no requests, no jobs running). | ||
| # The honest answer is *most* managed Azure resources do, because the underlying | ||
| # compute, storage, or networking stays reserved for you. The clearest exceptions | ||
| # in this exercise: | ||
| # - Container App Job (Microsoft.App/jobs) bills per execution, not per hour. | ||
| # - Log Analytics workspace bills per GB ingested, not per hour. | ||
| # Return True for "bills while idle", False otherwise. | ||
| _USAGE_BILLED_TYPES = { | ||
| "Microsoft.App/jobs", | ||
| "Microsoft.OperationalInsights/workspaces", | ||
| } | ||
|
|
||
|
|
||
| def bills_when_idle(resource_type: str) -> bool: | ||
| return resource_type not in _USAGE_BILLED_TYPES | ||
| # WHY default to True: framing the rule as "bills idle UNLESS the type is on the | ||
| # usage-billed allowlist" is safer than the reverse. Forgetting to list a new | ||
| # resource type then errs on the side of "assume it costs money", which matches | ||
| # how a student should think about an unfamiliar Azure resource in a shared RG. | ||
|
|
||
|
|
||
| # TODO 3: For each resource in the list, produce a dict with these keys: | ||
| # name, type_label, chapter, bills_idle | ||
| # Skip resources whose type is not in TYPE_CATALOG (return them as "unknown" with | ||
| # chapter=None instead of crashing). The chapter-readiness check matters because | ||
| # a real shared RG will accumulate extra resources over time. | ||
| def classify_resources(resources: list[dict]) -> list[dict]: | ||
| classified = [] | ||
| for r in resources: | ||
| rtype = r["type"] | ||
| label, chapter = TYPE_CATALOG.get(rtype, ("unknown", None)) | ||
| classified.append( | ||
| { | ||
| "name": r["name"], | ||
| "type_label": label, | ||
| "chapter": chapter, | ||
| "bills_idle": bills_when_idle(rtype), | ||
| } | ||
| ) | ||
| return classified | ||
| # WHY tolerate unknown types: a real `az resource list` against a long-lived RG | ||
| # tends to include extras (public IPs, NSGs, managed identities) you did not | ||
| # create yourself. Crashing on the first unfamiliar entry would make the script | ||
| # useless against real data; labelling it "unknown" leaves the rest readable. | ||
|
|
||
|
|
||
| def format_table(rows: list[dict]) -> str: | ||
| """Pretty-print the classification as a fixed-width table.""" | ||
| header = f"{'Name':<24} {'Type':<22} {'Chapter':<8} {'Bills idle?':<11}" | ||
| sep = "-" * len(header) | ||
| body = "\n".join( | ||
| f"{r['name']:<24} {r['type_label']:<22} {str(r['chapter'] or '-'):<8} {('yes' if r['bills_idle'] else 'no'):<11}" | ||
| for r in rows | ||
| ) | ||
| return f"{header}\n{sep}\n{body}" | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| resources = load_resources(SAMPLE_PATH) | ||
| rows = classify_resources(resources) | ||
| print(format_table(rows)) | ||
| idle_billers = sum(1 for r in rows if r["bills_idle"]) | ||
| print(f"\n{idle_billers} of {len(rows)} resources bill while idle.") | ||
|
|
||
| # Expected output (after you fill in the TODOs): | ||
| # | ||
| # Name Type Chapter Bills idle? | ||
| # -------------------------------------------------------------------- | ||
| # stweatherdev01 Storage account 3 yes | ||
| # pg-weather-dev Postgres server 4 yes | ||
| # env-weather-dev Container Apps env 5 yes | ||
| # job-weather-ingest Container App Job 5 no | ||
| # acrweatherdev Container Registry 5 yes | ||
| # kv-weather-dev Key Vault 6 yes | ||
| # log-weather-dev Log Analytics 6 no | ||
| # | ||
| # 5 of 7 resources bill while idle. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Copy to .env and fill from your teacher's shared connection string. | ||
| # Then either `source .env` before running, or use python-dotenv to load it. | ||
| AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=<name>;AccountKey=<key>;EndpointSuffix=core.windows.net | ||
|
lassebenni marked this conversation as resolved.
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.