编写 JavaScript Actions

编写属于自己的 GitHub JavaScript Action,用它来自动化你的工作流程。

这是一个交互式课程,需要在 GitHub 上实际操作来完成学习。本页面为静态预览,仅方便您一次性阅读所有步骤内容。

前往 GitHub 开始学习 →

📖课程概览

English | 中文

本课程翻译自 Github Skills,全部课程请点击 这里查看

编写 JavaScript Actions

编写属于自己的 GitHub JavaScript Action,用它来自动化你的工作流程。

Welcome

在这门课程中,你将学习如何编写并发布属于你自己的 JavaScript Action,来定制你的工作流程。

  • 目标人群:开发者、GitHub 用户、Git 新手、学生、项目管理者以及团队成员。
  • 你将学到:如何在工作流文件中使用现有的 Actions,以及如何创建自定义的 JavaScript Action,并将它发布到 GitHub Marketplace。
  • 先决条件:在开始之前,你需要对 GitHub、GitHub Actions 以及持续集成(CI)有基本了解。
  • 课程时长:大约需要 1 到 2 小时完成课程。

在本课程中,你将:

  1. 初始化一个 JavaScript 项目
  2. 配置一个 Action
  3. 创建元数据文件
  4. 编写 JavaScript 脚本
  5. 在 workflow 文件中添加 Action
  6. 触发 Action 运行

开始学习本课程

start-course

  1. 右键点击上方 Start course 按钮,选择在新标签页中打开链接。
  2. 在新页面中根据系统提示新建一个仓库。
    • 仓库名称、描述这些字段系统已经帮我们自动填充好了,您可以按需修改。
    • 建议选择公开仓库,因为私有仓库有GitHub Actions 分钟数限制
    • 最后点击 Create repository 按钮
  3. 仓库创建完毕后,等待大约 20 秒(等待Action执行),然后刷新页面。注意是刷新您仓库的页面,不是本课程的页面。如果页面没有变化,请继续等待。然后按照 README 中的步骤一步步进行。

🎯课程步骤

GitHub

Step 1: 初始化 JavaScript 项目

欢迎来到本课程 🎉

配置工作流

GitHub 仓库默认已经启用了 Actions,但要让它实际运行,还需要告诉仓库“应该执行什么”。具体做法是在仓库中创建一个工作流(workflow)文件来实现。

Workflow 文件用于描述自动化流程,它由 jobs(任务)和 steps(步骤)组成,以及触发执行所需的条件。

一个仓库中可以包含多个 workflow 文件,用于执行不同的任务。因此,在命名工作流文件时,应确保名称能准确反映其执行的任务内容。

在本课程中,我们会为了教学方便,将多个任务都放在同一个 workflow 文件中,这在实际项目中并不推荐。

了解更多:关于工作流 (workflows) 官方文档

准备你的开发环境

在接下来的练习中,我们将使用 GitHub ToolKit 来开发 JavaScript Actions。

这是一个外部依赖库,需要通过 npm 安装,因此你的电脑上必须先安装 Node.js

我们推荐在本地环境中编写 Action,而不是直接在 GitHub 的网页端操作。这样你可以使用自己熟悉的编辑器、插件等让开发更高效。

如果你没有 IDE 偏好,建议使用 Visual Studio Code,它与本课程的演示保持一致。

别忘了准备好你的开发环境

接下来的步骤大部分都需要在本地执行,因此请先确保你在电脑上安装了以下工具:

  1. Node.js
  2. Visual Studio Code 或其他编辑器。
  3. Git

⌨️ 实操环节:初始化一个新的 JavaScript 项目

在本地安装好以上工具后,按照下面的步骤创建你的第一个 Action:

  1. 打开终端(macOS / Linux)或命令提示符(Windows)。

  2. 克隆当前练习仓库到本地:

    git clone <this repository URL>.git
    
  3. 进入刚刚克隆的仓库目录:

    cd <local folder with cloned repo>
    
  4. 切换到 main 分支:

    git switch main
    
  5. 创建一个新文件夹,用于存放我们的 Action 文件:

    mkdir -p .github/actions/joke-action
    
  6. 进入刚创建的 joke-action 文件夹:

    cd .github/actions/joke-action
    
  7. 初始化 Node.js 项目(使用默认配置):

    npm init -y
    
  8. 使用 npm 安装所需依赖:GitHub ToolKit 相关包以及请求库:

    npm install --save request request-promise @actions/core
    
  9. 将新增的文件提交到仓库中(我们稍后会处理 node_modules 的上传问题):

    git add .
    git commit -m 'add project dependencies'
    
  10. 将修改推送到远程仓库:

    git push
    
  11. 等待约 20 秒后刷新本页面。GitHub Actions 会自动检测到你的更改,并进入下一步。

GitHub

Step 2: 配置你的 Action

很好! 继续 🚲

我们已经完成前期准备工作,接下来就来创建我们的 joke-action 吧。

