Search by Algolia
Algolia's search propels 1,000s of retailers to Black Friday success
e-commerce

Algolia's search propels 1,000s of retailers to Black Friday success

In the midst of the Black Friday shopping frenzy, Algolia soared to new heights, setting new records and delivering an ...

Bernadette Nixon

Chief Executive Officer and Board Member at Algolia

Generative AI’s impact on the ecommerce industry
ai

Generative AI’s impact on the ecommerce industry

When was your last online shopping trip, and how did it go? For consumers, it’s becoming arguably tougher to ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

What’s the average ecommerce conversion rate and how does yours compare?
e-commerce

What’s the average ecommerce conversion rate and how does yours compare?

Have you put your blood, sweat, and tears into perfecting your online store, only to see your conversion rates stuck ...

Vincent Caruana

Senior Digital Marketing Manager, SEO

What are AI chatbots, how do they work, and how have they impacted ecommerce?
ai

What are AI chatbots, how do they work, and how have they impacted ecommerce?

“Hello, how can I help you today?”  This has to be the most tired, but nevertheless tried-and-true ...

Catherine Dee

Search and Discovery writer

Algolia named a leader in IDC MarketScape
algolia

Algolia named a leader in IDC MarketScape

We are proud to announce that Algolia was named a leader in the IDC Marketscape in the Worldwide General-Purpose ...

John Stewart

VP Corporate Marketing

Mastering the channel shift: How leading distributors provide excellent online buying experiences
e-commerce

Mastering the channel shift: How leading distributors provide excellent online buying experiences

Twice a year, B2B Online brings together America’s leading manufacturers and distributors to uncover learnings and industry trends. This ...

Jack Moberger

Director, Sales Enablement & B2B Practice Leader

Large language models (LLMs) vs generative AI: what’s the difference?
ai

Large language models (LLMs) vs generative AI: what’s the difference?

Generative AI and large language models (LLMs). These two cutting-edge AI technologies sound like totally different, incomparable things. One ...

Catherine Dee

Search and Discovery writer

What is generative AI and how does it work?
ai

What is generative AI and how does it work?

ChatGPT, Bing, Bard, YouChat, DALL-E, Jasper…chances are good you’re leveraging some version of generative artificial intelligence on ...

Catherine Dee

Search and Discovery writer

Feature Spotlight: Query Suggestions
product

Feature Spotlight: Query Suggestions

Your users are spoiled. They’re used to Google’s refined and convenient search interface, so they have high expectations ...

Jaden Baptista

Technical Writer

What does it take to build and train a large language model? An introduction
ai

What does it take to build and train a large language model? An introduction

Imagine if, as your final exam for a computer science class, you had to create a real-world large language ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

The pros and cons of AI language models
ai

The pros and cons of AI language models

What do you think of the OpenAI ChatGPT app and AI language models? There’s lots going on: GPT-3 ...

Catherine Dee

Search and Discovery writer

How AI is transforming merchandising from reactive to proactive
e-commerce

How AI is transforming merchandising from reactive to proactive

In the fast-paced and dynamic realm of digital merchandising, being reactive to customer trends has been the norm. In ...

Lorna Rivera

Staff User Researcher

Top examples of some of the best large language models out there
ai

Top examples of some of the best large language models out there

You’re at a dinner party when the conversation takes a computer-science-y turn. Have you tried ChatGPT? What ...

Vincent Caruana

Sr. SEO Web Digital Marketing Manager

What are large language models?
ai

What are large language models?

It’s the era of Big Data, and super-sized language models are the latest stars. When it comes to ...

Catherine Dee

Search and Discovery writer

Mobile search done right: Common pitfalls and best practices
ux

Mobile search done right: Common pitfalls and best practices

Did you know that 86% of the global population uses a smartphone? The 7 billion devices connected to the Internet ...

Alexandre Collin

Staff SME Business & Optimization - UI/UX

Cloud Native meetup: Observability & Sustainability
engineering

Cloud Native meetup: Observability & Sustainability

The Cloud Native Foundation is known for being the organization behind Kubernetes and many other Cloud Native tools. To foster ...

Tim Carry

Algolia DocSearch is now free for all docs sites
product

Algolia DocSearch is now free for all docs sites

TL;DR Revamp your technical documentation search experience with DocSearch! Previously only available to open-source projects, we're excited ...

Shane Afsar

Senior Engineering Manager

4 questions to ask for relevant search results
product

4 questions to ask for relevant search results

Relevance – it’s what we’re all going for with our search implementations, but it’s so subjective that it ...

Jaden Baptista

Technical Writer

Looking for something?

facebookfacebooklinkedinlinkedintwittertwittermailmail

GitHub Issues are static content. What if they didn’t have to be?

When we (DevRels Chuck Meyer and Bryan Robinson) discovered that Dev.to was hosting a GitHub Actions hackathon, we knew we needed to give it a try.

