Operador para ajudar no desenvolvimento de tasks

0.4.4 2024-01-16 03:12 UTC

README

[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/sierratecnologia/operador/badges/quality-soperador.png?b=master)](https://scrutinizer-ci.com/g/sierratecnologia/operador/?branch=master)[![Code Coverage](https://scrutinizer-ci.com/g/sierratecnologia/operador/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/sierratecnologia/operador/?branch=master)[![Latest Stable Version](https://poser.pugx.org/sierratecnologia/operador/v/stable.png)](https://packagist.org/packages/sierratecnologia/operador) [![Total Downloads](https://poser.pugx.org/sierratecnologia/operador/downloads.png)](https://packagist.org/packages/sierratecnologia/operador) [![Latest Unstable Version](https://poser.pugx.org/sierratecnologia/operador/v/unstable.png)](https://packagist.org/packages/sierratecnologia/operador) [![License](https://poser.pugx.org/sierratecnologia/operador/license.png)](https://packagist.org/packages/sierratecnologia/operador)

Índice

Introdução

O que é o Operador?

Operador é uma biblioteca Laravel robusta e extensível desenvolvida pela SierraTecnologia para auxiliar no desenvolvimento, orquestração e execução de tarefas automatizadas, actions e processos em batch. A biblioteca oferece uma arquitetura sofisticada baseada em padrões de design consagrados, permitindo a criação de workflows complexos de forma simples e organizada.

Objetivo e Filosofia do Projeto

O Operador foi desenvolvido com os seguintes objetivos:

  • Orquestração de Tarefas: Simplificar a execução de múltiplas ações de forma sequencial ou paralela
  • Modularidade: Permitir a criação de componentes reutilizáveis e independentes
  • Rastreabilidade: Oferecer monitoramento detalhado do progresso de execução
  • Extensibilidade: Facilitar a criação de actions, workers e pipelines customizados
  • Integração: Integrar-se perfeitamente com o ecossistema Laravel e SierraTecnologia

A filosofia central é proporcionar uma camada de abstração que permita aos desenvolvedores focar na lógica de negócio, enquanto o Operador gerencia a complexidade de orquestração, execução e rastreamento.

Benefícios de Uso

  • Produtividade: Reduz significativamente o tempo de desenvolvimento de automações complexas
  • Padronização: Estabelece convenções claras para criação de tarefas e actions
  • Manutenibilidade: Código organizado e bem estruturado facilita manutenção
  • Reusabilidade: Componentes podem ser reutilizados em diferentes contextos
  • Rastreamento: Monitoramento em tempo real do progresso de execução
  • Flexibilidade: Suporta múltiplos tipos de workers e estratégias de execução

Ecossistema SierraTecnologia

O Operador se encaixa perfeitamente no ecossistema SierraTecnologia, trabalhando em conjunto com:

  • Muleta: Traits e contratos utilitários
  • Pedreiro: Modelos base customizados
  • Tramite: Sistema de tramitação e workflows
  • Outros pacotes: Integração transparente com toda a stack SierraTecnologia

Instalação

Requisitos Mínimos

  • PHP: ^7.2 ou ^8.0+
  • Laravel: ^7.0 ou superior
  • Composer: ^2.0
  • Extensões PHP: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite

Instalação via Composer

Execute o seguinte comando no terminal do seu projeto Laravel:

composer require sierratecnologia/operador

Registro Automático do Service Provider

O Operador utiliza o auto-discovery do Laravel. O service provider será registrado automaticamente:

// Registrado automaticamente via composer.json extra.laravel.providers
Operador\OperadorProvider

Publicação de Configurações (Opcional)

Se necessário, publique as configurações e assets:

php artisan vendor:publish --provider="Operador\OperadorProvider"

Executar Migrações

Execute as migrações para criar as tabelas necessárias:

php artisan migrate

As seguintes tabelas serão criadas:

  • bot_runners - Execução de runners
  • bot_internet_urls - URLs descobertas
  • bot_internet_url_links - Relacionamento entre URLs
  • bot_internet_url_forms - Formulários encontrados
  • bot_internet_url_form_fields - Campos de formulários
  • references - Referências dinâmicas
  • referenceables - Polimorfismo de referências

Configuração do Ambiente

Se for utilizar integração com Laravel Forge, configure as variáveis de ambiente:

FORGE_TOKEN=seu_token_aqui
FORGE_SITE_ID=seu_site_id
FORGE_SERVER_ID=seu_server_id

Arquitetura e Estrutura Interna

Estrutura de Diretórios

src/
├── Actions/                  # Actions - padrão principal de execução
│   ├── Action.php           # Classe base de actions
│   ├── ActionCollection.php # Orquestração de múltiplas actions
│   ├── Agir/                # Actions executivas (Excel, Export, Ban/Unban)
│   ├── Collect/             # Actions de coleta (Database, Repository)
│   ├── Instagram/           # Integração com Instagram
│   ├── Hooks/               # Webhooks (NewCommit, etc.)
│   └── Models/              # Actions específicas de modelos
│
├── Components/              # Componentes da aplicação
│   ├── TaskComponent.php    # Base para todas as tasks
│   ├── Processing/          # Processamento de dados
│   ├── Worker/              # Workers especializados
│   │   ├── Explorer/        # Web crawling e scraping
│   │   ├── Logging/         # Processamento de logs
│   │   ├── Deploy/          # Deploy de aplicações
│   │   ├── Sync/            # Sincronização de dados
│   │   ├── Reports/         # Geração de relatórios
│   │   └── Life/            # Health checks
│   ├── View/                # Componentes de visualização
│   ├── Feactures/           # Features avançadas (Assistente, Training)
│   └── Interactions/        # Interações com usuário
│
├── Contracts/               # Interfaces e contratos
│   ├── ActionInterface.php  # Interface de actions
│   ├── RunnerInterface.php  # Interface de runners
│   ├── TaskInterface.php    # Interface de tasks
│   ├── Pipeline.php         # Pipeline base
│   ├── Stage.php            # Stage base
│   └── Attributes/          # Atributos de metadados
│
├── Models/                  # Modelos Eloquent
│   ├── Runner.php           # Executor de actions
│   ├── Task.php             # Tarefa genérica
│   ├── Job.php              # Job da fila
│   └── FailedJob.php        # Jobs que falharam
│
├── Pipelines/               # Pipelines de processamento
│   ├── Pipeline.php         # Pipeline padrão
│   ├── Stages/              # Stages de pipeline
│   └── Handlers/            # Handlers de tipos de dados
│
├── Services/                # Serviços especializados
│   ├── QueueService.php     # Gerenciamento de filas
│   └── ForgeService.php     # Integração com Laravel Forge
│
├── Facades/                 # Laravel Facades
├── Http/Controllers/        # Controllers HTTP
└── OperadorProvider.php     # Service Provider principal

Namespaces

O Operador utiliza PSR-4 autoloading:

"autoload": {
    "psr-4": {
        "Operador\\": "src/"
    }
}

Padrões Arquiteturais Adotados

O Operador emprega diversos padrões de design reconhecidos:

1. Strategy Pattern

Actions funcionam como estratégias intercambiáveis de processamento. Cada action implementa ActionInterface e pode ser executada de forma uniforme.

2. Pipeline Pattern

Processamento sequencial de dados através de stages, onde cada stage transforma o payload:

Input → Stage1 → Stage2 → Stage3 → Output

3. Builder Pattern

Construção fluente de runners e collections:

$runner->usingAction($action)->usingTarget($target)->execute();

4. Observer Pattern

Board executa callbacks para cada integração/componente, permitindo processamento customizado.

5. Service Provider Pattern

Integração com Laravel através de OperadorProvider.

6. Facade Pattern

Acesso simplificado a serviços através de facades Laravel.

Comunicação Entre Camadas

┌─────────────────────────────────────────────────────┐
│                  ActionCollection                    │
│         (Orquestrador principal de actions)         │
└──────────────────┬──────────────────────────────────┘
                   │
                   ├─► Stage 0 (Paralelo)
                   │   ├─► Runner 1 → Action 1 → Worker 1
                   │   ├─► Runner 2 → Action 2 → Worker 2
                   │   └─► Runner 3 → Action 3 → Worker 3
                   │
                   ├─► Stage 1 (Após Stage 0)
                   │   └─► Runner 4 → Action 4 → Worker 4
                   │
                   └─► Stage N
                       └─► Runner N → Action N → Worker N

Convenções e Boas Práticas

  1. Nomenclatura: Classes de actions devem ser verbos no infinitivo (exemplo: ExportToExcel, SearchFollows)
  2. Responsabilidade Única: Cada action deve ter uma única responsabilidade bem definida
  3. Imutabilidade: Pipelines devem retornar novos payloads transformados ao invés de modificar o original
  4. Rastreabilidade: Sempre utilize OutputableTrait para logging consistente
  5. Tipagem: Utilize type hints e return types em todos os métodos públicos

Principais Componentes

1. TaskComponent

Classe base para todas as tasks e actions do Operador.

Localização: src/Components/TaskComponent.php

use Operador\Components\TaskComponent;

class TaskComponent extends ActionBase
{
    // Tipos de actions disponíveis
    const SPIDER = 1;      // Exploração web
    const ROUTINE = 2;     // Rotinas periódicas
    const HOOK = 3;        // Webhooks/triggers
    const SYNC = 4;        // Sincronização
    const LIFE = 5;        // Health checks

    public $cod;           // Código único da action
    public $classAfetada;  // Classe/modelo afetado
    public $classAExecutar; // Classe executora
    public $type;          // Tipo da action
}

Métodos Principais:

  • loadActions(): Carrega todas as actions registradas
  • getActionByCode(string $cod): Obtém action por código
  • getModels(): Lista todos os modelos disponíveis
  • getOnlyActionsForModel($model): Filtra actions para um modelo específico

Exemplo de Uso:

// Obter action por código
$action = TaskComponent::getActionByCode('scanDomain');

// Listar actions para um modelo específico
$actions = TaskComponent::getOnlyActionsForModel(Domain::class);

2. Action e ActionCollection

Action

Classe base para criar actions executáveis.

Localização: src/Actions/Action.php

use Operador\Actions\Action;

class MinhaAction extends Action
{
    public function execute()
    {
        // Lógica da action
        $this->info('Executando MinhaAction');

        // Processar dados
        $resultado = $this->processar();

        $this->notice('Action executada com sucesso');

        return $resultado;
    }
}

ActionCollection

Orquestrador que gerencia múltiplas actions em stages.

Localização: src/Actions/ActionCollection.php

use Operador\Actions\ActionCollection;

$collection = new ActionCollection();

// Adicionar actions ao Stage 0 (executam em paralelo)
$collection->newAction($action1, $stage = 0, $actorNumber = 0);
$collection->newAction($action2, $stage = 0, $actorNumber = 1);

// Adicionar action ao Stage 1 (executa após Stage 0)
$collection->newAction($action3, $stage = 1, $actorNumber = 0);

// Preparar, executar e finalizar
$collection->prepare();
$collection->execute();
$collection->done();

// Monitorar progresso
echo "Progresso: " . $collection->getPorcDone() . "%";
echo "Actions executadas: " . $collection->executedActions;
echo "Total de stages: " . $collection->totalStages();

Principais Métodos:

  • newAction(ActionInterface $action, int $stage, int $actorNumber): Adiciona action
  • newActionCollection(ActionCollection $collection, int $stage): Adiciona outra collection
  • prepare(): Prepara runners para execução
  • execute(): Executa todos os runners sequencialmente por stage
  • done(): Finaliza execução
  • run(): Executa prepare() + execute() + done()
  • getPorcDone(): Retorna porcentagem de conclusão (0-100)
  • getTotalActionsCount(): Total de actions
  • getTotalTargetsCount(): Total de targets

3. Runner

Modelo que executa uma action contra um target específico.

Localização: src/Models/Runner.php

use Operador\Models\Runner;

$runner = Runner::makeWithOutput($output);

$runner->usingAction($action)
       ->usingTarget($modelInstance)
       ->prepare()
       ->execute()
       ->done();

Estrutura do Banco de Dados:

Schema::create('bot_runners', function (Blueprint $table) {
    $table->id();
    $table->string('action_code');  // Código da action
    $table->string('target_id');    // ID do target
    $table->string('progress');     // Progresso da execução
    $table->string('task');         // Descrição da task
    $table->string('stage');        // Stage atual
    $table->timestamps();
});

4. Workers Especializados

Spider - Web Crawler

Explora sites, extrai links e armazena informações.

Localização: src/Components/Worker/Explorer/Spider.php

use Operador\Components\Worker\Explorer\Spider;

// Criar spider para explorar domínio
$spider = new Spider('https://exemplo.com.br', $follow = true);

// Executar exploração
$spider->execute();

Funcionalidades:

  • Extração automática de links
  • Identificação de formulários
  • Análise de estrutura do site
  • Armazenamento de URLs descobertas
  • Suporte a crawling recursivo

Logging - Processamento de Logs

Processa logs de diferentes servidores web.

Localização: src/Components/Worker/Logging/Logging.php

Plugins Suportados:

  • Apache
  • Nginx
  • IIS
  • PHP Error Logs
use Operador\Components\Worker\Logging\Logging;

$logging = new Logging();
$logs = $logging->findForLogsInServer();

Deploy Worker

Gerencia deploy de aplicações.

Localização: src/Components/Worker/Deploy/DeployBusinessAmbiente.php

Sync Worker

Sincroniza dados entre sistemas.

Localização: src/Components/Worker/Sync/Project.php

5. Pipeline

Sistema de processamento sequencial através de stages.

Localização: src/Pipelines/Pipeline.php

use Operador\Pipelines\PipelineBase;
use Operador\Pipelines\TimesTwoStage;
use Operador\Pipelines\AddOneStage;

$pipeline = (new PipelineBase)
    ->pipe(new TimesTwoStage())     // Multiplica por 2
    ->pipe(new AddOneStage());      // Adiciona 1

$resultado = $pipeline->process(10);  // (10 * 2) + 1 = 21

Criando Stage Customizado:

use Operador\Contracts\Stage;
use Operador\Contracts\StageInterface;

class MeuStage extends Stage implements StageInterface
{
    public function __invoke($payload)
    {
        // Processar payload
        $payloadTransformado = $this->processar($payload);

        // Retornar payload transformado
        return $payloadTransformado;
    }

    private function processar($payload)
    {
        // Lógica de processamento
        return $payload;
    }
}

6. Board

Orquestrador de integrações e componentes.

Localização: src/Components/View/Board.php

use Operador\Components\View\Board;

$board = new Board();

// Executar para cada integração
$board->executeForEachIntegration(function ($integration) {
    $integration->sincronizar();
});

// Executar para cada componente (suporta recursão)
$board->executeForEachComponent(function ($component, $callback) {
    $dados = $integration->obterDados($component);

    foreach ($dados as $item) {
        // Processar subcomponentes recursivamente
        $callback($item);
    }
});

Boards Especializados:

  • BusinessBoard: Board de negócios
  • MidiasSocialBoard: Mídias sociais
  • InfraBoard: Infraestrutura
  • MarketingBoard: Marketing
  • PhotoBoard: Fotos e imagens
  • PersonalBoard: Tarefas pessoais

7. Services

QueueService

Gerenciamento de filas Laravel.

Localização: src/Services/QueueService.php

use Operador\Services\QueueService;

$queueService = new QueueService();

// Jobs ativos
$active = $queueService->activeJobs();

// Jobs agendados
$upcoming = $queueService->upcomingJobs();

// Jobs que falharam
$failed = $queueService->failedJobs();

// Reiniciar queue
$queueService->restart();

// Retentar todos os jobs
$queueService->retryAll();

// Retentar job específico
$queueService->retry($jobId);

// Cancelar job
$queueService->cancel($jobId, $table);

ForgeService

Integração com Laravel Forge.

Localização: src/Services/ForgeService.php

use Operador\Services\ForgeService;

$forgeService = new ForgeService();

// Obter configurações do servidor
$settings = $forgeService->getSettings();

// Gerenciar firewall
$firewalls = $forgeService->getFirewalls();

// Gerenciar sites
$sites = $forgeService->getSites();
$site = $forgeService->getSite($siteId);

// Gerenciar jobs agendados
$jobs = $forgeService->getJobs();
$forgeService->createJob($dados);
$forgeService->deleteJob($jobId);

// Gerenciar workers
$workers = $forgeService->getWorkers();
$forgeService->createWorker($dados);
$forgeService->deleteWorker($workerId);

Uso Prático

Exemplo 1: Executar Action Simples

use Operador\Components\TaskComponent;
use Operador\Models\Runner;
use Symfony\Component\Console\Output\ConsoleOutput;

// Obter action registrada
$action = TaskComponent::getActionByCode('scanDomain');

// Obter modelo target
$domain = Domain::find(1);

// Criar output para logging
$output = new ConsoleOutput();

// Criar e executar runner
$runner = Runner::makeWithOutput($output)
    ->usingAction($action)
    ->usingTarget($domain)
    ->run();  // prepare() + execute() + done()

Exemplo 2: Executar Múltiplas Actions em Stages

use Operador\Actions\ActionCollection;
use Operador\Components\TaskComponent;

// Criar collection
$collection = new ActionCollection();

// Stage 0: Coletar dados (em paralelo)
$coletarUsuarios = TaskComponent::getActionByCode('coletarUsuarios');
$coletarPosts = TaskComponent::getActionByCode('coletarPosts');

$collection->newAction($coletarUsuarios, 0, 0);
$collection->newAction($coletarPosts, 0, 1);

// Stage 1: Processar dados (após Stage 0)
$processarDados = TaskComponent::getActionByCode('processarDados');
$collection->newAction($processarDados, 1, 0);

// Stage 2: Gerar relatório (após Stage 1)
$gerarRelatorio = TaskComponent::getActionByCode('gerarRelatorio');
$collection->newAction($gerarRelatorio, 2, 0);

// Executar todos os stages sequencialmente
$collection->run();

// Monitorar progresso
echo "Progresso total: " . $collection->getPorcDone() . "%\n";
echo "Actions executadas: {$collection->executedActions} de {$collection->getTotalActionsCount()}\n";

Exemplo 3: Criar Action Customizada

namespace App\Actions;

use Operador\Actions\Action;
use Operador\Contracts\ActionInterface;

class ExportarRelatorioAction extends Action implements ActionInterface
{
    public function execute()
    {
        $this->info('Iniciando exportação de relatório...');

        try {
            // Obter dados
            $dados = $this->obterDados();

            $this->notice("Coletados {$dados->count()} registros");

            // Processar dados
            $processados = $this->processar($dados);

            // Gerar arquivo
            $arquivo = $this->gerarArquivo($processados);

            $this->info("Relatório gerado: {$arquivo}");

            return [
                'success' => true,
                'file' => $arquivo,
                'records' => $dados->count()
            ];

        } catch (\Exception $e) {
            $this->error("Erro ao exportar relatório: {$e->getMessage()}");

            return [
                'success' => false,
                'error' => $e->getMessage()
            ];
        }
    }

    private function obterDados()
    {
        return User::with('posts', 'comments')->get();
    }

    private function processar($dados)
    {
        return $dados->map(function ($user) {
            return [
                'nome' => $user->name,
                'email' => $user->email,
                'posts' => $user->posts->count(),
                'comentarios' => $user->comments->count(),
            ];
        });
    }

    private function gerarArquivo($dados)
    {
        $filename = 'relatorio_' . date('Y-m-d_H-i-s') . '.json';
        $path = storage_path("app/reports/{$filename}");

        file_put_contents($path, json_encode($dados, JSON_PRETTY_PRINT));

        return $path;
    }
}

Registrar Action no TaskComponent:

// Em um Service Provider ou no próprio TaskComponent

protected static function getRoutines($actions = [])
{
    $actions[] = self::insertAction(
        'exportarRelatorio',                    // Código único
        \App\Models\User::class,               // Classe afetada
        \App\Actions\ExportarRelatorioAction::class,  // Classe executora
        self::ROUTINE                          // Tipo
    );

    return parent::getRoutines($actions);
}

Exemplo 4: Usar Pipeline

use Operador\Pipelines\PipelineBase;

// Criar stages customizados
class ValidarDadosStage extends Stage
{
    public function __invoke($payload)
    {
        // Validar dados
        if (empty($payload['email'])) {
            throw new \Exception('Email é obrigatório');
        }

        return $payload;
    }
}

class EnriquecerDadosStage extends Stage
{
    public function __invoke($payload)
    {
        // Adicionar informações extras
        $payload['created_at'] = now();
        $payload['ip'] = request()->ip();

        return $payload;
    }
}

class SalvarDadosStage extends Stage
{
    public function __invoke($payload)
    {
        // Salvar no banco
        $user = User::create($payload);

        // Retornar usuário criado
        return $user;
    }
}

// Construir pipeline
$pipeline = (new PipelineBase)
    ->pipe(new ValidarDadosStage())
    ->pipe(new EnriquecerDadosStage())
    ->pipe(new SalvarDadosStage());

// Processar dados
$dados = [
    'name' => 'João Silva',
    'email' => 'joao@exemplo.com'
];

$usuario = $pipeline->process($dados);

Exemplo 5: Spider para Explorar Site

use Operador\Components\Worker\Explorer\Spider;

// Explorar site e extrair todos os links
$spider = new Spider('https://sierratecnologia.com.br', $follow = true);

// Executar exploração
$spider->execute();

// As URLs serão armazenadas automaticamente em:
// - bot_internet_urls (URLs descobertas)
// - bot_internet_url_links (relacionamentos)
// - bot_internet_url_forms (formulários encontrados)

Exemplo 6: Usar Board para Integrações

use Operador\Components\View\Boards\MidiasSocialBoard;

$board = new MidiasSocialBoard();

// Executar rotinas para todas as integrações
$board->executeForEachIntegration(function ($integration) {
    echo "Processando integração: " . get_class($integration) . "\n";

    // Sincronizar dados
    $integration->sincronizar();

    // Coletar novos posts
    $posts = $integration->coletarPosts();

    echo "Coletados {$posts->count()} posts\n";
});

// Processar componentes de forma recursiva
$board->executeForEachComponent(function ($component, $callback) {
    echo "Processando componente: {$component->getName()}\n";

    // Obter dados do componente
    $dados = $component->obterDados();

    // Processar cada item
    foreach ($dados as $item) {
        // Processar subcomponentes recursivamente
        $callback($item);
    }
});

Exemplo 7: Gerenciar Filas com QueueService

use Operador\Services\QueueService;

$queueService = new QueueService();

// Listar jobs ativos
$activeJobs = $queueService->activeJobs();

foreach ($activeJobs as $job) {
    echo "Job {$job->id}: {$job->queue} - Tentativas: {$job->attempts}\n";
}

// Listar jobs que falharam
$failedJobs = $queueService->failedJobs();

foreach ($failedJobs as $job) {
    echo "Job falhou: {$job->id} - {$job->exception}\n";
}

// Retentar job específico
if (!empty($failedJobs)) {
    $jobId = $failedJobs[0]->id;
    $queueService->retry($jobId);
    echo "Job {$jobId} reenfileirado\n";
}

// Reiniciar toda a fila
$queueService->restart();
echo "Fila reiniciada\n";

Integração com o Ecossistema SierraTecnologia

Bibliotecas Complementares

O Operador integra-se nativamente com outras bibliotecas da SierraTecnologia:

Muleta

Fornece traits e contratos utilitários usados pelo Operador:

use Muleta\Traits\OutputableTrait;

// Usado em Actions para logging consistente
class MinhaAction extends Action
{
    use OutputableTrait;

    public function execute()
    {
        $this->info('Informação');
        $this->notice('Aviso');
        $this->error('Erro');
    }
}

Pedreiro

Modelos base customizados:

use Pedreiro\Models\Base;

// Runner e outros models estendem Base
class Runner extends Base
{
    // Herda funcionalidades do Pedreiro
}

Tramite

Sistema de tramitação e workflows:

"require": {
    "privatejustice/tramite": "^0.4.0"
}

Integração para gerenciamento de fluxos de trabalho complexos.

Padrões de Versionamento

A SierraTecnologia segue o Versionamento Semântico (SemVer):

MAJOR.MINOR.PATCH

- MAJOR: Mudanças incompatíveis com versões anteriores
- MINOR: Novas funcionalidades compatíveis
- PATCH: Correções de bugs compatíveis

Exemplo: 1.2.3

  • 1 = versão major
  • 2 = versão minor (novas features)
  • 3 = versão patch (bugfixes)

Testes Automatizados e CI/CD

O Operador utiliza GitHub Actions para CI/CD:

Workflows Configurados

  1. Tests (.github/workflows/run-tests.yml)

    • Executa PHPUnit em múltiplas versões de PHP
    • Matrix testing: PHP 7.4, 8.0, 8.1, 8.2
    • Testa em Ubuntu e Windows
  2. PHP CS Fixer (.github/workflows/php-cs-fixer.yml)

    • Verifica e corrige automaticamente code style
    • Padrão PSR-12
    • Auto-commit de correções
  3. Psalm (.github/workflows/psalm.yml)

    • Análise estática de código
    • Nível de erro: 7
    • Detecta bugs potenciais

Como Diferentes Equipes Podem Aplicar

Equipe de Backend

// Criar actions para processar dados
class ProcessarPedidosAction extends Action
{
    public function execute()
    {
        $pedidos = Pedido::pendentes()->get();

        foreach ($pedidos as $pedido) {
            $this->processar($pedido);
        }
    }
}

Equipe de DevOps

// Usar ForgeService para automação
$forgeService = new ForgeService();

// Deploy automático
$forgeService->createJob([
    'command' => 'cd /home/forge/site && git pull origin main',
    'frequency' => 'hourly'
]);

Equipe de Data

// Pipeline de processamento de dados
$pipeline = (new PipelineBase)
    ->pipe(new ExtrairDadosStage())
    ->pipe(new TransformarDadosStage())
    ->pipe(new CarregarDadosStage());

$resultado = $pipeline->process($fonte);

Equipe de Marketing

// Board de mídias sociais
$board = new MidiasSocialBoard();

$board->executeForEachIntegration(function ($integration) {
    $integration->publicarPost([
        'titulo' => 'Novidade!',
        'conteudo' => 'Confira nosso novo produto'
    ]);
});

Extensão e Customização

Criar Actions Customizadas

Passo 1: Criar Classe da Action

namespace App\Operador\Actions;

use Operador\Actions\Action;
use Operador\Contracts\ActionInterface;

class MinhaActionCustomizada extends Action implements ActionInterface
{
    /**
     * Parâmetros da action
     */
    protected $parametro1;
    protected $parametro2;

    /**
     * Construtor
     */
    public function __construct($parametro1, $parametro2)
    {
        $this->parametro1 = $parametro1;
        $this->parametro2 = $parametro2;
    }

    /**
     * Método principal de execução
     */
    public function execute()
    {
        $this->info('Iniciando MinhaActionCustomizada');

        try {
            // Sua lógica aqui
            $resultado = $this->processar();

            $this->notice('Action executada com sucesso');

            return $resultado;

        } catch (\Exception $e) {
            $this->error("Erro: {$e->getMessage()}");
            throw $e;
        }
    }

    /**
     * Lógica de processamento
     */
    private function processar()
    {
        // Implementar lógica
        return true;
    }
}

Passo 2: Registrar Action

// Em App\Providers\OperadorServiceProvider

use Operador\Components\TaskComponent;

class OperadorServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Estender TaskComponent para registrar action
        TaskComponent::macro('getMinhasActions', function () {
            return [
                TaskComponent::insertAction(
                    'minhaActionCustomizada',           // Código único
                    \App\Models\MeuModelo::class,      // Modelo afetado
                    \App\Operador\Actions\MinhaActionCustomizada::class,  // Classe
                    TaskComponent::ROUTINE             // Tipo
                )
            ];
        });
    }
}

