This is the second day of my participation in Gwen Challenge

Fear what infinite truth, into an inch of joy. Hello everyone, I am @Luo Zhu, a lifelong learning practitioner who loves programming and life.

About making Apps

GitHub Apps are excellent products on GitHub. A GitHub App operates directly with its own identity through the API, which means you don’t need to maintain a bot or service account as a separate user.

GitHub Apps can be installed directly on an organization or user account and can be given access to a specific repository. They come with built-in Webhooks and narrow specific permissions. When you set up the GitHub application, you can select the repository you want it to access. For example, you can set up an application called MyGitHub that has and only has permission to write issues from the Octocat repository. To install the GitHub App, you need to be the owner of the organization or have admin privileges for the repository.

About the Probot

Probot is a framework for building GitHub Apps based on Node.js. It is designed to eliminate all the tedious things like receiving and validating Webhooks and doing authentication actions so you can focus on the features you want to implement. Probot applications are easy to write, deploy, and share. Most popular Probot apps are hosted, so you don’t need to do any deployment or administration. Here are a few applications built on Probot:

  • ESLint Disable Watcher – Comments when attempting to Disable ESLint rules in PR.
  • Developer Certificate of Origin – Force Pull Requests to comply with the DCO specification
  • Issue Check – Checks issues against keywords and task lists to ensure necessary information is included
  • Pull – Keep your forks up-to-date.

You can browse for more apps in the featured apps or GitHub Probot-App topic.

Hello Probot

A Probot application is essentially a Node.js module that exports a function:

module.exports = app= > {
  // your code here
};
Copy the code

The app argument is an instance of the Probot class that gives you access to all of GitHub’s gems.

Aap. on listens for all GitHub triggered Webhook events and notifies you when anything interesting happens on GitHub that your application wants to know about.

module.exports = app= > {
  app.on('issues.opened'.async context => {
    // A new issue is opened, what should we do?
    context.log.info(context.payload);
  });
};
Copy the code

The context passed to the event handler includes everything about the event that was fired, along with useful properties to respond to the event in a useful way. Octokit is a certified GitHub client that can be used to make REST API and GraphQL calls, and allows you to programmatically do almost anything you can do on GitHub via a browser.

Here is an App that automatically reviews when issues is opened.

module.exports = app= > {
  app.on('issues.opened'.async context => {
    // Context 'extracts information from events that can be passed to GitHub API calls. This returns:
    // { owner: 'yourname', repo: 'yourrepo', number: 123, body: 'Hello World ! }
    const params = context.issue({ body: 'Hello World! ' });

    // Post a comment on the issue
    return context.octokit.issues.createComment(params);
  });
};
Copy the code

Develop a Probot app

To develop a Probot app, you first need to install Node.js 10.0.0 or later.

Make a new app

Create-probot-app is the best way to start building a new app. It will generate a new application with everything you need to get started and run your application in production.

Run the following command to generate a project:

$ npx create-probot-app my-first-app
Copy the code

The command asks a series of questions about your app that look something like:

Let's create a Probot app!
? App name: my-first-app
? Description of app: A 'Hello World' GitHub App built with Probot.
? Author's full name: Katie Horne
? Author's email address: [email protected] ? GitHub user or org name: khorne3 ? Repository name: Which template would you like to use? (use arrow keys) ❯ basic-js basic-ts (use this one for TypeScript support) checks-js git-data-js deploy-js Finished scaffolding files! Installing dependencies. This may take a few minutes... Successfully created my-first-app. Begin using your app with: cd my-first-app npm start View your app's README for more usage instructions.

Visit the Probot docs:
  https://probot.github.io/docs/

Get help from the community:
  https://probot.github.io/community/

Enjoy building your Probot app!
Copy the code

The most important files to create are index.js (where your app code resides) and package.json (to make your app a standard NPM module).

Run your app locally

Now you’re ready to run your app locally. To start a server, run NPM start:

Note: If you choose a TypeScript template, be sure to execute NPM run build!

$yarn start YARN run v1.22.10 $probot run./lib/index.js INFO (server): Running Probot v11.3.0 (node.js: V14.15.5) INFO (server) : Forwarding https://smee.io/dz7D1zur24cGNj7 to http://localhost:3000/ INFO (server) : Listening on http://localhost:3000 INFO (server): ConnectedCopy the code

Configuration making App

Here are the steps to automatically configure the GitHub App:

  1. Execute on the local command linenpm start.
  2. Visit http://localhost:3000 for next steps.
  3. You will see a page similar to the following.

  1. Click the Register a GitHub App button to continue.
  2. Next, you need to give your App a name that is not already in use. Note: if you see something similarName is reserved for the account @tuyaThis means you cannot use the name of an existing GitHub organization as the name of your app (unless you are the owner of that organization).

When making the Releasenpm publish

GitHub CI automatically publishes NPM packages to properly manage the permission to publish external NPM packages. A more common time to release is at GitHub Release. Based on the analysis of the above flow chart, we can see that NPM publish is most appropriate for the released state.

The logic we implemented was to handle pre-release actions when the Probot app listened for a release. Released event. The important thing is that we need to match the tag to the version field in package.json, for example:

  • 1.0.0:tag 为 latest 的 1.0.0
  • 0: Tag is 1.0.0-beta.0 of beta
  • 1.0.0-alpha.0: Tag is 1.0.0-alpha of alpha

Implementation principle of NPM automatic publishing

Before publishing, we need to pull the repository code, extract the version and tag, set up the NPM publish Token, and so on. First on the core code, we will analyze in detail later.