We knew we wanted to figure out a useful tool to integrate Algolia into an Action. There were obvious thoughts on what sort of project to undertake. We thought through the usual takes on indexing content, products, or markdown. They all would have been helpful for web creators. Would they have been helpful to open source maintainers, though? Probably?

How could we make their overall workflow better?

Then it struck us: What if we could give recommended Issues for frequently asked questions? Could we lessen the burden of maintainers answering similar questions? How many Issues get closed as “duplicate” in large repositories? Could Algolia provide Issue creators a list of related, helpful Issues?

Spoiler alert: Yeah, totally!

The Workflow structure

When a developer adds an Issue to a repository, we need to execute three steps.

First, we need to search an Algolia Index for related Issues. Then, we bundle those results into Markdown and pass it to an Action to create a comment on the initial Issue. Finally, we need to put the Issue into our Index for future searches.

Each of these steps requires an Action. The Algolia-specific Actions, we needed to create from scratch. The comment-writing Action, we decided to use the amazing Peter Evan’s create-or-update-comment Action – which, as it turns out, GitHub uses in many of their docs about Actions.

Let’s dive into the new Actions.

Performing a search query

The first step of our Workflow is a search query sent to Algolia. We created a custom Action for this Get Algolia Issue Records.

To use the Action, we need to send it four required inputs (and an optional fifth).

  • app_id: the ID of the application in your Algolia account. This is best stored as a Secret in your repository
  • api_key: An API key with search permissions to the Index in your Algolia App. This is best stored in a Secret in your repository.
  • index_name: The name of the Algolia Index to search. For consistency, we recommend the github.event.repository.name variable.
  • issue_title: The title of the inciting Issue found with github.event.issue.title.
  • max_results: (OPTIONAL) A number of results to return to the comment (defaults to 3)

We take these variables and perform a similarQuery search based on the inciting Issue’s title. We then create a comment body and a list of items in Markdown (the format needed for GitHub comments). This outputs are passed to Peter Evans’ create-or-update-comment Action.

const { inspect } = require('util');
const core = require('@actions/core');
const algoliasearch = require('algoliasearch');

async function run() {
  try {
    const inputs = {
      appId: core.getInput('app_id'),
      apiKey: core.getInput('api_key'),
      indexName: core.getInput('index_name'),
      issueTitle: core.getInput('issue_title'),
      maxResults: core.getInput('max_results'),
    };
    core.info(`Inputs: ${inspect(inputs)}`);

    if (!inputs.appId && !inputs.apiKey && !inputs.indexName) {
      core.setFailed('Missing one or more of Algolia app id, API key, or index name.');
      return;
    }

    inputs.maxResults = inputs.maxResults || 3;

    const client = algoliasearch(inputs.appId, inputs.apiKey);
    const index = client.initIndex(inputs.indexName);

    index.search('', { 
        similarQuery: inputs.issueTitle,
        hitsPerPage: inputs.maxResults
      }).then(({hits}) => {
      core.info(`Searching for record`);
      core.info(`Hits: ${inspect(hits)}`);
      const message = `## Other issues similar to this one:\n${hits.map(hit => `* [${hit.title}](${hit.url})`).join('\n')}`
      const listItems = `${hits.map(hit => `* [${hit.title}](${hit.url})`).join('\n')}\n`
      core.info(message)
      core.info(listItems)
      core.setOutput('comment_body', message);
      core.setOutput('issues_list', listItems);
    })
      .catch(err => {
        core.setFailed(err.message);
      }
    );
  } catch (error) {
    core.debug(inspect(error));
    core.setFailed(error.message);
    if (error.message == 'Resource not accessible by integration') {
      core.error(`See this action's readme for details about this error`);
    }
  }
}

run();

Adding the issue to your Algolia index

For the final step of our workflow, we add this new issue to the Algolia index for future searches. We created another GitHub Action for this purpose: Create or Update Algolia Index Record. This action atomically adds/updates a record directly to an index rather than writing/reading from a JSON file. This makes sense in situations where we are acting on metadata about the repo (issues, pull requests, comments) as opposed to building an index for the application itself.

To use this action, we’ll need to create an Algolia API key with permissions to add/update records in our index. Additionally, we will need permission to create a new index for the repo. Otherwise, we must create it ahead of time and hard code the index name in our configuration.

Along with the new API key we’ll need a few other inputs to use the action:

  • app_id: You should already have this as a Secret in your repository from the action above
  • api_key: This is the new key with permission to save records to your index. This is best stored in a Secret in your repository.
  • index_name: The name of the Algolia index to add/update this record. For consistency, we recommend the github.event.repository.name variable.
  • record: A string represneting the JSON record to add to the index.

If the API key has permission, the action creates an index for the repository. We’ll add the issue title and URL (to link back) as the record. It’s a multi-line string in our workflow, but must_ be valid JSON for the action to work (see Preparing your data for details).