Passo 3: Usar Action

use Operador\Components\TaskComponent;
use Operador\Models\Runner;

// Obter action
$action = TaskComponent::getActionByCode('minhaActionCustomizada');

// Executar
$runner = Runner::makeWithOutput($output)
    ->usingAction($action)
    ->usingTarget($modelo)
    ->run();

Criar Workers Customizados

namespace App\Operador\Workers;

class MeuWorkerCustomizado
{
    /**
     * Output para logging
     */
    protected $output;

    /**
     * Target sendo processado
     */
    protected $target;

    /**
     * Construtor
     */
    public function __construct($output, $target)
    {
        $this->output = $output;
        $this->target = $target;
    }

    /**
     * Executar worker
     */
    public function execute(): bool
    {
        $this->output->writeln('<info>Executando MeuWorkerCustomizado</info>');

        // Sua lógica aqui
        $this->processar();

        $this->output->writeln('<notice>Worker executado com sucesso</notice>');

        return true;
    }

    /**
     * Processar target
     */
    private function processar()
    {
        // Implementar lógica de processamento
    }
}

Criar Stages de Pipeline Customizados

namespace App\Operador\Stages;

use Operador\Contracts\Stage;
use Operador\Contracts\StageInterface;

class MeuStageCustomizado extends Stage implements StageInterface
{
    /**
     * Processar payload
     */
    public function __invoke($payload)
    {
        // Validar payload
        $this->validar($payload);

        // Transformar payload
        $payloadTransformado = $this->transformar($payload);

        // Retornar payload transformado
        return $payloadTransformado;
    }

