githubs actions

148 阅读4分钟
# 1,触发条件
```yaml
on:
  push:
    branches:
      - master

1.1,触发器

名称types备注
push fork
pull_requestopened、edited、closed提交合并请求
create delete创建或删除分支和tag
schedule定时启动(延迟较大)
workflow_dispatch手动(选择分支)触发,只能在默认分支上发布
repository_dispatch通过web api触发
workflow_runcompleted、requested在另一个workflow变化时
issuesopened等

1.2,筛选器

名称备注
typescreated等
workflows-workflow name
branches-master -releases/**
tags-v1 -v2/*
branches-ignore-master -releases/**
tags-ignore-v1 -v2/*
paths-**.js
paths-ignore-**.js
cronm h d m w通用cron
github的cron

1.3,使用实例

1.3.1,types

on:
  pull_request:
    types:
      - opened
      - edited

1.3.2,branches与branches-ignore/tags与tags-ignore(branches与branches-ignore不能同时出现在一个触发事件中,tags与tags-ignore一样)

on:
  push:
    branches:
      - 'release/**'
      - '!release/beta'
    tags:
      - 'v1'
  pull_request:
    branches-ignore:
      - master
    tags-ignore:
      - 'v1'

1.3.3,paths与paths-ignore

on:
  push:
    paths:
      - '**.js'  # 当推送中含有js文件时触发

1.3.4,cron

on:
  schedule:
    cron:
      - '30 5,17 * * 1,3' # 在周一和周三的5:30与17:30执行

1.3.5,workflow_run

被触发的工作流:workflow_run1.yaml (必须放在默认分支上)

name: test push2 when call2
on:
  workflow_run:
    workflows:
      - workFlows_name
    types:
      - completed
    branches:
      - barnch_filter # 指定的是触发器必须在哪个分支上
jobs:
  job1:
    steps:
      - run: echo something

起触发作用的工作流:main.yaml (可以放在任何分支上)

name: workFlows_name # 用于被监听的name

1.3.6,repository_dispatch (必须放在默认分支上)

on:
  repository_dispatch:
    types:
      - TRIGGER_KEYWORDS # 调用api时传入的 event_type 参数
jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      - run: echo success

触发:

curl -X POST https://api.github.com/:owner/:repo/test-github-actions/dispatches \
    -H "Accept: application/vnd.github.everest-preview+json" \
    -H "Authorization: token GITHUB_TOKEN" \
    --data '{"event_type": "TRIGGER_KEYWORDS"}'

2,复用action

2.1,local actions(只能在job中使用)(相当于扩展jobs)

reusable-workflow.yaml

on: workflow_call
jobs:
  job1: # 内部的job和step的id不会影响到main.yaml
    steps: run: echo 1

main.yaml

on:
  push
jobs:
  job2: # 两种引用方式,第二种可以引用其他项目的action(只能在job中使用)
    uses: ./.github/workflows/reusable-workflow.yaml
    uses: github_user_name/repository_name/.github/workflows/reusable-workflow.yaml@branch_name|tag|SHA
    with:
      inputVar1: inputVal1 # 这里传入的变量必须在原yaml中声明

2.2,编写action npm包(只能在step中使用)(相当于扩展jobs)

2.2.1,文件目录

image.png

2.2.2,action.yaml

name: action name
description: action description

runs:
  using: node12 # node12或node 16
  main: dist/index.js
  pre: setup.js
  post: cleanup.js
  pre-if: runner.os == 'linux'
  post-if: runner.os == 'linux'

2.2.3,使用

workflow/test.yaml

name: test push when call
on:
  push
jobs:
  job1:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v3 # action包在本项目时必须先checkout才能拿到项目里的action
      - uses: ./.github/myaction # 只能在step中使用
      
      - uses: github_user_name/repository_name/.github/myaction@branch_name|tag|SHA # 直接使用url就不需要checkout了,而且是最新的action

2.2.4,composite action

action.yaml

runs:
  using: composite
  steps:
      shell: sh # 每一步都需要写shell
    - run: echo "::set-output name=outputVar1::val"
      shell: sh
    - run: echo ${{github.action_path}}
      shell: sh

3,输入输出

3.1,手动触发工作流(workflow_dispatch)的输入

on:
  workflow_dispatch:
    inputs:
      inputVar1:
        description: string
        require: true # 输入参数的时候会提示,无默认值时会校验
        default: string
        type: choice | boolean | string
        options:
          - chioice-1

3.2,同一个workflow中的输入输出

jobs:
  job1: # 如果需要与其他job共享数据,则需要把step的输出提升到job的输出
    outputs:
      job1Var1: ${{steps.step1.outputs.step1Var1}}
    runs-on: ubuntu-18.04
    steps:
      - id: step1
        run: echo "::set-output name=step1Var1::val"
      - run: echo ${{steps.step1.outputs.step1Var1}} # step间的输入输出
  job2:
    runs-on: ubuntu-18.04
    needs:
      - job1 # 需要声明依赖的job
    steps:
      - run: echo ${{needs.job1.outputs.job1Var1}} # job间的输入输出

3.3,Local Action 间的输入输出

reusable-workflow.yaml

on:
  workflow_call:
    inputs:
      inputVar1:
        description: string
        default: string
        type: string # 字段必须
    outputs:
      outputVar1:
        description: string
        value: ${{jobs.job1.outputs.jobVar1}} # 必须将输出浮到job层,并在这里声明
jobs:
  job1:
    outputs:
      jobVar1: ${{steps.step1.outputs.stepVar1}}
    steps:
      - id: step1
        run: echo "::set-output name=stepVar1::val1"

使用:main.yaml

on:
  push
jobs:
  job2: # 两种引用方式,第二种可以引用其他项目的action(只能在job中使用)
    uses: ./.github/workflows/reusable-workflow.yaml
    with:
      inputVar1: inputVal1 # 这里传入的变量必须在原yaml中声明
  job3:
    needs:
      - job2 # 用新的job name
    steps:
      - run: echo ${{needs.job2.outputs.outputVar1}}

3.4 npm包

3.4.1 声明输入输出

action.yaml

# inputs和outputs中,只有inputs的default会对action对应的程序产生影响,其他的内容都是提示性质的,可有可无
inputs:
  inputVar1:
    description: string
    required: false # 设置为true也不会引起校验
    default: default_val
outputs: # 执行程序为js时这里的output声明只有提示效果
  outputVar1:
    description: string

3.4.2,javascript 中获取输入输出、github上下文及设置输出

github action工具包地址 github.com/actions/too…

const core = require('@actions/core');
const github = require('@actions/github');

// 设置输出
core.setOutput('outputVar1', '');
// 获取上下文
console.log(JSON.stringify(github.context.payload, undefined, 2));
// 获取输入
console.log(core.getInput('inputVar1')); // 原理:从process.env[INPUT_$name]上获取

3.4.3,composite action获取输入和设置输出

action.yaml

outputs:
  outputVar1:
    description: string
    # 从step的结果中获取
    value: ${{steps.outputVar1-generator.outputs.outputVar1}}
runs:
  using: composite
  steps:
    - run: echo ${{inputs.inputVar1}}
      shell: sh # 每一步都需要写shell
    - id: outputVar1-generator
      run: echo "::set-output name=outputVar1::val"
      shell: sh
    - run: echo ${{github.action_path}}
      shell: sh

3.4.4,使用

main.yaml

jobs:
  job1:
    steps:
      - uses: actions/checkout@v3
      - uses: ./.github/myaction
        id: my_action # 如果需要获取输出需要重新设置id
        with:
          inputVar1: string # 设置输入
      - run: echo ${{steps.my_action.outputs.outputVar1}} # 获取输出

4,Cache(7天内未被访问的缓存会被删除,缓存总大小限制为10GB,超过会以旧换新)

job1:
  steps:
    - uses: actions/cache@v3
      id: cache-dir
      with:
        path: |
          dirPath1
          dirPath2/*/fileName
        key: key1-suffix-${{hashFiles('package.json')}}
    # 判断是否命中缓存
    - if: ${{steps.cache-dir.outputs.cache-hit != 'true'}}
      run: echo failed
    - run: echo "new content" > dirPath1/newFile # 新加入的文件也会进入cache,因为是在job结束前才存缓存
job2:
  needs: job1
  steps:
    - uses: actions/cache@v3
      with: # path的值必须完全相同,不然不会命中
        path: |
          dirPath1
          dirPath2/*/fileName
        key: key1 # 这里的匹配是只要由key1开头都会匹配到
        restore-keys: |
          key2 # 备用的还原键;当key匹配失败后会用下面的key继续匹配

5,Artifact

jobs:
  job1:
    steps:
      - run: echo "new content" > dirOrFilePath/new-file
      - uses: actions/upload-artifact@v3
        with:
          name: artifactName
          path: dirOrFilePath # 如果是目录,则只会上传目录里的文件,在下载时不会再有这个目录包裹
          if-no-files-found: warn | error | ignore # 当文件不存在时,报警告|让step失败|忽略
  job2:
    needs: job1
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: artifactName
          path: newFolderToSaveArtifact # (可选);这个时候的文件路径为 newFolderToSaveArtifact/new-file

6,矩阵

jobs:
  job1:
    strategy:
      fail-fast: true # 只要矩阵中有一个作业失败,则矩阵中其他所有作业取消
      max-parallel: 6 # 最大并行仍无
      matrix:
        node-version: # 单维矩阵会并行执行n次,多维会并行执行n*m次
          - 12
          - 14
    steps:
      - uses: actions/setup-node@v3
        with:
          node-version: ${{matrix.node-version}} # 从上下文获取参数
      - run: node -v

7,函数

job1:
  if: ${{contains('hello world', 'llo')}}
  if: ${{startsWith('hello world', 'llo')}}
  if: ${{endsWith('hello world', 'llo')}}
  steps:
    - run: echo ${{format('Hello {0} {1} {2}', 'Mona', 'the', 'Octocat')}}
    - run: echo ${{join(array, optionalSeparator || ',')}}
    - run: echo "${{toJSON(github)}}"
    - run: echo ${{fromJSON('["push", "pull_request"]')[0]}}
    - run: echo ${{fromJSON('{"push":"pull_request"}')['push']}}
    - run: echo ${{hashFiles('package.json', 'index.js'...)}}

7.1,状态检测

steps:
  - if: ${{ success() }}
  - if: ${{ always() }}
  - if: ${{ cancelled() }}
  - if: ${{ failure() }}

8,使用镜像作为runner

jobs:
  job1:
    runs-on: ubuntu-latest
    container:
      image: dockerhub_username/image:tag
      volumes:
        - source:/destinationPath
      credentials: # 私有镜像需要验证
        username: string
        password: string