{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/lighthouse-meet-github-actions",
  "description": "This post illustrates how to integrate Lighthouse into a GitHub Actions workflow for an Azure Static Web App.",
  "path": "/posts/lighthouse-meet-github-actions",
  "publishedAt": "2022-03-20T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "azure static web apps",
    "github actions",
    "docusaurus"
  ],
  "textContent": "Lighthouse is a tremendous tool for auditing the performance and usability of websites. Rather than having to perform these audits manually, it's helpful to be able to plug it into your CI pipeline. This post illustrates how to integrate Lighthouse into a GitHub Actions workflow for an Azure Static Web App, and report findings directly in pull requests that are raised.\n\n\n\nWhat we'll do\n\nThis post isn't a walkthrough of how to use Lighthouse effectively. There is already great guidance out there on this topic.\n\nInstead, we're going build a simple web application, in the context of a GitHub repo. We'll wire it up to deploy via GitHub Actions to Azure Static Web Apps. Static Web Apps is a free hosting option for static websites and it comes with staging environments or deployment previews built in. This feature deploys a fully functional version of a site each time a pull request is raised, built upon the changes implemented in that pull request.\n\nThe staging environment is a perfect place to implement our Lighthouse checks. If a pull request impacts usability or performance, seeing those details in the context of our pull request is exactly where we'd like to learn this. This kind of check gives us the opportunity to ensure we only merge when we're happy that the changes do not negatively impact our Lighthouse scores.\n\nIn this post we'll start from the point of an empty GitHub repo and build up from there.\n\nCreate our application\n\nInside the root of our repository we're going to create a Docusaurus site. Docusaurus is a good example of a static site, the kind of which is a natural fit for Jamstack. We could equally use something else like Hugo for instance.\n\nAt the command line we'll enter:\n\nAnd Docusaurus will create a new site in the website directory. Let's commit and push this and turn our attention to Azure.\n\nCreating a Static Web App in Azure\n\nThere's a number of ways to create a Static Web App in Azure. It's possible to use infrastructure as code with a language like Bicep. But for this post let's use the Azure Portal instead. If you don't have an account already, you can set one up for free very quickly.\n\nOnce you've logged in, click \"Create a resource\" and look up Static Web App:\n\nClick on \"Create\" and you'll be take to the creation dialog:\n\nYou'll need to create a resource group for your SWA to live in, give the app a name, the \"Free\" plan and a deployment source of GitHub.\n\nClick on the \"Sign in with GitHub\" button and authorize Azure to access your GitHub account for Static Web Apps.\n\nAt this point Azure will query GitHub on your behalf and look up the organisations and repositories you have access to. Select the repository that you'd like to deploy to your Static Web App and select the branch you'd like to deploy.\n\nYou also need to provide Azure with some build details that help it understand how your app is built. We'll provide a preset of \"Custom\". We'll set the \"App location\" (the root of our front end app) to be \"/website\" to tally up with the application we just created. We'll leave \"Api location\" blank and we'll set the output location to be \"build\" - this is the directory under website where Docusaurus will create our site.\n\nFinally click \"Review + create\" and then \"Create\".\n\nAzure will now:\n\n- Create an Azure Static Web app resource in Azure\n- Update your repository to add a GitHub Actions workflow to deploy your static web app\n- Kick off a first run of the GitHub Actions workflow to deploy your SWA.\n\nPretty amazing, right?\n\nWhen you look at the resource in Azure it will look something like this:\n\nIf you click on the GitHub Action runs you'll be presented with your GitHub Action:\n\nAnd when that finishes running you'll be able to see your deployed Static Web App by clicking on the URL in the Azure Portal:\n\nWe now have:\n\n- a GitHub repo\n- which contains a simple web application\n- and a GitHub Actions workflow which:\n  - deploys to an Azure Static Web App\n  - spins up a staging environment for pull requests\n\nPreparing to plug in Lighthouse\n\nWith this groundwork in place we're ready to add Lighthouse into the mix. If you look in the /.github/workflows folder of your repo, you'll find a workflow file with contents along these lines:\n\nThis was created for us when we set up our SWA in Azure. We're now going to update the contents to add some Lighthouse jobs.\n\nBefore we do that, we need to acquire two things:\n\n1. the custom domain of our static web app\n2. the location of the resource group where the SWA resides\n\nThese two pieces of information are required such that we can determine the URL of our staging environments.\n\nCustom domain\n\nWe acquire the custom domain of our static web app in the \"Custom Domains\" screen of the Azure Portal:\n\nThe custom domain is the auto-generated custom domain - it's highlighted in the screenshot above. For the SWA we're building here the custom domain is agreeable-rock-039a51810.1.azurestaticapps.net.\n\nLocation\n\nWe acquire the location by looking at the resource group in the Azure Portal. For the SWA we've been building the location is \"Central US\". However, rather than the \"display name\" variant of the location, what we want is the \"code\" which will be used in the URL. You can see what this is by clicking on the \"JSON view\" in the Azure Portal:\n\nAs the screenshot above demonstrates, the code we need is centralus.\n\nPlugging in Lighthouse\n\nWe now have all we need to plug in Lighthouse. Let's create a branch:\n\nWe're going to add a new \"Lighthouse report\" job to our GitHub Actions workflow file:\n\nThere's a number of things happening in this workflow. Let's walk through them.\n\nStatic Web App - get preview URL\n\nHere we acquire the preview URL of our static web app using:\n\n- the default host name of the static web app\n- the location\n- the pull request number eg 123\n\nGiven a default host name of agreeable-rock-039a51810, a location of centralus and a pull request number of 123, the preview url would be agreeable-rock-039a51810-123.centralus.1.azurestaticapps.net. Using a little bash magic we create an output variable named PREVIEW_URL containing that value. We'll re-use it later in the workflow.\n\nStatic Web App - wait for preview\n\nWe don't want to run our test until the static web app is up and running. To cater for this we're going to pull in the wait_for_response GitHub Action. This polls until a website returns a 200, we're going to point it at our SWA.\n\nAudit URLs using Lighthouse\n\nThe big moment has arrived! We're going to plug Lighthouse into our workflow using the lighthouse-ci-action GitHub Action.\n\nWe provide a configPath: ./.github/workflows/lighthousesrc.json which points to file that configures our Lighthouse configuration. We'll create that file as well and populate it with this:\n\nThis in turn hands off the specific configuration to a lighthouse-config.js file that we also need to create:\n\nThe configuration above can be amended based upon the various links in the comments. Generally it's a good idea to roll with the defaults; however skipping the canonical audit is sensible as it will reliably be incorrect for staging sites.\n\nAlong side the Lighthouse configuration, there's config for the GitHub Action itself:\n\n- uploadArtifacts: true - will save results as an action artifacts\n- temporaryPublicStorage: true - will upload lighthouse report to the temporary storage\n- runs: 5 - will run Lighthouse 5 times to get more reliable performance results\n\nFormat lighthouse score\n\nWe've run Lighthouse at this point. What we want to do next is take the results of the run and build up some text that we can add to our pull request as a comment.\n\nFor this we're going to use the github-script GitHub Action, grab the outputs of the previous step and call out to a lighthouseCommentMaker.js file we're going to write to make the comment we'd like to publish to our PR:\n\nThe above code takes the Lighthouse outputs and creates some Markdown to represent the results. It uses some nice emoji as well. Wonderfully, we're entirely free to customise this as much as we'd like; it's just code! All that matters is that a string is pumped out at the end.\n\nAdd Lighthouse stats as comment\n\nFinally we're ready to add the comment to the PR. We'll do this using the sticky-pull-request-comment GitHub Action. We pass in the comment we've just made in the previous step, as well as some other parameters, and this will write the comment to the PR.\n\nPutting it all together\n\nWhen we commit our changes and raise a pull request, we see our GitHub Action run, and then once it has we see a Lighthouse report being attached to our pull request:\n\nNote you can also click on a link in the comment to go directly to the full report.\n\nNow, with each PR that is raised, any regressions in performance can be observed and resolved _before_ they make get in front of customer's eyes!\n\nThis post was originally published on LogRocket.\n\n<head>\n    <link rel=\"canonical\" href=\"https://blog.logrocket.com/lighthouse-meets-github-actions-use-lighthouse-ci/\" />\n</head>",
  "title": "Lighthouse meet GitHub Actions"
}