    /**
     * Validar payload
     */
    private function validar($payload)
    {
        if (!isset($payload['campo_obrigatorio'])) {
            throw new \Exception('Campo obrigatório não encontrado');
        }
    }

    /**
     * Transformar payload
     */
    private function transformar($payload)
    {
        // Adicionar timestamp
        $payload['processed_at'] = now();

        // Adicionar metadados
        $payload['metadata'] = [
            'stage' => 'MeuStageCustomizado',
            'version' => '1.0.0'
        ];

        return $payload;
    }
}

Usar Stage Customizado:

use Operador\Pipelines\PipelineBase;
use App\Operador\Stages\MeuStageCustomizado;

$pipeline = (new PipelineBase)
    ->pipe(new MeuStageCustomizado())
    ->pipe(new OutroStage());

$resultado = $pipeline->process($dados);

Criar Boards Customizados

namespace App\Operador\Boards;

use Operador\Components\View\Board;

class MeuBoardCustomizado extends Board
{
    /**
     * Definir integrações
     */
    public function getIntegrations(): array
    {
        return array_merge(parent::getIntegrations(), [
            new MinhaIntegracaoCustomizada(),
            new OutraIntegracao(),
        ]);
    }

    /**
     * Definir actions disponíveis
     */
    public function getActions(): array
    {
        return array_merge(parent::getActions(), [
            \App\Actions\MinhaAction::class,
            \App\Actions\OutraAction::class,
        ]);
    }

