DEV Community

Cover image for Como criar uma GitHub Action para importar posts do DEV.to em PHP com o Minicli - Vídeo + Tutorial
Erika Heidi
Erika Heidi

Posted on

Como criar uma GitHub Action para importar posts do DEV.to em PHP com o Minicli - Vídeo + Tutorial

GitHub Actions é uma funcionalidade oferecida pelo GitHub que permite a execução de processos automatizados que podem ser engatilhados por eventos tais como pull requests, pushs, novos comentários, mas também podem rodar em agendamento similar ao crontab. Actions podem ser combinadas para a criação de workflows automatizados diversos, que podem ser usados para CI/CD e também para outras finalidades.

Repositórios open source tem acesso ilimitado a esse recurso, fazendo dessa funcionalidade uma ótima ferramenta para execução de tarefas agendadas, pequenos workers e bots.

Esse post reúne os vídeos que produzi mostrando como criar uma GitHub Action em PHP com o Minicli, um microframework PHP para a linha de comando. O primeiro vídeo traz uma introdução rápida sobre o Minicli, útil para fornecer um contexto antes de iniciarmos o desenvolvimento da aplicação. No segundo vídeo, vemos como criar a aplicação que irá importar os posts do DEV.to e salvá-los como arquivos markdown. No terceiro e último vídeo, vemos como adaptar a aplicação para ser usada como GitHub Action.

Logo abaixo dos vídeos você encontra os comandos e arquivos necessários para reproduzir o tutorial.

Prerequisitos para seguir o tutorial

Para executar os passos desse tutorial, você precisará de:

  • Um ambiente de desenvolvimento PHP-cli 8.0+, com a extensão php-curl instalada.
  • Composer instalado.

Introdução ao Minicli (Opcional)

Nesse vídeo curto, mostro uma visão geral sobre o Minicli e como fazer o bootstrap de uma nova aplicação usando esse framework.

Criando uma aplicação Minicli para importar posts do DEV.to

Nesse vídeo, criamos uma aplicação Minicli do zero e desenvolvemos um comando para importar posts de um usuário ou org do DEV.to, usando a API fornecida por essa plataforma de conteúdo.

Bootstrap da aplicação

Você pode criar uma nova aplicação Minicli com o seguinte comando:

composer create-project minicli/application importDevTo
Enter fullscreen mode Exit fullscreen mode

Adicionando dependência minicli/curly

Vamos usar o pacote minicli/curly para fazer requisições à API do DEV.to:

composer require minicli/curly
Enter fullscreen mode Exit fullscreen mode

Criando um novo comando

Para criar um novo comando que será chamado com minicli import dev, você precisará seguir a convenção estabelecida pelo Minicli: app/Command/CommandNamespace/SubcommandController.php.

mkdir app/Command/Import
touch app/Command/Import/DevController.php
Enter fullscreen mode Exit fullscreen mode

Vamos precisar de alguns valores de configurações que poderão ser usados para customizar essa Action através de variáveis de ambiente. Abaixo, a versão mais atualizada do arquivo, já contendo alterações que serão trazidas no próximo vídeo:

<?php

return [
    'app_path' => __DIR__ . '/app/Command',
    'debug' => true,
    'devto_username' => getenv('DEVTO_USERNAME') ?: 'erikaheidi',
    'data_path' => getenv('APP_DATA_DIR') ?: __DIR__ . '/devto'
];
Enter fullscreen mode Exit fullscreen mode

Para usar esse config com a aplicação, você precisará editar o arquivo minicli na raiz da aplicação. Substitua a linha onde a aplicação é instanciada pela seguinte linha:

(...)
$app = new App(require __DIR__ .'/config.php');
(...)
Enter fullscreen mode Exit fullscreen mode

A versão mais atualizada do arquivo DevController.php, que contém o comando chamado por minicli import dev, está disponível abaixo. Note que essa versão não irá coincidir com a do vídeo pois contém algumas adaptações incluídas posteriormente para facilitar o uso prático dessa aplicação como GitHub Action.

<?php

namespace App\Command\Import;

use Minicli\Curly\Client;
use Minicli\Command\CommandController;

class DevController extends CommandController
{
    public string $API_URL = 'https://dev.to/api';

