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 ...
- What to do - About GitHub Actions - Choices - Docker Container Action Configuration - Try to make it
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.

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.
& mdash; Tomorrow: ☀/☀/☀/☀/☀/☀/☁/☁ (@ egpl0) December 21, 2020
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].
There are three ways to create Actions. (Described in actions.yml)
action.yml
runs:
  using: 'docker'
  image: 'Dockerfile'
action.yml
runs:
  using: 'node12'
  main: 'hogehoge.js'
action.yml
runs:
  using: 'composite'
This time, we will create a Docker Container action.
You only have to write three parts roughly,
ENTRYPOINT
-** Program that performs the actual processing **
--This time written in PythonIs described.
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.
--Required arguments
open_weather_api_token
--Openweathermap API tokentwitter_consumer_key, twitter_consumer_secret, twitter_access_key, twitter_access_secret
-Twitter API tokenlocation_query
--Weather forecast location
--Optional argument descriptiontime_zone
--Time zone of forecast to be used
--By default, use the time zone of the location of location_queryname_format
--Format to fit the weather forecasticon_sep
--Parameters that separate the weatherforecast_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 1runs
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.
icon
-Corresponds to Feathercolor
--You can choose from white, yellow, blue, green, orange, red, purple, gray-dark.yaml:action:yml
icon: "link"
color: "green"
Then

It looks like.
Below is created 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"]
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.
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).

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.

Click

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

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,

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.

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!
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.

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