    /**
     * Definir componentes
     */
    public function getComponents(): array
    {
        return array_merge(parent::getComponents(), [
            'meu_componente' => \App\Components\MeuComponente::class,
        ]);
    }

    /**
     * Executar rotinas customizadas
     */
    public function executeRoutines(): void
    {
        parent::executeRoutines();

        // Suas rotinas customizadas
        $this->minhaRotinaCustomizada();
    }

    /**
     * Rotina customizada
     */
    private function minhaRotinaCustomizada()
    {
        // Implementar lógica
    }
}

Substituir Classes Padrão via IoC

// Em App\Providers\AppServiceProvider

public function register()
{
    // Substituir Runner padrão
    $this->app->bind(
        \Operador\Models\Runner::class,
        \App\Operador\Models\MeuRunnerCustomizado::class
    );

    // Substituir ActionCollection
    $this->app->bind(
        \Operador\Actions\ActionCollection::class,
        \App\Operador\Actions\MinhaCollectionCustomizada::class
    );
}

Boas Práticas para Manutenção

  1. Documentação: Sempre documente suas classes e métodos customizados
  2. Testes: Escreva testes unitários para actions e workers customizados
  3. Versionamento: Mantenha compatibilidade com a API do Operador
  4. Logging: Utilize OutputableTrait para logging consistente
  5. Tratamento de Erros: Sempre capture e trate exceções adequadamente
  6. Code Style: Siga os padrões PSR-12
  7. Type Hints: Utilize type hints e return types

