preface

Recently, I was reading a question on LeetCode, thinking about how to make a document to record the question, idea and solution. Just a few days ago, I used GitHub Actions, combined with Vuepress, and automatically deployed the article to GitHub Pages. Why don’t you file the algorithm on GitHub, too?

But there are not necessarily only a few algorithm solutions and ideas, different languages are not the same way to achieve, that is, for different algorithm problems to create the corresponding issue as a comment area, for the bosses to show their respective SAO operation, so that is not the United States zizier zier ~

Creating these issues manually isn’t elegant enough. Now that you’ve had a taste of Actions, let’s leave it to it.

(Actions come here! Come to work!

Note: this article is mainly to share how to use Actions to automatically create issues, about if automatic deployment document method, concrete can refer to my previous article: https://juejin.cn/post/7029247758582153252Copy the code

start

There are two main steps to complete the function described in the title:

1. Create an issue 2. Automate the process of creating an issue through ActionsCopy the code

Create issue

The way to create an issue here is definitely not to manually create it under the GitHub project.

One library I recommend: Octokit. This library provides the ability to manipulate GitHub, and in this case, we use it to help us create issues.

Of course, it offers more than just the ability to manipulate GitHub, as described below:

The `octokit` package integrates the three main Octokit libraries
1.  **API client** (REST API requests, GraphQL API queries, Authentication)
2.  **App client** (GitHub App & installations, Webhooks, OAuth)
3.  **Action client** (Pre-authenticated API client for single repository)
Copy the code

Interested partners can poke links to explore, here do not do too much verbose ~

Step 1: The old rule, if you need it, install one:

yarn add -D octokit
Copy the code

Step 2: Create the executable file that creates the issue

Bring in the octokit you just installed and start writing the logic to create the issue.

// utils/createIssues.js

const { Octokit } = require("octokit")
// The token of the GitHub account is passed in
const octokit = new Octokit({ auth: 'your token' })

octokit.rest.issues.create({
  owner: "your name".// GitHub account name
  repo: "your project name" // Project name
  title: 'Delete duplicates in sorted array'./ / issue title
  body: 'More on removing duplicates from sorted arrays are welcome to discuss in issue ~' / / issue description
})
Copy the code

To initialize octokit, you need the token of your GitHub account. You can create one in the Account Settings

After the file is created, run it in the console to see if the issue is ready to be created. Start by adding the create:issue command to the scripts of package.json

scripts: {
  "create:issue": "node utils/createIssues.js"
}
Copy the code

Then perform

yarn create:issue
Copy the code

After executing the script, go to the appropriate project directory on GitHub and click on the Issues option:

At this point we can see that the issue has been successfully created! At this point, our first feature point is complete! (Scatter flowers ~)

Automate the process of creating an issue through Actions

Now we need to automate the process of creating the issue. In this case, we do this through the official provided actions for creating Javascript.

Step 1: Create an operation metadata file

In the project root directory, create the action.yml file:

name: 'GET TOKEN' # the name
description: 'Get secrets token' # description
runs:
  using: 'node12' Specifies to execute on node12
  main: 'utils/createIssues.js' # specify the file to execute
Copy the code

Step 2: Create an Action

In the GitHub project, select Actions and create a new Workflow. In the Actions screen, Git will provide some templates for us to use. Here we will choose the default one:

Once created, one will be generated by default under our project.github/workflows/blank.ymlFile for the configuration script, which we modify slightly:

# Action Name name: CREATE ISSUES # Action execution timing on: # Execute push: # execute master Branches: [master] # execute pull_request in PR phase: # execute master Branches: [master] # execute job: build: # run-on: ubuntu-latest # steps: # run-on: ubuntu-latest # steps: # run-on: ubuntu-latest # uses: Actions /checkout@v2 - name: Install packages # Run: NPM install-name: Create an issue uses:./ # Use action.yml in the root directoryCopy the code

Step 3: Verify && find problems

After the action was created and submitted, we went to GitHub’s Actions and waited for the script to finish. Then we switched to Issues and found that the issue was not successfully created! At this time, Zhang Fei could not help asking:

The reason? Let’s click on the console and see what the problem is:

In short, the token is invalid!

So why does the token lapse? The problem is with utils/ createissues.js where we created the issue. In this file, the token we pass in when we initialize octokit is passed in plain text and is immediately invalidated when we upload the action.

Step 4: Solve the problem

Don’t understand ask: that how to step 3 in the question? Answer: since the problem is passing in token in plaintext, let’s not pass in token in plaintext! Use utils/ createissue. js to obtain a token without writing it. A: There is an official toolkit available: @Actions/Core. With this package, we can retrieve the content passed from the action.

Problem solving type 1: The old rule, if we use it, then we install it!
yarn add -D @actions/core
Copy the code
Problem Solving Type 2: Modify the Action execution script

To get the token through action, we need to get it to be thrown first.

Back in the user Settings screen, we regenerated a token and set this token to the Secrets option in the project Settings:

Then modify the script file slightly to add the with configuration

# omit a lot of code ahead... - name: Create an issue uses:./ # Use the root directory action.yml with: token: ${{secrets.token}} # Throw tokenCopy the code
Type 3: Modify the action.yml file to define the input items used to accept tokens
name: 'GET TOKEN' # the name
description: 'Get secrets token' # description
# define input items
inputs:
  token:  Enter the name of the item
    description: 'Get secrets token' Enter a description of the item
    required: true Whether the entry is required
runs:
  using: 'node12' Specifies to execute on node12
  main: 'utils/createIssues.js' # specify the file to execute
Copy the code
Problem solving Type 4: Set the token

Add a reference to @Actions /core in the utils/ createissues.js file and get token:

const { Octokit } = require("octokit")
const core = require('@actions/core')

const auth = core.getInput('token')
const octokit = new Octokit({ auth })

octokit.rest.issues.create({
  owner: "your name".// GitHub account name
  repo: "your project name" // Project name
  title: 'Delete duplicates in sorted array'./ / issue title
  body: 'More on removing duplicates from sorted arrays are welcome to discuss in issue ~' / / issue description
})
Copy the code

Then submit the modification item and check GitHub’s Actions again to find that the script runs correctly and the new issue has appeared in Issues.

At this point, function completion has come to an end ~

thinking

Through the above operations, we have now realized the function of automatically creating the issue, but the function is not perfect, there are mainly two problems:

1. After updating the document every time, I have to manually modify the title and body of the issue to ensure the correctness of the issue I created, which is obviously not feasible. 2. How can I ensure that the issue is not created repeatedly each time it is re-executed?Copy the code

So how to solve it?

For Question 1:

In docs/.vuepress/config.js, we can get the sidebar configuration. Through this configuration, I must have a way to get the title information.

Here, I use a library: Markdown-to-ast. This library converts the markDown file contents into an AST, which I can use to get the title content:

const vuepressConfig = require(".. /docs/.vuepress/config")
const fs = require("fs")
const path = require("path")
const { parse } = require("markdown-to-ast")

const baseDir = '/notes/exercises/'
// Get the exercise file
const { themeConfig: { sidebar } } = vuepressConfig
const exercisesSidebar = sidebar[`${baseDir}`]
const exercisesFiles = exercisesSidebar.reduce((files, item) = > {
 if( item && item.children ) { files.push(... item.children) }return files
}, [])
// Get the mapping between the title and the file path
const docs = exercisesFiles.map(fileDir= > {
 const content = fs.readFileSync(path.resolve(__dirname, '.. / '.`docs${baseDir}${fileDir}`), {
  encoding: 'utf-8'
 })
 const { children } = parse(content)
 const titleConfig = children.filter(ch= > ch.type === 'Header' && ch.depth === 1)
 let title = ' '
 if (titleConfig && titleConfig.length) title = titleConfig[0].raw.replace(The '#'.' ')
 return {
  title,
  fileDir
 }
})

module.exports = { exercisesSidebar, exercisesFiles, docs }
Copy the code

Then I just need to import docs in utils/ createissues.js and iterate to get the title:

const { Octokit } = require("octokit");
const core = require('@actions/core');
const { docs } = require('./getAllDocs')

const auth = core.getInput('token')
const octokit = new Octokit({ auth })

const titles = docs.filter(doc= > doc.title)

titles.forEach(title= > {
 octokit.rest.issues.create({
  owner: "your name".repo: "your project name",
  title,
  body: ` about${title}More solutions are welcome to discuss ~ 'in issue
 });
})
Copy the code

For Question 2:

How do you avoid repeating the same issue? Wouldn’t it solve the problem if I could get a list of active issues that have been created and filter them out? How do I get active issues that have been created? The answer is to use the Octokit library mentioned above. It provides a way to get a list of active issues:

Once again, we are very interested inutils/createIssues.jsMake some changes to the file:

const { Octokit } = require("octokit");
const core = require('@actions/core');
const { docs } = require('./getAllDocs')

const auth = core.getInput('token')
const octokit = new Octokit({ auth })

// Define common project parameters
const REPO_INFO = {
 owner: "your name".repo: "your project name"
}
// Get all issues
async function getAllIssues () {
 return awaitoctokit.paginate(octokit.rest.issues.listForRepo, { ... REPO_INFO,per_page: 100,
 })
}
getAllIssues().then(data= > {
 if (data && data.length) {
  let issuesList = data.map(issue= > issue.title)
  // Get the title of the issue not created
  const titles = docs.filter(doc= >! issuesList.includes(doc.title))// create an issue for all algorithms that do not create an issue
  titles.forEach(title= >{ octokit.rest.issues.create({ ... REPO_INFO, title,body: ` about${title}More solutions are welcome to discuss ~ 'in issue
   });
  })
 }
}).catch(err= > { console.log(err) })
Copy the code

In this way, we can filter the issues that we have already created and solve the problem perfectly

conclusion

At this point, we have completed the automatic creation of issues through GitHub Actions.

There is about this article project with source, interested partners can stamp here ~. Welcome to star, and leave your own action in issues

The document address mentioned in this article is also deployed and can be stamped here ~

Refer to documentation && videos

Cui Big teaching video ~

Deploy Vuepress using Git Actions

Create Javascript actions

octokit

@actions/core

markdown-to-ast