⌨️ 实操环节

接下来的所有步骤都在 .github/actions/joke-action 目录下进行。

我们先定义 Action 所必需的参数,后续随着功能演进,再逐步添加可选参数。

  1. .github/actions/joke-action 目录下创建一个新文件 action.yml

  2. 打开该文件并添加以下内容:

    name: "my joke action"
    
    description: "use an external API to retrieve and display a joke"
    
    runs:
      using: "node16"
      main: "main.js"
    

    这段配置的含义是:

    • name:Action 的名称(这里叫“my joke action”);
    • description:Action 的简单描述;
    • runs:定义运行环境为 Node.js 16,并指定入口文件为 main.js
  3. 保存 action.yml 文件。

  4. 将修改提交并推送到 main 分支:

    git add action.yml
    git commit -m 'create action.yml'
    git pull
    git push
    
  5. 等待大约 20 秒后刷新本页面。GitHub Actions 会自动检测更新,并跳转到下一步。

GitHub

Step 3: Action 元数据文件

在上一步中我们已经创建好了 Action 元数据文件,本节我们来完善它。

关于 Action 的元数据

每个 GitHub Action 都必须具有一个 元数据文件(metadata file)。并遵守如下规则:

  • 文件名必须action.yml.
  • 无论是 Docker 类型还是 JavaScript 类型的 Action 都需要它。
  • 文件内容使用 YAML 语法编写。

这个文件主要定义了 Action 的以下信息:

参数 说明 是否必需
Name Action 的名称,用于在工作流中直观识别。
Description 对 Action 功能的简要描述。
Inputs 输入参数,允许你在运行时向 Action 传入数据。这些参数在运行器中会作为环境变量使用。
Outputs 指定 Action 执行后产生的输出数据,供工作流中后续的步骤使用。
Runs Action 执行时要运行的命令或入口文件。
Branding 可设置图标和颜色,在 GitHub Marketplace 中个性化展示你的 Action。

想了解更多,请查看 Action 元数据语法说明

⌨️ 实操环节:补充元数据文件

以下步骤都在 .github/actions/joke-action 目录下完成。

我们的 Action 不需要复杂的元数据即可运行。本次我们不会接收任何输入参数,但会定义一个输出参数。

  1. 更新元数据文件 .github/actions/joke-action/action.yml,内容如下:

    name: "my joke action"
    
    description: "use an external API to retrieve and display a joke"
    
    outputs:
      joke-output:
        description: The resulting joke from the icanhazdadjokes API
    
    runs:
      using: "node16"
      main: "main.js"
    
  2. 保存 action.yml 文件。

  3. 提交并推送修改到 GitHub:

    git add action.yml
    git pull   
    git commit -m 'add metadata for the joke action'
    git push
    
  4. 等待大约 20 秒后刷新本页面,GitHub Actions 会自动检测更改并进入下一步。

GitHub

Step 4: 为你的 Action 编写 JavaScript 代码

元数据文件已经加好了! 💃

文件结构

在 JavaScript(以及其他编程语言)中,我们通常会把代码拆分成多个模块,方便阅读和维护。 由于 JavaScript Actions 本质上也是一段根据特定触发条件运行的 JS 程序,我们同样可以采用模块化的方式组织代码。

在本步骤中,我们将创建两个文件:

  1. joke.js:负责从外部 API 获取一个笑话;
  2. main.js:调用上面的模块,并将笑话输出到控制台。

在下一步中,我们还会进一步扩展它的功能。

获取笑话数据

笑话 API

我们首先创建 joke.js 文件,用来从 icanhazdadjoke API 获取笑话。 这个 API 不需要认证,但需要在请求头中设置一些参数。

调用该 API 后,我们会收到一个 JSON 对象,格式如下:

{
  "id": "0LuXvkq4Muc",
  "joke": "I knew I shouldn't steal a mixer from work, but it was a whisk I was willing to take.",
  "status": 200
}

返回的数据包含三个键值对,其中我们只关心 joke 字段,它就是笑话的内容。

笑话模块实现

.github/actions/joke-action 目录下创建文件 joke.js,内容如下:

const request = require("request-promise");

const options = {
  method: "GET",
  uri: "https://icanhazdadjoke.com/",
  headers: {
    Accept: "application/json",
    "User-Agent": "Writing JavaScript action GitHub Skills course.",
  },
  json: true,
};

async function getJoke() {
  const res = await request(options);
  return res.joke;
}

module.exports = getJoke;

代码说明:

  • 首先导入我们之前通过 npm 安装的 request-promise 库;

  • 定义 options 对象,其中包含请求方式、目标 URL 以及请求头;

    • Accept 表示希望返回 JSON 格式;
    • User-Agent 是 API 要求的标识;
  • 定义一个异步函数 getJoke(),发送请求并获取响应;

  • 函数返回 JSON 对象中的 joke 字段内容(每次调用都会返回不同的笑话);

  • 最后通过 module.exports 导出函数,以便在 main.js 中使用。