Exemplos Reais

Exemplo 1: Sistema de Processamento de Pedidos

Cenário: E-commerce que precisa processar pedidos automaticamente em múltiplos estágios.

Solução com Operador:

namespace App\Actions\Pedidos;

use Operador\Actions\ActionCollection;
use Operador\Components\TaskComponent;

class ProcessarPedidosAutomaticamente
{
    public function executar()
    {
        $collection = new ActionCollection();

        // Stage 0: Validar pedidos
        $validarPedidos = TaskComponent::getActionByCode('validarPedidos');
        $collection->newAction($validarPedidos, 0);

        // Stage 1: Processar pagamentos
        $processarPagamentos = TaskComponent::getActionByCode('processarPagamentos');
        $collection->newAction($processarPagamentos, 1);

        // Stage 2: Gerar notas fiscais
        $gerarNotasFiscais = TaskComponent::getActionByCode('gerarNotasFiscais');
        $collection->newAction($gerarNotasFiscais, 2);

        // Stage 3: Enviar para logística
        $enviarLogistica = TaskComponent::getActionByCode('enviarLogistica');
        $collection->newAction($enviarLogistica, 3);

        // Stage 4: Notificar clientes
        $notificarClientes = TaskComponent::getActionByCode('notificarClientes');
        $collection->newAction($notificarClientes, 4);

        // Executar pipeline completo
        $collection->run();

        return [
            'success' => true,
            'progress' => $collection->getPorcDone(),
            'actions_executed' => $collection->executedActions
        ];
    }
}

