[PYTHON] GitHub Actions Introduction to self-made actions

This article is the 20th day of klis Advent Calendar 2020 ~~ 21 ~~. Continuing from Last year, this year's article will have a thin klis element ...

table of contents

- What to do - About GitHub Actions - Choices - Docker Container Action Configuration - Try to make it

What to do

Repository: ** eggplants/twitter-weathername-action **

I will explain the procedure to create an action that runs on GitHub Actions based on Python + Docker and publish it to Marketplace on GitHub. As an example, we will create a Twitter screen name of ** tomorrow's 3-hour weather forecast **, as shown in the picture below.

image.png

Also, I will try a regular execution cron on GitHub Actions that is completely free and without a server, which is ** updated automatically every day at JST 00:00 ** like running on your own server or VPS. ~~ However, it is necessary to create a repository to run ... ~~

The Workflow using the action created this time is here, and the one that published the action on the Marketplace is here.

About GitHub Actions

GitHub Actions is a CI/CD service provided by GitHub. You can write yaml in the .github/workflows directory of the repository and run it with a push, pull request, or a trigger such as a schedule that runs regularly. Also, if it is a public repository, it is attractive that you can rotate it for ** completely free **. If you use a certain amount in a private repository or organization repository, you will be charged [https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions#about-billing-for-github-actions].

Choices

There are three ways to create Actions. (Described in actions.yml)

-Docker Container Action

action.yml


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

-Javascript Action

action.yml


runs:
  using: 'node12'
  main: 'hogehoge.js'

-Composite execution action

action.yml


runs:
  using: 'composite'

This time, we will create a Docker Container action.

Docker Container Action Configuration

You only have to write three parts roughly,

Is described.

Try to make

actions.yml

List the values ​​to be described for each.

name, author, description

These are the "action name", "author", and "action description" when the action is published.

inputs

It is an "argument definition" that can be passed when executing an action.

Actions can receive the arguments passed in jobs. <Job_id> .steps.with when used in workflow. As we will see later, the passed argument XXX is defined as the environment variable INPUT_XXX and can be referenced within the ENTRYPOINT. If you set required: true, you cannot execute it unless you specify it at the time of use. Also, in the case of required: false (optional argument), you can define the default value of the argument with default.

Arguments defined this time

--Required arguments

  • open_weather_api_token --Openweathermap API token
  • twitter_consumer_key, twitter_consumer_secret, twitter_access_key, twitter_access_secret -Twitter API token
  • location_query --Weather forecast location --Optional argument description
  • time_zone --Time zone of forecast to be used --By default, use the time zone of the location of location_query
  • name_format --Format to fit the weather forecast
  • icon_sep --Parameters that separate the weather
  • forecast_day --Set the number of days to forecast in n days ahead --Specified by 0 ~ 2 for the convenience of the weather API -"Tomorrow" is 1

runs

This time it's a Docker Container action, so

action.yml


runs:
  using: "docker"
  image: "Dockerfile"

will do. This time, I specified the Dockerfile I created for image, but I can also specify the public Docker image of DockerHub and Public container of GitHub Packages.

branding

You can specify the icon and its background color when it is published in Marketplace.

yaml:action:yml


icon: "link"
color: "green"

Then

image.png

It looks like.

Below is created actions.yml.

actions.yml

action.yml


name: "Twitter Weathername"
author: "haruna"
description: "Update Twit description ter Username to a daily forecast of given location"
inputs:
  open_weather_api_token:
    description: "Openweathermap API Token"
    required: true
  twitter_consumer_key:
    description: "Twitter API consumer key"
    required: true
  twitter_consumer_secret:
    description: "Twitter API consumer secret key"
    required: true
  twitter_access_key:
    description: "Twitter API access key"
    required: true
  twitter_access_secret:
    description: "Twitter API access secret key"
    required: true
  location_query:
    description: "City name, state code and country code divided by comma, use ISO 3166 country codes"
    required: true
  time_zone:
    description: "Time zone to be used as a time reference (ex. Asia/Tokyo) (def: LOCATION_QUERY's local time zone)"
    required: false
  name_format:
    description: "Username format ({} is substituted by joined weather icons with icon_sep)"
    required: false
    default: "<{}"
  icon_sep:
    description: "String for joining icons"
    required: false
    default: ":"
  forecast_day:
    description: "Show the weather in the next n days (n=0 is today)"
    required: false
    default: "0"
runs:
  using: "docker"
  image: "Dockerfile"
branding:
  icon: "link"
  color: "green"

Dockerfile

Since Python will be executed this time, write a Dockerfile that creates an execution environment for running Python. Also, specify the program that receives the argument and performs the actual processing (here, the Twitter user name is updated to the obtained weather forecast) in ENTRYPOINT. You can also specify it as CMD ["python "," /src/main.py "].

Below is the created Dockerfile.

Dockerfile


FROM python:latest

ADD src /src
ADD requirements.txt /requirements.txt

RUN pip install -r requirements.txt
RUN chmod +x src/main.py

ENTRYPOINT ["/src/main.py"]

Program that does the actual processing

The arguments passed in workflow (eg XXX) are

/src/main.py


from os import environ

xxx = environ.get('INPUT_XXX', 'default')

You can receive it like this.

This time,

① Get weather.json for 3 days from Openweathermap API ② 3 days weather .json is shaped as a name ③ Update the name from Twitter API

Write a program to do. The created program is here.

Test the action you created

You can test with GitHub Actions whether the actions created so far work properly. Let's test if it works before publishing it on the Marketplace.

Also, strings that you do not want to be open to the public, such as API tokens, can be added from the repository [Settings]-> [Secrets]-> [New repository secret] and called with $ {{secrets.XXX}}. I will.

The workflow that runs every push in the repository and tries to update successfully is like this.

yml:.github/workflows/test.yml


name: Test
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Change Name
        uses: eggplants/twitter-weathername-action@main #Action repository
        with:
          open_weather_api_token: ${{ secrets.OPEN_WEATHER_API_TOKEN }}
          twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_KEY }}
          twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          twitter_access_key: ${{ secrets.TWITTER_ACCESS_KEY }}
          twitter_access_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
          location_query: tsukuba
          name_format: "tomorrow: {}"
          icon_sep: "/"
          forecast_day: 1 #Tomorrow's weather