We take all of these inputs and execute a saveObject call via the Algolia API. We use the issue ID as the objectID in the index. This makes it easy to tie the record back to this issue if we add workflows for update or delete events later.

const { inspect } = require('util');
const core = require('@actions/core');
const algoliasearch = require('algoliasearch');

async function run() {
  try {
    const inputs = {
      appId: core.getInput('app_id'),
      apiKey: core.getInput('api_key'),
      indexName: core.getInput('index_name'),
      record: core.getInput('record'),
    };
    core.debug(`Inputs: ${inspect(inputs)}`);

    if (!inputs.appId && !inputs.apiKey && !inputs.indexName) {
      core.setFailed('Missing one or more of Algolia app id, API key, or index name.');
      return;
    }

    core.info(`Writing record to index ${inputs.indexName}`)
    const client = algoliasearch(inputs.appId, inputs.apiKey);
    const index = client.initIndex(inputs.indexName);

    index.saveObject(JSON.parse(inputs.record), {'autoGenerateObjectIDIfNotExist': true})
      .then(({ objectID }) => {
        core.setOutput('object_id', objectID);
        core.info(
          `Created record in index ${inputs.indexName} with objectID ${objectID}.`
        );
      })
      .catch((err) => {
        core.setFailed(`Failed to save object: ${err}`);
      });

  } catch (error) {
    core.debug(inspect(error));
    core.setFailed(error.message);
    if (error.message == 'Resource not accessible by integration') {
      core.error(`See this action's readme for details about this error`);
    }
  }
}

run();

Next, we piece the two new Actions together with the existing comment creation action to build our workflow.

The full workflow file

To make this work, we need one job with three steps. Each step will use one of these Actions.

name: related-issues
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  issues:
    types: 
      - opened

jobs:
  get-related-issues:
    permissions: 
      # Gives the workflow write permissions only in issues
      issues: write
    runs-on: ubuntu-latest
    steps:
      # Performs a search in an Algolia Index based on Issue Title
      # The Index should have historical Issues
      # Returns two outputs:
      # issues_list: a markdown list of issues
      # comment_body: a generic comment body with the list of issues
      - id: search
        name: Search based on issue title
        uses: brob/algolia-issue-search@v1.0
        with: 
          # Requires an Algolia account with an App ID and write key
          app_id: ${{ secrets.ALGOLIA_APP_ID }}
          api_key: ${{ secrets.ALGOLIA_API_KEY }}
          index_name: ${{ github.event.repository.name }}
          issue_title: ${{ github.event.issue.title }}
      - name: Create or Update Comment
        uses: peter-evans/create-or-update-comment@v1.4.5
        with:
          # GITHUB_TOKEN or a repo scoped PAT.
          token: ${{ github.token }}
          # The number of the issue or pull request in which to create a comment.
          issue-number: ${{ github.event.issue.number }}
          # The comment body. Can use either issues_list or comment_body
          body: |
            # While you wait, here are related issues:
            ${{ steps.search.outputs.issues_list }}
            Thank you so much! We'll be with you shortly!
      # An Action to create a record in an Algolia Index
      # This is a generic Action and can be used outside of this workflow
      - name: Add Algolia Record
        id: ingest
        uses: chuckmeyer/add-algolia-record@v1
        with:
          app_id: ${{ secrets.ALGOLIA_APP_ID }}
          api_key: ${{ secrets.ALGOLIA_API_KEY }}
          index_name: ${{ github.event.repository.name }}
          # Record needs to be a string of JSON
          record: |
            {
              "title": "${{ github.event.issue.title }}", 
              "url": "${{ github.event.issue.html_url }}", 
              "labels": "${{ github.event.issue.labels }}",
              "objectID": "${{ github.event.issue.number }}"
            }

Next steps

We hope that this is helpful to maintainers, but we also hope it inspires others to find better and better ways to suggest content in static areas like GitHub Issues.

If you want to play around with the full workflow, you can check it out in this repository. Both the search and ingest Actions are available in the GitHub marketplace.

Search and discovery can become an interesting part of your automated workflow in GitHub and beyond.Check out related solutions on our open source code exchange platform.


About the authors
Bryan Robinson

Senior Developer Relations Specialist

githubtwitter
Chuck Meyer

Sr. Developer Relations Engineer

githubtwitter

Recommended Articles

Powered byAlgolia Algolia Recommend

Indexing Markdown content with Algolia
engineering

Michael King
Soma Osvay

Michael King &

Soma Osvay

How to use Algolia as a game engine debugging tool in Rust
engineering

Gyula László

Senior Developer @ Starschema

Building a Store Locator in React using Algolia, Mapbox, and Twilio – Part 3
engineering

Clément Sauvage

Software Engineer, Freelance