Resultado:

  • ✅ Processamento automatizado de pedidos
  • ✅ Execução sequencial garantida
  • ✅ Rastreamento de progresso em tempo real
  • ✅ Fácil manutenção e extensão

Exemplo 2: Sincronização de Dados de Múltiplas APIs

Cenário: Sistema que precisa sincronizar dados de Instagram, Facebook e Twitter.

Antes (Sem Operador):

// Código desorganizado e difícil de manter
class SincronizarMidiasSociais
{
    public function executar()
    {
        // Instagram
        try {
            $instagramApi = new InstagramApi();
            $posts = $instagramApi->getPosts();
            foreach ($posts as $post) {
                Post::updateOrCreate(['instagram_id' => $post->id], $post->toArray());
            }
        } catch (\Exception $e) {
            Log::error("Erro Instagram: " . $e->getMessage());
        }

        // Facebook
        try {
            $facebookApi = new FacebookApi();
            $posts = $facebookApi->getPosts();
            foreach ($posts as $post) {
                Post::updateOrCreate(['facebook_id' => $post->id], $post->toArray());
            }
        } catch (\Exception $e) {
            Log::error("Erro Facebook: " . $e->getMessage());
        }

        // Twitter
        try {
            $twitterApi = new TwitterApi();
            $posts = $twitterApi->getTweets();
            foreach ($posts as $post) {
                Post::updateOrCreate(['twitter_id' => $post->id], $post->toArray());
            }
        } catch (\Exception $e) {
            Log::error("Erro Twitter: " . $e->getMessage());
        }
    }
}

Depois (Com Operador):

use Operador\Components\View\Boards\MidiasSocialBoard;

class SincronizarMidiasSociais
{
    public function executar()
    {
        $board = new MidiasSocialBoard();

        // Executar sincronização para todas as integrações
        $board->executeForEachIntegration(function ($integration) {
            $this->info("Sincronizando {$integration->getName()}");

            // Coletar posts
            $posts = $integration->coletarPosts();

            // Salvar no banco
            foreach ($posts as $post) {
                Post::updateOrCreate(
                    [$integration->getName() . '_id' => $post->id],
                    $post->toArray()
                );
            }

            $this->notice("Sincronizados {$posts->count()} posts de {$integration->getName()}");
        });
    }
}

Benefícios:

  • ✅ Código 70% mais conciso
  • ✅ Fácil adicionar novas integrações
  • ✅ Logging consistente
  • ✅ Tratamento de erros centralizado
  • ✅ Manutenção simplificada

Exemplo 3: Web Scraping e Análise de Concorrência

Cenário: Sistema de inteligência de mercado que monitora sites concorrentes.

Solução com Operador:

use Operador\Components\Worker\Explorer\Spider;
use Operador\Actions\ActionCollection;

class MonitorarConcorrentes
{
    protected $concorrentes = [
        'https://concorrente1.com.br',
        'https://concorrente2.com.br',
        'https://concorrente3.com.br',
    ];

    public function executar()
    {
        $collection = new ActionCollection();

        // Stage 0: Explorar sites (paralelo)
        foreach ($this->concorrentes as $index => $url) {
            $spider = new Spider($url, $follow = true);
            $explorarAction = new ExplorarSiteAction($spider);
            $collection->newAction($explorarAction, 0, $index);
        }

        // Stage 1: Extrair preços
        $extrairPrecos = TaskComponent::getActionByCode('extrairPrecos');
        $collection->newAction($extrairPrecos, 1);

        // Stage 2: Analisar mudanças
        $analisarMudancas = TaskComponent::getActionByCode('analisarMudancas');
        $collection->newAction($analisarMudancas, 2);

        // Stage 3: Gerar alertas
        $gerarAlertas = TaskComponent::getActionByCode('gerarAlertas');
        $collection->newAction($gerarAlertas, 3);

        // Executar
        $collection->run();

        return [
            'sites_explorados' => count($this->concorrentes),
            'progress' => $collection->getPorcDone()
        ];
    }
}

Resultados:

  • ✅ Monitoramento automatizado de concorrentes
  • ✅ Exploração paralela de múltiplos sites
  • ✅ Detecção automática de mudanças de preços
  • ✅ Alertas em tempo real

Exemplo 4: Pipeline de Processamento de Imagens

Cenário: Sistema de galeria que processa uploads de imagens.

Solução com Pipeline:

use Operador\Pipelines\PipelineBase;

// Stages customizados
class ValidarImagemStage extends Stage
{
    public function __invoke($payload)
    {
        if ($payload['size'] > 10 * 1024 * 1024) {
            throw new \Exception('Imagem maior que 10MB');
        }

        if (!in_array($payload['mime'], ['image/jpeg', 'image/png'])) {
            throw new \Exception('Formato inválido');
        }

        return $payload;
    }
}

class RedimensionarImagemStage extends Stage
{
    public function __invoke($payload)
    {
        $imagem = Image::make($payload['path']);

        // Criar thumbnails
        $payload['thumbnails'] = [
            'small' => $this->resize($imagem, 150, 150),
            'medium' => $this->resize($imagem, 300, 300),
            'large' => $this->resize($imagem, 800, 800),
        ];

        return $payload;
    }