You can check if it worked or not from the Actions tab (https://github.com/eggplants/twitter-weathername-action/actions?query=workflow%3ATest).

image.png

Publish to Marketplace

By publishing the created action to the Marketplace, anyone can easily use the created action immediately.

The detailed procedure is easy to understand in Official Document.

If action.yml exists in the repository, the[Draft a release]banner will appear in the repository.

image.png

Click

image.png

When you click the accept the GitHub Marketplace Developer Agreement link,

image.png

You will be asked to agree to the GitHub Marketplace Developer Agreement (https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-marketplace-developer-agreement).

If you agree,

image.png

It will check if the actions.yml metadata is sufficient and if there is a README, and will ask you to fix it if it is inadequate.

image.png

You can publish by setting the category and pressing the [Publish release] button (which is Update release in the image ...). Thank you for your hard work!

Periodically execute the published action and try using it

As I wrote at the beginning, there is a schedule trigger that can be executed periodically like cron in the execution trigger of workflow of Actions.

cron_renamer.yml


on:
  schedule:
    - cron: "0 15 * * *" #In JST"0 0 * * *"

You can run it regularly with just the cron syntax. Please note that the Actions workflow is executed in ** UTC ** (Coordinated Universal Time), so if you want to execute it in accordance with Japan time, ** JST ** (Japan Standard Time) **-9 Let's specify the time of **.

Below is the current actually used cron workflow.

cron_renamer.yml


name: Cron renamer

on:
  schedule:
    - cron: "0 15 * * *"

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Change Name
        uses: eggplants/twitter-weathername-action@v2
        with:
          open_weather_api_token: ${{ secrets.OPEN_WEATHER_API_TOKEN }}
          twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_KEY }}
          twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_SECRET }}
          twitter_access_key: ${{ secrets.TWITTER_ACCESS_KEY }}
          twitter_access_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
          location_query: tsukuba
          name_format: "tomorrow: {}"
          icon_sep: "/"
          forecast_day: 1

You can check the execution log from the Actions tab as well as the test.

image.png

in conclusion

I didn't have an easy-to-understand article that describes the procedure for creating and testing, publishing, and regularly executing GitHub Actions' own actions, so I always thought about writing it as a memorandum, but this time the Advent calendar was a good opportunity. I did.

Wish you a good year~

Recommended Posts

GitHub Actions Introduction to self-made actions
Introduction to Ruby processing system self-made
Introduction to Ruby 2
Introduction to SWING
Introduction to web3j
Introduction to Micronaut 1 ~ Introduction ~
[Java] Introduction to Java
Introduction to migration
Introduction to java
Introduction to Doma
Introduction to JAR files
Introduction to Ratpack (8)-Session
Introduction to RSpec 1. Test, RSpec
Introduction to bit operation
Introduction to Ratpack (6) --Promise
Introduction to Ratpack (9) --Thymeleaf
Introduction to PlayFramework 2.7 ① Overview
Introduction to Android Layout
Introduction to design patterns (introduction)
Introduction to Practical Programming
Introduction to javadoc command
Introduction to jar command
Introduction to Ratpack (2)-Architecture
Try actions on GitHub [actions]
Introduction to lambda expression
Introduction to java command
Introduction to RSpec 2. RSpec setup
Introduction to Keycloak development
Introduction to javac command
Github Actions to get Rails code reviewed reasonably automatically
Push Docker images from GitHub Actions to GitHub Container Registry
Introduction to Design Patterns (Builder)
Introduction to RSpec 5. Controller specs
Introduction to Android application development
Introduction to RSpec 3. Model specs
Introduction to Ratpack (5) --Json & Registry
Introduction to Metabase ~ Environment Construction ~
(Dot installation) Introduction to Java8_Impression
Introduction to Design Patterns (Composite)
Introduction to Micronaut 2 ~ Unit test ~
Introduction to JUnit (study memo)
Introduction to Spring Boot ① ~ DI ~
Introduction to design patterns (Flyweight)
[Java] Introduction to lambda expressions
Introduction to Spring Boot ② ~ AOP ~
Introduction to Apache Beam (2) ~ ParDo ~
[Ruby] Introduction to Ruby Error statement
Introduction to EHRbase 2-REST API
Until you push to Github
[Java] Introduction to Stream API
Introduction to Design Patterns (Iterator)
Introduction to Spring Boot Part 1
Introduction to Ratpack (1) --What is Ratpack?
XVim2 introduction memo to Xcode12.3
Response to Github vulnerability alerts
Introduction to RSpec-Everyday Rails Summary-
Introduction to Design Patterns (Strategy)
[Introduction to rock-paper-scissors games] Java
Minimal Workflow to push Docker image to Github Container Registry with Github Actions
Introduction to Linux Container / Docker (Part 1)
How to push from Tarminal to GitHub