> For the complete documentation index, see [llms.txt](https://suki.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://suki.gitbook.io/notes/articles/dev-ops/github-actions/1.intro-to-actions.md).

# GitHub Action 简介

<https://lab.github.com/githubtraining/github-actions>

## 目标

* 学会如何创建 GitHub Action
* 学会如何在 workflow 中使用 GitHub Action

## GitHub Action 是什么？

GitHub Actions 是用来自动化任务的，比如：

* 自动化测试(CI)
* CD
* 自动使用 issues, @, labels 等响应 workflow triggers
* 触发 code review
* 管理分支
* 负责 issues, pr 的分类

这些任务都是代码，可以复用和分享。

## Actions and Workflows

每个 action 负责不同的事情，一个 workflow 里面可以有多个 action。

一个 action 可能会包含多个文件，一般每个 action 都有自己的文件夹，里面放着相关文件。

## Actions 的种类

action 分两种：

1. container action
2. javascript action

docker container action 将 action 代码和环境一起打包，只能在 GitHub-Hosted Linux 环境下运行。

JavaScript actions 将 action 代码和环境分开，执行速度更快，但是依赖管理的责任更重。

## 如何创建 action

### 第一步：新建 `Dockerfile`

Dockerfile 文件定义了 action 的 metadata。

新建 `action-name/Dockerfile` 文件：

```
# Dockerfile
FROM debian:9.5-slim

ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
```

### 第二步：添加入口脚本

上一步的 Dockerfile 文件中，最后一句指定了入口脚本文件，`/entrypoint.sh` 文件用来定义这个 action 具体要做的事情，它会在 Docker 中执行。

```
# Dockerfile
ENTRYPOINT ["/entrypoint.sh"]
```

所以我们要来定义这个入口文件，新建一个 `action-name/entrypoint.sh` 文件：

```bash
#!/bin/sh -l

sh -c "echo Hello world my name is $INPUT_MY_NAME"
```

### 第三步：添加 action metadata 文件

每个 action 都有一个 metadata 文件，使用 YAML 语法书写，文件定义了 action 的 `输入`、`输出` 和 `入口文件`。

新建一个 `action-name/action.yml` 文件：

```
name: 'Hello Actions'
description: 'Greet someone'
author: 'octocat@github.com'

inputs:
    MY_NAME:
        description: 'Who to greet'
        required: true
        default: 'World'

runs:
    using: 'docker'
    image: 'Dockerfile'

branding:
    icon: 'mic'
    color: 'purple'
```

### 第四步：定义 workflow 文件

workflow 文件定义在 `.github/workflows` 文件夹下。

我们可以自定义 workflow 执行的时机，比如 `push` 事件。

[workflow 触发时机](https://help.github.com/en/articles/events-that-trigger-workflows)可以是：

* github 事件
* 指定时间
* github 之外发生的事件

新建 `.github/workflows/main.yml` 文件：

```
# workflow 的名字
name: A workflow for my Hello World file

# 表示这个 workflow 会在 push 事件触发时执行
# on: [push] 格式可以指定多个触发事件
on: push
```

### 第五步：在 workflow 文件中执行 action

workflow 由 job 组成，job 由 step 组成，一个 step 可以是一个 action，也可以是一个 bash 命令。

job 可以执行 action，我们可以执行定义在同一个仓库下的 action，也可以是其他仓库的 action，或者是发布在社区的 action。

修改 `.github/workflows/main.yml` 文件：

```
# workflow 的名字
name: A workflow for my Hello World file
# 表示这个 workflow 会在 push 事件触发时执行
on: push

# jobs 是一个 workflow run 的基本组成部分
jobs:
    # build 是其中一个 job 的标识符，自己取的
    build:
        # 这个 job 的名字
        name: Hello world action
        runs-on: ubuntu-latest
        # 按顺序执行的步骤
        steps:
            # 使用了发布在社区的 action，名为 checkout
            # checkout: 将仓库代码复制到 virtual machine 中
            - uses: actions/checkout@v1
            # 使用定义在本仓库的名为 action-a 的 action
            - uses: ./action-a
            # 定义 bash 命令
            - run: echo hello
              # 用来定义输入变量
              # 这些变量在运行时可以从 action 文件中访问到
              with:
                  MY_NAME: 'suukii'
```

### 第六步：完成

现在我们往仓库里提交新代码时，push 事件触发，action-a 就会执行，可以在 GitHub 的 Actions tab 看到详细情况。

## 目录结构

```
│   LICENSE
│   README.md
│
├───.github
│   └───workflows
│           main.yml
│
└───action-a
        action.yml
        Dockerfile
        entrypoint.sh
```
