Guides & Tutorials

Hook into Netlify build events with Private Integrations

Have you slowly seen your team’s build process grow into a complex monster with configuration files the size of Mount Doom? Don’t worry, we’re here to help! Netlify Build Event Handlers can help make these processes more accessible for you and your team. Setting it up is a breeze — create a Private Integration once, and enable it for any site within your team. Did I mention it uses TypeScript? Throw out unnecessary complexity and join me in building next-generation integrations on Netlify.

What is a Build Event Handler?

Build Event Handlers open up a world of possibility by seamlessly integrating into the Netlify site building process and enhancing what Netlify builds can achieve. You can do things like perform post-build checks for broken links on your site, generate content such as sitemaps, RSS feeds, search indexes, and so much more. The imaginative digital sky is the limit!

As an example, I’m going to show you how you can build a private integration that checks for broken links on a site after building it but before deploying it. If it finds a broken link, it will automatically cancel the deploy.

Creating the basis for your private integration

You’ll be using the Netlify SDK to create your private integration. In your terminal, navigate to the folder where you want to make your integration and type: pnpm create @netlify/sdk@latest.

You will be prompted with some questions that help guide you in creating your new integration. Feel free to choose your own package manager, but make sure to go with the following answers:

? Where do you want to create the integration? link-checker-integration
? What is the slug of the integration? (e.g. my-integration) link-checker-integration
? What level will this integration be installed on? site
? Summarize what your integration does. This will be shown on the integration's card
on the Integrations page. This integration checks your build for any broken links
? Which boilerplate should be included? build
? Which package manager do you want to use? pnpm
? Select your permission scopes site:read
? Do you want to link a Netlify site to your integration? This will help you test your integration and will be used to host your integration. skip

Then, you can navigate to the directory it created for you by typing cd link-checker-integration. If you run ls you should be seeing something similar to this:

├── integration.yaml
├── netlify.toml
├── package.json
├── pnpm-lock.yaml
├── src
│   └── index.ts
└── tsconfig.json

Your Build Event Handler boilerplate

The SDK already made a few files for you! Let’s open up src/index.ts to see what your Build Event Handler boilerplate looks like:

// Documentation: https://sdk.netlify.com
import { NetlifyIntegration } from "@netlify/sdk";

const integration = new NetlifyIntegration();

integration.onEnable(async (_, { teamId, siteId, client }) => {
  // Build event handlers are disabled by default, so we need to
  // enable them when the integration is enabled.

  siteId && await client.enableBuildEventHandlers(siteId);
  
  return {
    statusCode: 200,
  };
});

integration.addBuildEventHandler("onPreBuild", () => {
  console.log("Hello there.");
});
  
export { integration };

There are a number of events in the build pipeline you can hook into if you want. But for this example let’s change the onPreBuild function to onPostBuild. Then make the function async and grab some function parameters like constants and utils. Your addBuildEventHandler method should look something like this:

integration.addBuildEventHandler('onPostBuild', async ({ constants, utils }) => {
  console.log("Hello there.");
});

Adding linkinator

To add the functionality of scanning a site’s build folder for any broken links we will use a package called linkinator, go ahead and run pnpm install linkinator.

Make sure to import the LinkChecker class from the package and create a new instance of it. Then use constants.PUBLISH_DIR to pass the folder that should be checked for any broken links. In this case I assume it will be the PUBLISH_DIR. You can set up your Build Event Handler in a way that, if the package finds any broken links, the deploy is cancelled! This is done by leveraging utils.build.failBuild.

This is what the code should look like:

// Documentation: https://sdk.netlify.com
import { NetlifyIntegration } from '@netlify/sdk';
import { LinkChecker } from 'linkinator';

const integration = new NetlifyIntegration();

integration.onEnable(async (_, { teamId, siteId, client }) => {
  // Build event handlers are disabled by default, so we need to
  // enable them when the integration is enabled.

  siteId && (await client.enableBuildEventHandlers(siteId));

  return {
    statusCode: 200,
  };
});

integration.addBuildEventHandler(
  'onPostBuild',
  async ({ constants, utils }) => {
    const checker = new LinkChecker();
    // Pass the PUBLISH_DIR that the site was built in
    const result = await checker.check({
      path: constants.PUBLISH_DIR,
    });

    // Log wether we passed or failed!
    console.log(result.passed ? 'PASSED :D' : 'FAILED :(');

    if (!result.passed) {
      // The list of checked links, and the pass/fail
      const brokeLinksCount = result.links.filter(
        (x: { state: string }) => x.state === 'BROKEN'
      );
      console.log(`Detected ${brokeLinksCount.length} broken links.`);

      // Show the list of scanned links and their results
      console.log(result);
      // Fail the build and cancel the deploy if there are broken links
      utils.build.failBuild('There are broken links, fix them first!');
    }
  }
);

export { integration };

That’s it! You are now ready to deploy your integration.

Deploy your integration

Alright, let’s get your integration out there for your team to use! First, make sure you commit the latest changes to your repository and publish it to your Git provider, for example GitHub. This way we can leverage Netlify’s continuous deployment. When you’re done with that, use the Netlify CLI to run netlify init in your terminal and answer the questions:

? What would you like to do? Create & configure a new site
? Team: {your team name}
? Site name (leave blank for a random name; you can change it later): {keep blank}
? Your build command (hugo build/yarn run build/etc): netlify-integration build -a
? Directory to deploy (blank for current dir): .ntli/site/static

Alright, you’re done! In your terminal, you should see an Admin URL. If you click it, it will take you to your admin panel in Netlify.

Creating a Private Integration

Now that we’ve deployed your code, we’re going to officially create a Private Integration out of it! In the Netlify UI, navigate to “integrations”. Once you’re there, select “Create a private integration” and fill in the form. You can find detailed information on the fields you see here, but I’ll highlight a few special ones as well:

  • Netlify integration site: select the name of the integration you have just deployed in the previous step!
  • Integration level: this integration will only work on a site level, so choose site.
  • Permission scopes: we only need site “read” permissions for this integration.

Smash that “create” button! You’re done!

Enabling your integration for your team’s sites

Now that your private integration has been deployed, we’re going to use it on one of your sites! Either find a site in your Netlify team that you want to use, or use the one I’ve made for you so you can test this integration out as soon as possible! You can deploy it with this button:

Deploy to Netlify

Once you’ve found a site you want to try your integration on, navigate to that site in the Netlify UI, and then go to “integrations”. Once you’re there, select the private integrations category. In that list you should be able to see a card with the name of the integration you just created. Enable that integration by selecting the “enable” button.

If you now run a new deploy on the site you’ve enabled your integration on, you should be able to see logs from your integration in the ‘build’ section of your deploy logs! Congratulations, you did it!

Next steps and making your integrations public

If you just want to try out this integration, use the button below to deploy it to your Netlify Team. And don’t forget to check out the template repository.

Deploy to Netlify

You can use this new integration on all of the sites you have within your Netlify Team! Learn more about building integrations on Netlify, or how to create a partner integration on Netlify.

Happy coding on Netlify!

Keep reading

Recent posts

How do the best dev and marketing teams work together?