Make your azd deployments a celebration
Tags: azure, cli, azd
Published: 2023-06-02 12:36:57

## Introduction

The Azure Developer CLI (azd) went [GA](https://devblogs.microsoft.com/azure-sdk/azd-ga-announcement/) a few weeks ago, so time to celebrate right? For sure that is a reason, but why not celebrate each and every deployment via `azd` by a confetti cannon? What? Yes you can, at least with a virtual one.

## Prerequisites

First of all you of course need the [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd) on your machine and a `azd`-compatible project e.g., one from the available templates or from the [Awesome AZD Templates](https://azure.github.io/awesome-azd/).

In addition you must have [Raycast](https://www.raycast.com/) on you machine which is available for MacOS only. And this is also the *limitation*: in case you are not on MacOS you will not be able to get the celebration feeling. 

The free version is sufficient and you can even install it via brew (`brew install --cask raycast`).

> **Note** I did not find a comparable tool for Windows. In case you happen to know one, just leave a comment and I will update this blog post.

Now we are set to do some magic with `azd` and hooks.

## azd Hooks

I already wrote a blog post about the hooks available in `azd` that you can find [here](https://dev.to/lechnerc77/azure-developer-cli-azure-developer-cli-episode-060-i-am-hooked-4on0). Since that blog post several things have been improved and the [documentation](https://learn.microsoft.com/azure/developer/azure-developer-cli/azd-extensibility) is much more concise now.

Nevertheless a short recap what hooks are about and what you can do with them. 

To make the `azd` flow more flexible it gives you the option to issue shell or PowerShell commands or according scripts as part of the `azd` execution flow. The scripts are linked (or "hooked") to the steps that get executed by the `azd` commands or represent so called *service lifecycle events*. 

To be precise the enhancements are run either before (*pre*-hook) or after (*post*-hook) a command or event gets executed. You find the complete list of available events in the [documentation](https://learn.microsoft.com/azure/developer/azure-developer-cli/azd-extensibility#available-hooks).

You define the hooks in the manifest of your `azd` project namely your `azure.yaml` file. This definition is backed by the YAML language server, so you get full type-ahead support. 

There are several options to configure them like what to do in an error case. You can even restrict the OS on which the script shall be applied e.g., if you want to execute a script exclusively on Windows. You find a description of all options in the [documentation](https://learn.microsoft.com/azure/developer/azure-developer-cli/azd-extensibility#hook-configuration).

With this `azd` feature together with Raycast we are now able to bring some glamour to our `azd` executions. Let's see how.

## Celebrating your Packaging and Deployments

One feature of Raycast is a (virtual) *confetti cannon*. You can trigger it from a console like bash or zsh via `open raycast://confetti`. This will give you a wonderful confetti explosion on your screen. 

Why not have that kind of celebration every time a `azd package` or `azd provision` is executed successfully? There is no reason why not, so let's do it.

We want to have things set up in a decent way, so instead of putting the call of Raycast in the `azure.yaml` we create a shell script for that call. First we create a folder in the root of our `azd` project and name it `hooks`. This is where we will put all our hook-scripts into. 

For our confetti cannon we create a file called `confetti.sh` and place it in this folder. The content of the file is:

```bash
#!/bin/bash
open raycast://confetti
exit
```

We make the file executable via `chmod a+x` so that we can test it without using `azd`. Calling the file directly should already give you some impression of the "functionality".

Next we must configure our `azure.yaml` file. We want to celebrate the *packaging* and the *provisioning* of infrastructure. With those two events, we cover a service lifecycle event as well as a command. As we know that we have Raycast on MacOS only we define the execution for POSIX-based OSes only (being well aware that we will fail on a GitHub Action runner). 

The sample project I will use for this enhancement is the [SAP Cloud SDK on Azure App Service Quickstart](https://github.com/Azure-Samples/app-service-javascript-sap-cloud-sdk-quickstart) but as all `azd` projects have the same structure this does not really matter. My `azure.yaml` file before making any configuration changes looks like this:

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: app-service-javascript-sap-cloud-sdk-quickstart
metadata:
  template: app-service-javascript-sap-cloud-sdk-quickstart
requiredVersions:
  azd: ">= 1.0.1"
services:
  sap-cloud-sdk-api:
    project: ./src/api
    language: ts
    host: appservice  
```

First we add the configuration for the provisioning hook:

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: app-service-javascript-sap-cloud-sdk-quickstart
metadata:
  template: app-service-javascript-sap-cloud-sdk-quickstart
requiredVersions:
  azd: ">= 1.0.1"
services:
  sap-cloud-sdk-api:
    project: ./src/api
    language: ts
    host: appservice  
hooks: # section for all azd command hooks
  postprovision: # azd command that should be enhanced 
    posix: # we restrict the enhancement to POSIX OS
      shell: sh # we use the regular shell
      continueOnError: true # if the script fails we do not want to abort the azd execution
      interactive: true # we bind the script to console stdin and stdout
      run: ./hooks/confetti.sh # we tell azd to use the script we created before
```

The comments in the code snippet above should give you the reasoning of the configuration. Be aware that the file location given in the `run` section must be relative to the *project root* if we are using a command hook.

Next we add the service lifecycle hook configuration for the packaging. For that we must configure the hook inside of the service block:

```yaml
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: app-service-javascript-sap-cloud-sdk-quickstart
metadata:
  template: app-service-javascript-sap-cloud-sdk-quickstart
requiredVersions:
  azd: ">= 0.8.0-beta.2"
services:
  sap-cloud-sdk-api:
    project: ./src/api
    language: ts
    host: appservice
    hooks:
      postpackage:
        posix:
          shell: sh
          continueOnError: true
          interactive: true
          run: ../../hooks/confetti.sh
hooks:
  postprovision:
    posix:
      shell: sh
      continueOnError: true
      interactive: true
      run: ./hooks/confetti.sh
```

The configuration is the same except for the location of the run script. Pay attention here as for service lifecycle hooks the location of the script file must be given *relative to the service*. As the service is located in `./src/api` we must navigate back to the root of the project. That is why this tine the `run:` argument is defined as `../../hooks/confetti.sh`.

Okay, that's it. Everything is in place to start the fun. Here we go for the postpackage hook ... wait for it:

![azd-with-confetti-animated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ovzn5u6mwptww8us1elr.gif)

No more to say than:

> Celebrate good times, come on (Let's celebrate)

## Summary

The hook functionality in `azd` is a powerful feature to enhance your `azd` flows with custom scripts at specific points in the `azd` flow. I still need some more experience with them to be able to derive some best practices and consequently the "don'ts" of this feature, but I consider it extremely helpful already.

As you have seen in this blog post you can also use this feature for maybe not so serious developer tasks and spice up your demos with a virtual confetti cannon.

With that ... happy azd'ing!