app.on('release.released'.async context => {
  if(! isTuya(context))return;
  app.log('npm publishing');
  const { repository: repo } = context.payload;
  const downloadDefaultBranch = `${repo.full_name}#${context.payload.release.tag_name}`;
  const downLoadTempDir = `${os.tmpdir()}/${repo.full_name}`;
  await download(downloadDefaultBranch, downLoadTempDir);
  const { version, scripts } = require(`${downLoadTempDir}/package.json`);
  const tag = /^\d\.\d\.\d-(.*)\.\d$/.exec(version)
    ? /^\d\.\d\.\d-(.*)\.\d$/.exec(version)[1]
    : 'latest';
  // Execute the build script first if there is one
  if (scripts.build) {
    await execSh(`cd ${downLoadTempDir} && npm install && npm run build`);
  }
  try {
    const result = await npmPublish({
      package: `${downLoadTempDir}/package.json`.token: process.env.NPM_AUTH_TOKEN,
      registry: 'https://registry.npmjs.org/',
      tag,
    });
    if (result.type === 'none') {
      app.log.error(
        `You can't publish duplicate version ${result.package}@${result.version}`,); }}catch(error) { app.log.error(error); }});Copy the code

NPM Publish Token

Apply for the NPM Publish Token

1. Visit nPMjs.com to Access Tokens page

2. Click the Generate New Token button

3. Select Publish as the Token type

Ensure NPM Publish Token security

NPM tokens cannot be seen by others. In order to do this, first the project needs to be set to private, and then the Token is put into.env, which is obtained by process.env.npm_auth_token. Also remember not to print environment variables in the log.

Ensure GitHub App security

If we publish the GitHub App as public, then any repository can install the App, which is not what we want. The solution is either to register the application as private or to check whether it is an allowed organization or user in the listening callback. I choose the second option, and the check function is as follows:

const isTuya = context= > {
  const { full_name } = context.payload.repository;
  return full_name.startsWith('youngjuning') || full_name.startsWith('tuya');
};
Copy the code

Download the source code

We chose download-git-repo to download the Git repository, but the repository does not support Promise. Let’s do a simple change:

const download = require('download-git-repo');

module.exports = (repo, tempDir) = > {
  return new Promise((resolve, reject) = > {
    download(repo, tempDir, err= > {
      if (err) {
        reject(err);
      } else {
        resolve(null); }}); }); };Copy the code

npmPublish

We chose @jsDevTools /npm-publish to perform the publish Action, which can be used as GitHub actions and command-line tools in addition to programming calls. Note that we need to extract the tag we want to publish with the re:

const tag = /^\d\.\d\.\d-(.*)\.\d$/.exec(version)
  ? /^\d\.\d\.\d-(.*)\.\d$/.exec(version)[1]
  : 'latest';
Copy the code

lerna publish

Lerna management releases cannot use the release process mentioned above because they may release multiple repositories at once. For LERNA, THE release process I designed is to take the latest commit after listening to the push action and match whether chore(Release): publish. The specific principles are as follows:

  1. Determine if the push branch is the primary branch and the commit information containschore(release): publish
  2. Because lerna publishes, the simple-git library clone project is required.
  3. Due to lerna publishDo not support the token, we adopt will//registry.npmjs.org/:_authToken=${process.env.NPM_AUTH_TOKEN}write.npmrcTo publish tokens.
  4. Finally, we need to usefrom-gitIn the way thatlerna publish.from-gitThe scenario is local executionlerna version, executed in CIlerna publish.

The complete code is as follows:

app.on('push'.async context => {
  if(! isTuya(context))return;
  if( context.payload.ref.indexOf(context.payload.repository.default_branch) ! = = -1 &&
    context.payload.head_commit.message.indexOf('chore(release): publish') = = =0
  ) {
    app.log('push event');
    execSh(`git --version`);
    const { repository: repo } = context.payload;
    const cloneTempDir = `${os.tmpdir()}/${repo.full_name}`;
    try {
      await git.clone(repo.clone_url, cloneTempDir);
      const { devDependencies } = require(`${cloneTempDir}/package.json`);
      if (devDependencies['lerna']) {
        app.log('lerna publishing');
        await execSh(
          `cd ${cloneTempDir} && echo //registry.npmjs.org/:_authToken=${process.env.NPM_AUTH_TOKEN} > .npmrc`,);await execSh(
          `cd ${cloneTempDir} && npm install && npm run build && ./node_modules/.bin/lerna publish from-git --yes --no-verify-access`,); }await execSh(`rm -rf ${cloneTempDir}`);
    } catch (error) {
      await execSh(`rm -rf ${cloneTempDir}`); }}});Copy the code

Glitch deployment

If you have your own server, you can deploy the bot directly to your own server. I’m using the officially recommended Glitch service deployment here. Glitch can host Node applications for free and edit them directly in the browser. That’s fine for simple applications.

  1. To register and create a new project in Glitch, select Import from GitHub, pop up the app GitHub address, or use github.com/behaviorbot… Import as a template and copy your own code.
  2. Open the.envReplace the file with the following:
APP_ID=<your app id>
WEBHOOK_SECRET=<your app secret>
PRIVATE_KEY_PATH=<your private_key>
NODE_ENV=production
NPM_AUTH_TOKEN=3c2c104e-9f1f-4fc5-903e-726610b75ce1
INPUT_TOKEN=
Copy the code
  1. Just set the Glitch link to your GitHub App’s Webhook address, then update the code and Glitch will automatically deploy.

permissions

The initial permissions of the Probot App are in the app.yml file. If the App has been created and you want to update the permissions, you can go to github.com/settings/ap… In the update. Please click app.yml to view the permissions I used.

This article was first published on the official website of Luozhu, as well as the public account luozhu Morning Teahouse and Gold digging Column.