Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducing GitHub Actions

Introducing GitHub Actions

8c3a2ebf7c2b84f8390d99c7bf8c8a48?s=128

Sobolev Nikita

October 30, 2019
Tweet

Transcript

  1. X Никита Соболев github.com/sobolevn

  2. >_ X Автоматизируем все с Github Actions 2

  3. Для кого мой доклад? 3

  4. Для кого мой доклад? > Для девелоперов 3

  5. Для кого мой доклад? > Для девелоперов > Для опсов

    3
  6. None
  7. У нас был целый склад велосипедов! 5

  8. У нас был целый склад велосипедов! > Свои боты в

    Gitlab CI 5
  9. У нас был целый склад велосипедов! > Свои боты в

    Gitlab CI > Свои боты в Heroku + Cron 5
  10. У нас был целый склад велосипедов! > Свои боты в

    Gitlab CI > Свои боты в Heroku + Cron > Свои боты, которые слушали вебхуки 5
  11. None
  12. В чем разница? 7

  13. Платформа и сообщество 8

  14. None
  15. None
  16. >_ X Платформа 11

  17. None
  18. Полностью бесплатно для публичных репозиториев

  19. Задача: прогоним линтер для Python проекта

  20. None
  21. None
  22. None
  23. None
  24. None
  25. None
  26. Готово!

  27. Термины

  28. Термины > Workflow

  29. Термины > Workflow > Job

  30. Термины > Workflow > Job > Step

  31. Термины > Workflow > Job > Step > Action

  32. Термины > Workflow > Job > Step > Action >

    Event
  33. None
  34. name: Python package on: [push] jobs: build: runs-on: ubuntu-latest strategy:

    max-parallel: 4 matrix: python-version: [2.7, 3.5, 3.6, 3.7] steps: # ...
  35. name: Python package on: [push] jobs: build: runs-on: ubuntu-latest strategy:

    max-parallel: 4 matrix: python-version: [2.7, 3.5, 3.6, 3.7] steps: # ...
  36. None
  37. name: Python package on: [push] jobs: build: runs-on: ubuntu-latest strategy:

    max-parallel: 4 matrix: python-version: [2.7, 3.5, 3.6, 3.7] steps: # ...
  38. name: Python package on: [push] jobs: build: runs-on: ubuntu-latest strategy:

    max-parallel: 4 matrix: python-version: [2.7, 3.5, 3.6, 3.7] steps: # ...
  39. None
  40. Подготовка

  41. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt
  42. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt
  43. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt
  44. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt matrix: python-version: [2.7, 3.5, 3.6, 3.7]
  45. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt
  46. name: Python package # ... steps: - uses: actions/checkout@v1 -

    name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -r requirements.txt
  47. Подготовились. Проверяем!

  48. name: Python package # ... steps: # ... - name:

    Lint with wemake-python-styleguide run: | pip install flake8 flake8 . - name: Test with pytest run: | pip install pytest pytest
  49. name: Python package # ... steps: # ... - name:

    Lint with wemake-python-styleguide run: | pip install flake8 flake8 . - name: Test with pytest run: | pip install pytest pytest
  50. None
  51. None
  52. None
  53. None
  54. Infrastructure as Code

  55. Infrastructure as Reusable Code

  56. >_ X Автоматизируем все с Github Actions 40

  57. Типы событий

  58. Типы событий > push, commit

  59. Типы событий > push, commit > issues, pull_request

  60. Типы событий > push, commit > issues, pull_request > issue_comment,

    label, gollum
  61. Типы событий > push, commit > issues, pull_request > issue_comment,

    label, gollum > member
  62. Типы событий > push, commit > issues, pull_request > issue_comment,

    label, gollum > member > schedule, webhook
  63. Можно еще глубже!

  64. on: pull_request - assigned - unassigned - labeled - unlabeled

    - opened - edited - closed - reopened - synchronize - ready_for_review - locked - unlocked - review_requested - review_request_removed
  65. >_ X Создай свое! 44

  66. Что потребуется?

  67. Что потребуется? > Dockerfile

  68. Что потребуется? > Dockerfile > action.yml

  69. Dockerfile

  70. FROM python:3.7-alpine RUN apk add --no-cache bash RUN pip install

    wemake-python-styleguide COPY entrypoint.sh / RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
  71. FROM python:3.7-alpine RUN apk add --no-cache bash RUN pip install

    wemake-python-styleguide COPY entrypoint.sh / RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
  72. FROM python:3.7-alpine RUN apk add --no-cache bash RUN pip install

    wemake-python-styleguide COPY entrypoint.sh / RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]
  73. #!/bin/bash # Runs flake8: output=$(flake8 "$1") status="$?" echo "::set-output name=output::$output"

    # Fail the build in case status code is not 0: if [[ "$status" != 0 ]]; then echo "$output" echo "Process failed with the status code: $status" exit "$status" fi
  74. #!/bin/bash # Runs flake8: output=$(flake8 "$1") status="$?" echo "::set-output name=output::$output"

    # Fail the build in case status code is not 0: if [[ "$status" != 0 ]]; then echo "$output" echo "Process failed with the status code: $status" exit "$status" fi
  75. #!/bin/bash # Runs flake8: output=$(flake8 "$1") status="$?" echo "::set-output name=output::$output"

    # Fail the build in case status code is not 0: if [[ "$status" != 0 ]]; then echo "$output" echo "Process failed with the status code: $status" exit "$status" fi
  76. None
  77. None
  78. jobs: steps: - name: lint uses: wemake-services/wemake-python-styleguide@latest with: path: src/

    - run: echo ${{ steps.outputs.lint.output }} > log.txt
  79. jobs: steps: - name: lint uses: wemake-services/wemake-python-styleguide@latest with: path: src/

    - run: echo ${{ steps.outputs.lint.output }} > log.txt
  80. jobs: steps: - name: lint uses: wemake-services/wemake-python-styleguide@latest with: path: src/

    - run: echo ${{ steps.outputs.lint.output }} > log.txt
  81. jobs: steps: - name: lint uses: wemake-services/wemake-python-styleguide@latest with: path: src/

    - run: echo ${{ steps.outputs.lint.output }} > log.txt
  82. jobs: steps: - name: lint uses: wemake-services/wemake-python-styleguide@latest with: path: src/

    - run: echo ${{ steps.outputs.lint.output }} > log.txt
  83. Да у нас же тут композиция!

  84. output@action1 |> input@action2

  85. action.yml

  86. name: 'wemake-python-styleguide' inputs: path: description: 'List of paths to lint'

    required: false default: '.' outputs: output: description: 'The output of a linter run' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.path }}
  87. name: 'wemake-python-styleguide' inputs: path: description: 'List of paths to lint'

    required: false default: '.' outputs: output: description: 'The output of a linter run' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.path }}
  88. name: 'wemake-python-styleguide' inputs: path: description: 'List of paths to lint'

    required: false default: '.' outputs: output: description: 'The output of a linter run' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.path }}
  89. name: 'wemake-python-styleguide' inputs: path: description: 'List of paths to lint'

    required: false default: '.' outputs: output: description: 'The output of a linter run' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.path }}
  90. >_ X Возьми фреймворк 66

  91. Готовые npm компоненты

  92. Готовые npm компоненты > @actions/core

  93. Готовые npm компоненты > @actions/core > @actions/exec

  94. Готовые npm компоненты > @actions/core > @actions/exec > @actions/io

  95. Готовые npm компоненты > @actions/core > @actions/exec > @actions/io >

    @actions/tool-cache
  96. Готовые npm компоненты > @actions/core > @actions/exec > @actions/io >

    @actions/tool-cache > @actions/github
  97. const github = require('@actions/github') const core = require('@actions/core') async function

    run() { const octokit = new github.GitHub(process.env.GITHUB_TOKEN) switch (github.context.eventName) { case 'issue_comment': checkIssueComment(github.context, async () => { await octokit.issues.updateComment({ ...github.context.repo, 'body': core.getInput('text'), }) }) break // ... } }
  98. const github = require('@actions/github') const core = require('@actions/core') async function

    run() { const octokit = new github.GitHub(process.env.GITHUB_TOKEN) switch (github.context.eventName) { case 'issue_comment': checkIssueComment(github.context, async () => { await octokit.issues.updateComment({ ...github.context.repo, 'body': core.getInput('text'), }) }) break // ... } }
  99. const github = require('@actions/github') const core = require('@actions/core') async function

    run() { const octokit = new github.GitHub(process.env.GITHUB_TOKEN) switch (github.context.eventName) { case 'issue_comment': checkIssueComment(github.context, async () => { await octokit.issues.updateComment({ ...github.context.repo, 'body': core.getInput('text'), }) }) break // ... } }
  100. name: comments on: issues: types: [opened, edited] issue_comment: types: [created,

    edited] pull_request: types: [created, edited] jobs: comments: runs-on: ubuntu-latest steps: - uses: sobolevn/restrict-cursing-action@latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  101. name: comments on: issues: types: [opened, edited] issue_comment: types: [created,

    edited] pull_request: types: [created, edited] jobs: comments: runs-on: ubuntu-latest steps: - uses: sobolevn/restrict-cursing-action@latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  102. name: comments on: issues: types: [opened, edited] issue_comment: types: [created,

    edited] pull_request: types: [created, edited] jobs: comments: runs-on: ubuntu-latest steps: - uses: sobolevn/restrict-cursing-action@latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  103. None
  104. https://github.com/ sobolevn/restrict- cursing-action

  105. >_ X Используй готовое! 76

  106. Github Actions vs Github Apps

  107. None
  108. None
  109. None
  110. None
  111. Работает с любым языком и линтером

  112. $ flake8 . | reviewdog -f=pep8

  113. $ your-linter . | reviewdog -efm="%f:%l:%c: %m"

  114. InfoSec

  115. InfoSec > Python: wemake-python-styleguide, bandit, dlint

  116. InfoSec > Python: wemake-python-styleguide, bandit, dlint > JS: eslint-plugin-security

  117. InfoSec > Python: wemake-python-styleguide, bandit, dlint > JS: eslint-plugin-security >

    Elixir: sobelow
  118. !85

  119. None
  120. None
  121. None
  122. None
  123. None
  124. None
  125. None
  126. Упади, все плохо import { danger, fail } from 'danger'

    if (danger.github.pr.base.ref !== 'master') { fail('We only accept PRs to `master` branch.') } if (!danger.github.pr.rebaseable) { fail('Looks like your PR cannot be merged, please fix it: reopen or rebase.') }
  127. Не падай, но скажи import { danger, warn } from

    'danger' if (danger.github.pr.body.length < 50) { warn('Please provide a summary, at least 50 chars') } if (!danger.github.pr.body.match(/closes #\d+/i)) { warn('MR does not close any issues. Should close one') }
  128. Полезности

  129. Полезности > Проверять, что не утекли пароли: npmjs.com/package/detect-secrets

  130. Полезности > Проверять, что не утекли пароли: npmjs.com/package/detect-secrets > Валидировать

    конфиги: yaml, json
  131. Полезности > Проверять, что не утекли пароли: npmjs.com/package/detect-secrets > Валидировать

    конфиги: yaml, json > Проверять повторяющиеся действия
  132. None
  133. !95

  134. Автоматически обновляет пакеты с уязвимостями

  135. None
  136. None
  137. None
  138. None
  139. None
  140. None
  141. И вообще любые пакеты!

  142. Алгоритм

  143. Алгоритм > Бот читает список ваших зависимостей

  144. Алгоритм > Бот читает список ваших зависимостей > Смотрит на

    наличие обновлений по заданным правилам
  145. Алгоритм > Бот читает список ваших зависимостей > Смотрит на

    наличие обновлений по заданным правилам > Делает много PR с изменениями одной зависимости
  146. Алгоритм > Бот читает список ваших зависимостей > Смотрит на

    наличие обновлений по заданным правилам > Делает много PR с изменениями одной зависимости > Ждет прогона CI
  147. Алгоритм > Бот читает список ваших зависимостей > Смотрит на

    наличие обновлений по заданным правилам > Делает много PR с изменениями одной зависимости > Ждет прогона CI > Готово!
  148. None
  149. None
  150. None
  151. None
  152. None
  153. semantic-release

  154. Валидируем коммиты

  155. /^(revert: )?(feat|fix|docs|chore)(\(.+\))?:.{1,50}refs #\d+/

  156. None
  157. None
  158. Релизим правильно!

  159. const releasePipeline = { 'plugins': [ '@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/changelog', ['@semantic-release/git',

    { 'assets': ['CHANGELOG.md'], }], ['@semantic-release/github', { assets }], ] }
  160. None
  161. None
  162. steps: - uses: actions/checkout@master - uses: codfish/semantic-release-action@master id: semantic env:

    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: echo "${{ steps.semantic.outputs.release-version }}"
  163. steps: - uses: actions/checkout@master - uses: codfish/semantic-release-action@master id: semantic env:

    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: echo "${{ steps.semantic.outputs.release-version }}"
  164. steps: - uses: actions/checkout@master - uses: codfish/semantic-release-action@master id: semantic env:

    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: echo "${{ steps.semantic.outputs.release-version }}"
  165. GITHUB_TOKEN

  166. NPM_TOKEN

  167. None
  168. None
  169. None
  170. None
  171. None
  172. None
  173. Умные комментарии

  174. /rebase

  175. None
  176. None
  177. None
  178. None
  179. /revert

  180. None
  181. None
  182. None
  183. None
  184. Любые ваши!

  185. Деплой

  186. Готовые провайдеры

  187. Готовые провайдеры > AWS, Azure

  188. Готовые провайдеры > AWS, Azure > Zeit / Now, Heroku

  189. Готовые провайдеры > AWS, Azure > Zeit / Now, Heroku

    > K8S, DockerSwarm, Dokku
  190. Готовые провайдеры > AWS, Azure > Zeit / Now, Heroku

    > K8S, DockerSwarm, Dokku > Ansible, Chef, Terraform
  191. Готовые провайдеры > AWS, Azure > Zeit / Now, Heroku

    > K8S, DockerSwarm, Dokku > Ansible, Chef, Terraform > rsync
  192. Готовые провайдеры > AWS, Azure > Zeit / Now, Heroku

    > K8S, DockerSwarm, Dokku > Ansible, Chef, Terraform > rsync > Docker registry
  193. И вспомогательные средства

  194. Пример с Docker

  195. None
  196. None
  197. None
  198. on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@master

    - name: Publish to Registry uses: elgohr/Publish-Docker-Github-Action@master with: name: myDocker/repository username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} registry: my.custom-registry.com
  199. on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@master

    - name: Publish to Registry uses: elgohr/Publish-Docker-Github-Action@master with: name: myDocker/repository username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} registry: my.custom-registry.com
  200. Наша инфраструктура

  201. None
  202. None
  203. None
  204. None
  205. None
  206. None
  207. None
  208. None
  209. Можно триггерить другие CI

  210. Какие? > Gitlab CI > Azure > Travis > Drone

    > Circle
  211. Пример с Terraform

  212. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/deploy
  213. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/deploy
  214. None
  215. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/deploy
  216. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/deploy
  217. None
  218. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/deploy
  219. None
  220. name: terraform on: pull_request jobs: terraform: runs-on: ubuntu-latest steps: -

    uses: hashicorp/terraform-github-actions/fmt - uses: hashicorp/terraform-github-actions/init - uses: hashicorp/terraform-github-actions/validate - uses: hashicorp/terraform-github-actions/plan - uses: hashicorp/terraform-github-actions/apply
  221. None
  222. https://github.com/ hashicorp/terraform- github-actions

  223. Управление разработчиками

  224. И многое другое!

  225. >_ X Автоматизировать - просто!

  226. Бета!

  227. None
  228. 13 Ноября

  229. Проблемы

  230. Проблемы > Пока не работает кеш для зависимостей

  231. Проблемы > Пока не работает кеш для зависимостей > Проблемы

    с origin / fork
  232. Проблемы > Пока не работает кеш для зависимостей > Проблемы

    с origin / fork > Относительно мало готовых компонентов
  233. Проблемы > Пока не работает кеш для зависимостей > Проблемы

    с origin / fork > Относительно мало готовых компонентов > Не у всех есть доступ (до 13.11)
  234. Проблемы > Пока не работает кеш для зависимостей > Проблемы

    с origin / fork > Относительно мало готовых компонентов > Не у всех есть доступ (до 13.11) > Тесты за вас никто не напишет!
  235. Полезные ссылки > https://help.github.com/en/ articles/about-github-actions > https://help.github.com/en/ articles/events-that-trigger- workflows >

    https://github.com/sdras/awesome- actions
  236. Специально для конференции > https://github.com/sobolevn/ restrict-cursing-action > https://github.com/wemake- services/wemake-python-styleguide

  237. GitHub Actions + Jenkins

  238. Вопросы? github.com/sobolevn sobolevn.me