    private function resize($imagem, $width, $height)
    {
        $filename = uniqid() . '.jpg';
        $path = storage_path("app/thumbnails/{$width}x{$height}/{$filename}");

        $imagem->fit($width, $height)->save($path);

        return $path;
    }
}

class OtimizarImagemStage extends Stage
{
    public function __invoke($payload)
    {
        // Otimizar imagem original
        $optimizer = OptimizerChainFactory::create();
        $optimizer->optimize($payload['path']);

        // Otimizar thumbnails
        foreach ($payload['thumbnails'] as $thumbnail) {
            $optimizer->optimize($thumbnail);
        }

        return $payload;
    }
}

class SalvarBancoDadosStage extends Stage
{
    public function __invoke($payload)
    {
        $imagem = Imagem::create([
            'path' => $payload['path'],
            'thumbnails' => $payload['thumbnails'],
            'size' => $payload['size'],
            'mime' => $payload['mime'],
        ]);

        return $imagem;
    }
}

// Usar pipeline
class ProcessarUploadImagem
{
    public function executar($file)
    {
        $pipeline = (new PipelineBase)
            ->pipe(new ValidarImagemStage())
            ->pipe(new RedimensionarImagemStage())
            ->pipe(new OtimizarImagemStage())
            ->pipe(new SalvarBancoDadosStage());

        $dados = [
            'path' => $file->store('images'),
            'size' => $file->getSize(),
            'mime' => $file->getMimeType(),
        ];

        return $pipeline->process($dados);
    }
}

Benefícios:

  • ✅ Pipeline de processamento claro e organizado
  • ✅ Fácil adicionar ou remover etapas
  • ✅ Cada stage tem responsabilidade única
  • ✅ Facilita testes unitários

Guia de Contribuição

Como Contribuir

Agradecemos seu interesse em contribuir para o Operador! Siga as instruções abaixo:

1. Fork do Repositório

# Fork via GitHub
# Depois clone seu fork
git clone https://github.com/seu-usuario/operador.git
cd operador

2. Configurar Ambiente Local

# Instalar dependências
composer install

# Copiar .env.example (se houver)
cp .env.example .env

# Executar migrações
php artisan migrate

3. Criar Branch para Feature/Fix

Siga a convenção de nomenclatura:

# Features
git checkout -b feature/nome-da-feature

# Bugfixes
git checkout -b fix/nome-do-bug

# Refatoração
git checkout -b refactor/nome-da-refatoracao

# Documentação
git checkout -b docs/nome-da-documentacao

4. Fazer Alterações

  • Escreva código seguindo PSR-12
  • Adicione testes para novas funcionalidades
  • Mantenha a cobertura de testes
  • Documente métodos públicos

5. Executar Testes e Verificações

# Executar testes
./vendor/bin/phpunit

# Verificar code style
./vendor/bin/php-cs-fixer fix --dry-run --diff

# Análise estática
./vendor/bin/psalm

# GrumPHP (se configurado)
./vendor/bin/grumphp run

6. Commit das Alterações

Siga o padrão de mensagens de commit:

# Formato: tipo(escopo): descrição

# Exemplos:
git commit -m "feat(actions): adicionar suporte a retry em actions"
git commit -m "fix(runner): corrigir memory leak em execução paralela"
git commit -m "docs(readme): atualizar exemplo de pipeline"
git commit -m "test(spider): adicionar testes para Spider::explore"
git commit -m "refactor(collection): simplificar lógica de stages"

Tipos de Commit:

  • feat: Nova funcionalidade
  • fix: Correção de bug
  • docs: Documentação
  • test: Testes
  • refactor: Refatoração
  • style: Formatação de código
  • perf: Melhoria de performance
  • chore: Tarefas gerais

7. Push e Pull Request

# Push para seu fork
git push origin feature/nome-da-feature

# Criar Pull Request via GitHub
# Descreva claramente as mudanças
# Referencie issues relacionadas

Padrões de Código

PSR-12

O Operador segue rigorosamente o padrão PSR-12:

<?php

namespace Operador\Actions;

use Operador\Contracts\ActionInterface;

class MinhaAction implements ActionInterface
{
    /**
     * Descrição do método
     *
     * @param string $parametro
     * @return bool
     */
    public function execute(string $parametro): bool
    {
        // Código aqui
        return true;
    }
}

Convenções de Nomenclatura

  • Classes: PascalCase (exemplo: ActionCollection)
  • Métodos: camelCase (exemplo: executeAction)
  • Variáveis: camelCase (exemplo: $actualStage)
  • Constantes: UPPER_SNAKE_CASE (exemplo: SPIDER)
  • Namespaces: PascalCase (exemplo: Operador\Actions)

Documentação de Código

/**
 * Executa action contra target específico
 *
 * Este método prepara o worker, executa a action e
 * registra o progresso no banco de dados.
 *
 * @param ActionInterface $action Action a ser executada
 * @param Base $target Target/modelo a ser processado
 * @return bool True se executado com sucesso
 * @throws \Exception Se worker não puder ser instanciado
 */
public function execute(ActionInterface $action, Base $target): bool
{
    // Implementação
}

Executar Testes Localmente

PHPUnit

# Executar todos os testes
./vendor/bin/phpunit

# Executar com cobertura
./vendor/bin/phpunit --coverage-html coverage

# Executar teste específico
./vendor/bin/phpunit tests/Unit/Actions/ActionCollectionTest.php

# Executar com filtro
./vendor/bin/phpunit --filter testExecute

PHP CS Fixer

# Verificar problemas de estilo
./vendor/bin/php-cs-fixer fix --dry-run --diff

# Corrigir automaticamente
./vendor/bin/php-cs-fixer fix

# Verificar arquivo específico
./vendor/bin/php-cs-fixer fix src/Actions/Action.php --dry-run

Psalm (Análise Estática)

# Executar análise
./vendor/bin/psalm

# Com relatório detalhado
./vendor/bin/psalm --show-info=true

# Gerar baseline (ignorar erros existentes)
./vendor/bin/psalm --set-baseline=psalm-baseline.xml

Política de Licença

O Operador é licenciado sob ANCAP License.

Ao contribuir, você concorda que suas contribuições serão licenciadas sob a mesma licença.

Autores e Contato

Mantenedor Principal: SierraTecnologia

Email:

Links:

Processo de Review

  1. Automated Checks: GitHub Actions executará automaticamente:

    • Testes PHPUnit
    • PHP CS Fixer
    • Psalm
  2. Code Review: Mantenedores revisarão:

    • Qualidade do código
    • Testes adequados
    • Documentação
    • Aderência aos padrões
  3. Aprovação: Após aprovação, o PR será merged

