Monorepo using pulumi for azure infraestructure, using mainly bun, but could be used with other package managers.
Important to note that azure tools are not that great documentated for monorepos.
This repo is using:
- Azure functions β‘οΈ Hono api β
- Azure Static Web Apps β‘οΈ Next.js app β
- Azure Database for Postgres β‘οΈ Postgres DB β
After cloning the repo:
- Change all references to
pulumazto your project or org name - Remove the package
functions-build-target(was just for reference for how the output build of the functions pckg should look like) - Run
az login - Run
pulumi org set-default {org-name} - Add github secrets:
PULUMI_ACCESS_TOKEN - Configure Pulumi.yml file with your pulumi stack name, app name and app description
- Create an app registration with (az active-directory service-principle):
az ad sp create-for-rbac --name "pulumaz" --role contributor --scopes /subscriptions/{sub-id} --sdk-auth - With the output add github secrets:
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_SUBSCRIPTION_ID,AZURE_TENANT_ID,AZURE_CREDENTIALS
- run
./oidc.sh app-name gh-org-name/gh-repo-name ./fics.json, this will create all needed resources for OIDC, and set up the GH secretsAZURE_CLIENT_ID,AZURE_SUBSCRIPTION_ID,AZURE_TENANT_IDusing the GH cli- app-name: name of the app registration, this will create an Active Directory App Registration with the name
app-name - gh-org-name/gh-repo-name: the github org and repo name, this will create a service principal with the name
app-namein thegh-org-nameorg - fics.json: the Federated Identity Credentials file containing wich fics to create (for main branch, master branch and pull request branch are set by default)
- app-name: name of the app registration, this will create an Active Directory App Registration with the name
This is an overview of how the repo is built and structured, it includes understandings of the different parts of the repo and some pain points encountered.
The workflow does the following:
- set up bun, node, run bun i
- run pulumi up
- get the www name (gets a random name by azure) from pulumi output
- get the deployment token from azure
- build and deploy the static web app using previous values
- this build and deploy is runned by the official Azure/static-web-apps-deploy which uses
npmby default, you could override the build command but it didn't work for me. Also you could disable the build and build the app a step before but it didn't work either. My solution was to keep installs from the monorepo usable for npm as well (because it's used by default).
- this build and deploy is runned by the official Azure/static-web-apps-deploy which uses
- get variables from pulumi and azure cli (deploy token)
- build and deploy the static web app using previous values for main branch and pr to new environments. also removes stages when pr is closed
- running with next.js standalone mode
PRE_BUILD_COMMAND: npm install -g bun && bun installto install dependencies and use bunCUSTOM_BUILD_COMMAND: bun run build && cp -r .next/standalone/packages/www/. .next/standaloneto copy the www folder to the .next folder (workaround)- set up env vars
It uses Azure Database for Postgres with a flexible server. To connect to it:
psql $(pulumi stack output DATABASE_URL --show-secrets)The only good way that I found to deploy is using the Azure/static-web-apps-deploy action, a pain point on this is how to add env vars to the Next.js deployment.
Also I didn't found a way to deploy the zip file using pulumi.
Azure provides a managed way to deploy a CRUD api and graphQL api called swa-db-connection. We are not using it in this repo. official tutorial here
Only way is to add the env vars in the github action. That's why we pulled all the needed env vars from pulumi and azure cli in a previous step, and then we add them to the build_and_deploy_job in the env section.
I have tried a lot of things but the only way to make the azure functions to recognize the functions is using the current way, meaning:
- create an extra package with the output of the build and installing the package @azure/functions to it like a orphan repo (esbuild + build.sh or tsc + build.sh).
- only works with the linux version of AzureFunctions see github issue,
- from the same issue I got the
build.shscript.
Some useful resources researched:
- different ways to publish Azure Functions
- issue @azure/functions-core is only available at runtime
- example of deploying azure functions with pulumi
- example pulumi azure postgresql
- script oidc setup, from script just changed the creating role assignment line adding
--scope /subscriptions/$SUB_ID(scope is required value) - issue swa deployment, monorepo: www referencing another repo, solved by using standalone and copying output
- pulumi/azure-native tsserver issues "solutions"
- Azure Functions -> Hono api
- Azure StaticWebApp -> Next.js Web App
- Postgres DB linked to api and possible to Next.js server-side
- Centralized logging
- Auth
- Transactional emails
- Pull request review (preview environments)
- SWA deployment
- Infra deployment, reusing expencive infrastructure
- Auth azure CLI in github actions using OIDC (recommended by azure)
- Postgres DB linked to Next.js server-side