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.yml
File 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.js
Make 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