Versionamento Semântico

O Operador segue Semantic Versioning 2.0.0:

MAJOR.MINOR.PATCH

1.2.3
│ │ └─ Patch: Correções de bugs
│ └─── Minor: Novas funcionalidades (compatível)
└───── Major: Mudanças incompatíveis (breaking changes)

Ferramentas de Qualidade

GitHub Actions Workflows

O Operador utiliza GitHub Actions para garantir qualidade contínua do código.

1. Tests Workflow

Arquivo: .github/workflows/run-tests.yml

Executa testes automatizados em múltiplos ambientes:

  • Sistemas Operacionais: Ubuntu e Windows
  • Versões PHP: 7.4, 8.0, 8.1, 8.2
  • Versões Laravel: 7.x, 8.x, 9.x, 10.x
  • Estratégias de Dependências: prefer-lowest e prefer-stable
# Executar localmente
./vendor/bin/phpunit

# Com cobertura
./vendor/bin/phpunit --coverage-html coverage

# Visualizar cobertura
open coverage/index.html

2. PHP CS Fixer Workflow

Arquivo: .github/workflows/php-cs-fixer.yml

Verifica e corrige automaticamente o estilo de código segundo PSR-12:

# Verificar problemas (dry-run)
./vendor/bin/php-cs-fixer fix --dry-run --diff --config=.php_cs

# Corrigir automaticamente
./vendor/bin/php-cs-fixer fix --config=.php_cs

# Verificar arquivo específico
./vendor/bin/php-cs-fixer fix src/Actions/Action.php --dry-run

Regras Configuradas (.php_cs):

  • Padrão PSR-2/PSR-12
  • Permissão de constantes uppercase
  • Flexibilidade em espaçamento de argumentos

3. Psalm Workflow

Arquivo: .github/workflows/psalm.yml

Análise estática de código para detectar bugs potenciais:

# Executar análise
./vendor/bin/psalm

# Com informações detalhadas
./vendor/bin/psalm --show-info=true

# Gerar relatório JSON
./vendor/bin/psalm --report=psalm-report.json

# Limpar cache
./vendor/bin/psalm --clear-cache

Configuração (psalm.xml):

  • Nível de Erro: 7 (rigoroso)
  • Diretórios Analisados: src/
  • Ignora: vendor/

Configuração Local de Desenvolvimento

GrumPHP

Hooks Git automáticos para garantir qualidade antes do commit:

# Instalar hooks
./vendor/bin/grumphp git:init

# Executar manualmente
./vendor/bin/grumphp run

# Bypass (use com cautela)
git commit --no-verify

Verificações Configuradas (grumphp.yml):

  • Tamanho de arquivo (max 10MB)
  • Formato de mensagem de commit
  • Blacklist de código (var_dump, die, exit)
  • Nomenclatura de branches
  • Psalm

PHPUnit

Configuração: phpunit.xml

<phpunit colors="true">
    <testsuites>
        <testsuite name="Operador Tests">
            <directory>./tests/</directory>
        </testsuite>
    </testsuites>
</phpunit>

Executar Testes:

# Todos os testes
./vendor/bin/phpunit

# Suite específica
./vendor/bin/phpunit --testsuite "Operador Tests"

# Teste específico
./vendor/bin/phpunit tests/Unit/Actions/ActionCollectionTest.php

# Com filtro de método
./vendor/bin/phpunit --filter testExecuteActionsInStages

# Com cobertura de código
./vendor/bin/phpunit --coverage-html coverage --coverage-filter src/

Badges de Qualidade

Adicione ao README os badges de status:

[![Tests](https://github.com/sierratecnologia/operador/workflows/Tests/badge.svg)](https://github.com/sierratecnologia/operador/actions)
[![Code Style](https://github.com/sierratecnologia/operador/workflows/Check%20%26%20fix%20styling/badge.svg)](https://github.com/sierratecnologia/operador/actions)
[![Psalm](https://github.com/sierratecnologia/operador/workflows/Psalm/badge.svg)](https://github.com/sierratecnologia/operador/actions)

Integração com Scrutinizer CI

O Operador também utiliza Scrutinizer CI para análise adicional de qualidade.

Configuração: .scrutinizer.yml

# Visualizar no Scrutinizer
https://scrutinizer-ci.com/g/sierratecnologia/operador/

Integração com CodeClimate

Configuração: .codeclimate.yml

Análise de:

  • Complexidade ciclomática
  • Duplicação de código
  • Manutenibilidade
  • Cobertura de testes

Comandos Úteis de Desenvolvimento

# Instalar dependências de desenvolvimento
composer install

# Atualizar dependências
composer update

# Verificar dependências desatualizadas
composer outdated

# Validar composer.json
composer validate

# Dump autoload
composer dump-autoload

# Executar todas as verificações de qualidade
./vendor/bin/grumphp run

# Limpar caches
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear

Checklist de Qualidade

Antes de criar Pull Request, verifique:

  • ✅ Todos os testes passando (./vendor/bin/phpunit)
  • ✅ Code style correto (./vendor/bin/php-cs-fixer fix --dry-run)
  • ✅ Análise estática sem erros (./vendor/bin/psalm)
  • ✅ Novos testes adicionados para novas funcionalidades
  • ✅ Documentação atualizada
  • ✅ Mensagem de commit seguindo padrões
  • ✅ GrumPHP validado (./vendor/bin/grumphp run)
  • ✅ Sem código comentado ou debug (var_dump, dd, etc.)
  • ✅ Sem conflitos de merge

About SierraTecnologia

A SierraTecnologia é uma organização brasileira focada no desenvolvimento de soluções tecnológicas inovadoras e de alta qualidade para o ecossistema Laravel e PHP.

Nossa Missão

Criar ferramentas e bibliotecas que aumentem a produtividade dos desenvolvedores, estabeleçam padrões de excelência e simplifiquem tarefas complexas.

Nossos Valores

  • Qualidade: Código limpo, testado e bem documentado
  • Inovação: Soluções criativas para problemas reais
  • Comunidade: Contribuição ativa com o open source
  • Excelência: Comprometimento com as melhores práticas

Outras Bibliotecas

Conheça outros projetos da SierraTecnologia:

  • Muleta: Traits e contratos utilitários
  • Pedreiro: Modelos base e helpers
  • Tramite: Sistema de tramitação e workflows
  • Fabrica: Infraestrutura e domain models
  • E mais...

Contato

Licença

O Operador é um software open-source licenciado sob a ANCAP License.

Desenvolvido com ❤️ pela SierraTecnologia