创建 Action 的主入口

Main 模块

在同一目录下创建 main.js 文件,内容如下:

const getJoke = require("./joke");
const core = require("@actions/core");

async function run() {
  const joke = await getJoke();
  console.log(joke);
  core.setOutput("joke-output", joke);
}

run();

代码说明:

  • 首先引入我们自己写的 joke.js 模块,以及 GitHub 提供的 @actions/core 库;

  • 定义一个异步函数 run()

    • 调用 getJoke() 获取笑话内容并存入变量 joke
    • 将笑话打印到控制台;
    • 使用 core.setOutput() 将笑话内容设置为输出参数 joke-output(稍后会被其他步骤使用)。
  • 最后调用 run() 来执行整个流程。

⌨️ 实操环节

  1. 创建文件 .github/actions/joke-action/joke.js,内容如下:

    const request = require("request-promise");
    
    const options = {
      method: "GET",
      uri: "https://icanhazdadjoke.com/",
      headers: {
        Accept: "application/json",
        "User-Agent": "Writing JavaScript action GitHub Skills course.",
      },
      json: true,
    };
    
    async function getJoke() {
      const res = await request(options);
      return res.joke;
    }
    
    module.exports = getJoke;
    
  2. 保存 joke.js 文件。

  3. 创建文件 .github/actions/joke-action/main.js,内容如下:

    const getJoke = require("./joke");
    const core = require("@actions/core");
    
    async function run() {
      const joke = await getJoke();
      console.log(joke);
      core.setOutput("joke-output", joke);
    }
    
    run();
    
  4. 保存 main.js 文件。

  5. 提交修改并推送到 GitHub:

    git add joke.js main.js
    git commit -m 'creating joke.js and main.js'
    git pull
    git push
    
  6. 等待大约 20 秒后刷新本页面。GitHub Actions 会自动检测更新,并进入下一步。

GitHub

Step 5: 在 workflow 文件中引用你的 Action

干得漂亮! 🎉

接下来的步骤会把你刚创建的 Action 添加到仓库中已有的工作流文件 my-workflow.yml 中。

⌨️ 实操环节: 在 workflow 文件中引用自定义 Action

my-workflow.yml 文件中添加如下内容:

- name: ha-ha
  uses: ./.github/actions/joke-action

完整的 workflow 文件示例如下:

name: JS Actions

on:
  issues:
    types: [labeled]

jobs:
  action:
    if: ${{ !github.event.repository.is_template }}
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - name: ha-ha
        uses: ./.github/actions/joke-action

说明:

  • 我们这里使用 issues 事件触发,而不是 pull_request
  • 移除了之前示例中的 hello-world Action。
  • uses: ./.github/actions/joke-action 指向本地的自定义 Action 目录。

你可以在浏览器中打开 my-workflow.yml 并直接编辑文件。 记得选择 Commit directly to the main branch 以直接提交更改。

等待大约 20 秒后刷新本页面,GitHub Actions 会自动检测更新,并进入下一步。

GitHub

Step 6: 触发你的笑话 Action

太棒了! ❤️

现在一切准备就绪,我们可以准备“开怀大笑”了 😄

在本仓库中,你会看到一些与笑话相关的标签(labels)。 实际上,任何标签都会触发我们的工作流,但为了方便跟随课程演示,建议使用推荐的标签。

触发笑话 Action

  1. 打开 Issues tab页中的 issue #1。
  2. 给这个 issue 添加标签 first-joke
  3. 等几秒钟后,再给同一个 issue 添加标签 second-joke
  4. 打开 Actions 标签页,查看 JS Actions 工作流的执行结果。
  5. 等待大约 20 秒后刷新本页面,GitHub Actions 会自动检测更新,并进入下一步。
GitHub

完成

celebrate

恭喜你,成功完成了本课程!

在本课程中,你学习了如何使用 JavaScript 和 Actions Toolkit 开发自定义 Action,并将其集成到你的工作流中。

发布你的 Action

将你的 Action 发布到 GitHub Marketplace 是一个很好的方式,不仅能帮助你的团队,也能惠及整个 GitHub 社区。 虽然 Action 并不一定要发布才能使用,但发布后其他人可以更方便地找到并使用它。

Marketplace 上的一些热门 Action 示例:

这仅仅是 Marketplace 上 1600+ 个 Action 的冰山一角。

想要学习如何将你的 Action 发布到 GitHub Marketplace,可以参考官方指南

接下来可以做什么?

恭喜你迈出了成为 GitHub Action 开发者的重要一步! 🎉

关于 GitHub Skills

GitHub Skills 是 GitHub 官方提供的交互式学习平台。 原始课程需要在 GitHub 上执行操作,通过 GitHub Actions 自动检测进度。

本页面将所有步骤展示在一个页面中,方便您一次性阅读全部内容。

前往 GitHub 实操练习