    public function handle(): void
    {
        $this->getPrinter()->display('Fetching posts from DEV...');
        $crawler = new Client();

        if (!$this->getApp()->config->devto_username) {
            throw new \Exception('You must set up your devto_username config.');
        }

        $devto_username = $this->getApp()->config->devto_username;

        $articles_response = $crawler->get($this->API_URL . '/articles?username=' . $devto_username);

        if ($articles_response['code'] !== 200) {
            throw new \Exception('Error while contacting the dev.to API.');
        }

        if (!$this->getApp()->config->data_path) {
            throw new \Exception('You must define your data_path config value.');
        }

        $data_path = $this->getApp()->config->data_path;

        if (!is_dir($data_path) && !mkdir($data_path)) {
            throw new \Exception('You must define your data_path config value.');
        }

        $articles = json_decode($articles_response['body'], true);
        foreach($articles as $article) {
            $get_article = $crawler->get($this->API_URL . '/articles/' . $article['id']);

            if ($get_article['code'] !== 200) {
                $this->getPrinter()->error('Error while contacting the dev.to API.');
                continue;
            }

            $article_content = json_decode($get_article['body'], true);
            $date = new \DateTime($article_content['published_at']);
            $filepath = $data_path . '/' . $date->format('Ymd') . '_' . $article_content['slug'] . '.md';
            $file = fopen($filepath, 'w+');
            fwrite($file, $article_content['body_markdown']);
            fclose($file);

            $this->getPrinter()->info("Saved article: " . $article_content['title'] . " to $filepath");
        }

        $this->getPrinter()->info("Finished importing.", true);
    }
}
Enter fullscreen mode Exit fullscreen mode

Convertendo a aplicação demo em GitHub Action

Nesse vídeo, partimos da aplicação desenvolvida no vídeo anterior, fazendo pequenas adaptações e criando os arquivos necessários para usar a aplicação como GitHub Action.

Criando um Dockerfile para a aplicação

O arquivo Dockerfile deve ser criado na raiz do repositório da sua GitHub Action. Ele será referenciado pelo arquivo action.yml que define o que essa Action irá executar.

FROM php:8.1-cli

RUN apt-get update && apt-get install -y \
    git \
    curl \
    libxml2-dev \
    zip \
    unzip

RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install Composer and set up application
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
RUN mkdir /application
COPY . /application/
RUN cd /application && composer install

ENTRYPOINT [ "php", "/application/minicli" ]
CMD ["import", "dev"]
Enter fullscreen mode Exit fullscreen mode

Criando um action.yml

O arquivo action.yml define os metadados da Action e deve ser comitado na raiz do repositório.

name: 'Import DEV.to posts'
description: 'Imports posts from DEV.to as markdown files'
outputs:
  response:
    description: 'Output from command'
runs:
  using: 'docker'
  image: 'Dockerfile'
Enter fullscreen mode Exit fullscreen mode

Montando um Workflow

O workflow deve ser criado no repositório onde você quer salvar os arquivos markdown. Esse arquivo pode ter qualquer nome desde que esteja dentro da pasta .github/workflows dentro do repositório.

O workflow abaixo irá criar um pull request sempre que houver uma diff entre a versão atual do repositório e o conteúdo importado pela Action. Ele utiliza três actions:

  • actions/checkout@v2
  • erikaheidi/importDevTo@v1.2
  • eter-evans/create-pull-request@v3
name: Import posts from DEV
on:
  schedule:
    - cron: "0 1 * * *"
  workflow_dispatch:
jobs:
  main:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: erikaheidi/importDevTo@v1.2
        name: "Import posts from DEV"
        env:
          DEVTO_USERNAME: erikaheidi
          APP_DATA_DIR: ${{ github.workspace }}/devto
      - name: Create a PR
        uses: peter-evans/create-pull-request@v3
        with:
          commit-message: Import posts from DEV
          title: "[automated] Import posts from DEV"
          token: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Testando workflow

Para testar o workflow, acesse o repositório e vá até a aba "Actions", selecione o workflow no sidebar da esquerda, e clique em "Run Workflow".

Após o workflow finalizar sua execução, você deverá ver um pull request aberto no repositório onde o workflow está definido (desde que haja posts que não foram importados já anteriormente).

pull request criado automaticamente por esse workflow

Conclusão

GitHub Actions é uma ferramenta poderosa e versátil oferecida pelo GitHub que nos permite executar workflows customizados que vão muito além de CI/CD. Nesse tutorial eu procurei passar um pouco mais de contexto para enriquecer os tutoriais em vídeo que compartilhei recentemente sobre o assunto.

Links Úteis:

Top comments (0)