PHPackages                             argws/laravel-updater - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. argws/laravel-updater

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

argws/laravel-updater
=====================

Sistema genérico de autoatualização para aplicações Laravel.

v0.1.177(2mo ago)0507proprietaryPHPPHP &gt;=8.2CI passing

Since Feb 10Pushed 2mo agoCompare

[ Source](https://github.com/wkarts/laravel-updater)[ Packagist](https://packagist.org/packages/argws/laravel-updater)[ RSS](/packages/argws-laravel-updater/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (351)Used By (0)

argws/laravel-updater
=====================

[](#argwslaravel-updater)

Pacote Composer para autoatualização segura, idempotente e reversível de aplicações Laravel, agora com camada de **Updater Manager** (painel administrativo, auth independente, branding white-label e API de disparo).

Compatibilidade
---------------

[](#compatibilidade)

- PHP: **8.2, 8.3, 8.4**
- Laravel/Illuminate: **10, 11, 12**

Instalação
----------

[](#instalação)

```
composer require argws/laravel-updater
php artisan vendor:publish --tag=updater-config
```

### Atualização do config após update do pacote

[](#atualização-do-config-após-update-do-pacote)

### Publicação automática de config/views (equivalente ao --force)

[](#publicação-automática-de-configviews-equivalente-ao---force)

A partir desta versão, o updater pode sincronizar automaticamente (em execução de console) os arquivos publicados de `config` e `views` para manter o pacote atualizado, com comportamento equivalente ao `vendor:publish --force`.

Controle por `.env`:

```
UPDATER_AUTO_PUBLISH_ENABLED=true
UPDATER_AUTO_PUBLISH_CONFIG=true
UPDATER_AUTO_PUBLISH_VIEWS=true
```

Se quiser desativar a sincronização automática, ajuste para `false`.

Por padrão, o `vendor:publish` **não sobrescreve** `config/updater.php` se ele já existir no seu projeto. Se uma nova versão do pacote trouxer chaves novas no config, você tem 2 opções:

```
# atualizar o arquivo de config do projeto com a versão do pacote (sobrescreve)
php artisan vendor:publish --tag=updater-config --force
```

> Dica: se você personaliza `config/updater.php`, recomendo versionar esse arquivo no seu repositório.

> Os assets do updater são sincronizados automaticamente para `public/vendor/laravel-updater` durante o boot do pacote. Assim, você não precisa rodar `php artisan vendor:publish --tag=updater-assets --force` a cada instalação/atualização.

Rotas principais
----------------

[](#rotas-principais)

- `/_updater`
- `/_updater/login`
- `/_updater/security`
- `/_updater/settings`
- `POST /_updater/api/trigger`

Variáveis de ambiente (principais)
----------------------------------

[](#variáveis-de-ambiente-principais)

```
UPDATER_UI_ENABLED=true
UPDATER_UI_PREFIX=_updater
UPDATER_UI_AUTH_ENABLED=true
UPDATER_UI_AUTO_PROVISION_ADMIN=true
UPDATER_UI_DEFAULT_EMAIL=admin@admin.com
UPDATER_UI_DEFAULT_PASSWORD=123456
UPDATER_UI_DEFAULT_NAME=Admin
UPDATER_UI_SESSION_TTL=120
UPDATER_UI_RATE_LIMIT_MAX=10
UPDATER_UI_RATE_LIMIT_WINDOW=600

UPDATER_UI_2FA_ENABLED=true
UPDATER_UI_2FA_REQUIRED=false
UPDATER_UI_2FA_ISSUER="Argws Updater"

UPDATER_GIT_PATH=/var/www/seu-projeto
UPDATER_GIT_REMOTE=origin
UPDATER_GIT_BRANCH=main
UPDATER_GIT_FF_ONLY=true
# opcional para bootstrap automático quando a pasta ainda não é git
UPDATER_GIT_AUTO_INIT=false
UPDATER_GIT_REMOTE_URL=

UPDATER_GIT_DEFAULT_UPDATE_MODE=merge
UPDATER_SOURCES_ALLOW_MULTIPLE=false

# Composer (somente se necessário)
# Em alguns servidores (Supervisor/cron), o PATH pode vir reduzido. O updater tenta normalizar o PATH
# e também detecta composer em locais comuns. Se ainda assim falhar, informe o caminho completo.
UPDATER_COMPOSER_BIN=/usr/bin/composer

# Se você edita arquivos em produção (ex.: config/updater.php), isso pode deixar o repositório "dirty".
# Defina quais caminhos podem ficar sujos sem bloquear a atualização.
UPDATER_GIT_DIRTY_ALLOWLIST="config/updater.php,.env,storage/,bootstrap/cache/"

UPDATER_APP_NAME="ARGWS ERP - Updater"      # opcional (default: APP_NAME)
UPDATER_APP_SUFIX_NAME="Homolog"   # opcional
UPDATER_APP_DESC="Sistema em atualização" # opcional

# Whitelabel (opcional) - URLs diretas (sem upload)
UPDATER_BRAND_LOGO_URL="https://seu-dominio.com.br/assets/logo.png"
UPDATER_BRAND_FAVICON_URL="https://seu-dominio.com.br/assets/favicon.ico"
UPDATER_BRAND_PRIMARY_COLOR="#0d6efd"
UPDATER_SYNC_TOKEN=
```

Padrão recomendado de `.env` por cenário
----------------------------------------

[](#padrão-recomendado-de-env-por-cenário)

> **Importante:** após qualquer alteração no `.env`, execute `php artisan config:clear`.

### 1) Produção (recomendado)

[](#1-produção-recomendado)

```
UPDATER_TRIGGER_DRIVER=queue
UPDATER_UI_FORCE_SYNC=false

UPDATER_GIT_PATH=/var/www/sua-aplicacao
UPDATER_GIT_REMOTE=origin
UPDATER_GIT_BRANCH=main
UPDATER_GIT_FF_ONLY=true
UPDATER_GIT_AUTO_INIT=false
UPDATER_GIT_DEFAULT_UPDATE_MODE=ff-only
```

Quando usar:

- aplicação com worker de fila ativo;
- deploy previsível e com menor bloqueio da requisição HTTP.

### 2) Homologação / teste manual pelo painel

[](#2-homologação--teste-manual-pelo-painel)

```
UPDATER_TRIGGER_DRIVER=sync
UPDATER_UI_FORCE_SYNC=true

UPDATER_GIT_PATH=/home/seu-usuario/htdocs/seu-projeto
UPDATER_GIT_REMOTE=origin
UPDATER_GIT_BRANCH=main
UPDATER_GIT_AUTO_INIT=true
UPDATER_GIT_REMOTE_URL=https://github.com/wkarts/seu-repo.git
UPDATER_GIT_DEFAULT_UPDATE_MODE=tag
```

Quando usar:

- você quer ver resultado imediato no painel;
- ambiente com menor volume de acesso;
- diretório pode precisar de bootstrap git automático.

### 3) Compatibilidade de variáveis antigas de login

[](#3-compatibilidade-de-variáveis-antigas-de-login)

O updater aceita os dois formatos abaixo para rate limit do login UI:

```
# formato novo (preferencial)
UPDATER_UI_RATE_LIMIT_MAX=10
UPDATER_UI_RATE_LIMIT_WINDOW=600

# formato legado (compatível)
UPDATER_UI_LOGIN_MAX_ATTEMPTS=10
UPDATER_UI_LOGIN_DECAY_MINUTES=10
```

Se ambos existirem, o formato novo (`UPDATER_UI_RATE_LIMIT_*`) tem prioridade.

.env do updater sem sobrescrever seu .env atual
-----------------------------------------------

[](#env-do-updater-sem-sobrescrever-seu-env-atual)

Para reaproveitar o `.env` atual da aplicação (sem perder chaves já existentes), o pacote inclui:

- `stubs/env/updater.default.env.example`
- `stubs/env/updater.production.env.example`
- `stubs/env/updater.homolog.env.example`

E um comando de sincronização não destrutiva:

```
# apenas lista chaves UPDATER_* ausentes
php artisan system:update:env-sync --profile=default

# adiciona somente as chaves ausentes no .env atual
php artisan system:update:env-sync --profile=production --write
```

Perfis disponíveis em `--profile`:

- `default`
- `production`
- `homolog`

Esse fluxo mantém o `.env` existente e só acrescenta parâmetros do updater que ainda não existem.

### Seed pós-update (comportamento padrão)

[](#seed-pós-update-comportamento-padrão)

Por padrão, após cada update o updater tenta executar **somente**:

```
php artisan db:seed --class=Database\Seeders\ReformaTributariaSeeder --force
```

Se a classe não existir na aplicação host, o updater apenas registra log e segue o pipeline.

As seeds padrão do sistema (`DatabaseSeeder`) **não** rodam por padrão. Para instalação inicial (zero), habilite explicitamente:

```
php artisan system:update:run --seed --install-seed-default --force
```

Ou via `.env`:

```
UPDATER_SEED_ALLOW_DEFAULT_DATABASE_SEEDER=true
```

Também é possível trocar a classe da seed específica:

```
UPDATER_SEED_REFORMA_TRIBUTARIA_SEEDER="Database\Seeders\ReformaTributariaSeeder"
```

CI e release
------------

[](#ci-e-release)

- CI valida matrix real: PHP 8.2/8.3/8.4 + Laravel 10/11/12.
- `release-after-ci.yml` cria tag automática após CI verde na `main` (evento `push`).
- Para evitar erro 403 no push de tag, configure o secret `RELEASE_TOKEN` com permissão de `contents:write` (fallback automático para `GITHUB_TOKEN`).
- Notificação Packagist usa `PACKAGIST_USERNAME` e `PACKAGIST_TOKEN` como secrets.

Segurança
---------

[](#segurança)

- Auth interna opcional (`updater.auth`) com SQLite do pacote.
- Sessão própria com cookie HttpOnly + SameSite=Lax + Secure quando HTTPS.
- 2FA TOTP nativo (6 dígitos, janela +-1 step).
- Rate limit de login por email+IP.
- Permissões granulares por usuário (acesso por módulo/ação), com exceção de usuário master.

### Usuário master + permissões por perfil

[](#usuário-master--permissões-por-perfil)

Defina no `.env` o usuário master que sempre terá acesso total, independente das permissões marcadas na UI:

```
UPDATER_UI_MASTER_EMAIL=wkarts@gmail.com
```

No menu `/_updater/users` você pode definir permissões específicas de cada usuário (dashboard, updates, backups, logs, fontes, perfis, usuários, settings etc.).

Comandos Artisan
----------------

[](#comandos-artisan)

```
php artisan system:update:check
php artisan system:update:run --force
php artisan system:update:rollback --force
php artisan system:update:status
```

Notificação de nova atualização (tag/release)
---------------------------------------------

[](#notificação-de-nova-atualização-tagrelease)

Habilite no `.env`:

```
UPDATER_NOTIFY_ENABLED=true
UPDATER_NOTIFY_TO=devops@empresa.com
UPDATER_TRIGGER_DRIVER=auto
```

Agende no `App\Console\Kernel` da aplicação host:

```
$schedule->command('system:update:notify')->hourly();
```

Regra de fonte/perfil ativo
---------------------------

[](#regra-de-fonteperfil-ativo)

Você pode cadastrar várias fontes e perfis, mas apenas **UMA fonte ativa** e **UM perfil ativo** devem ficar selecionados por vez para evitar conflitos.

Guia rápido de uso de fontes de atualização
-------------------------------------------

[](#guia-rápido-de-uso-de-fontes-de-atualização)

### 1) Cadastrar fonte

[](#1-cadastrar-fonte)

Na tela **Fontes** (`/_updater/sources`):

- Informe nome, tipo, URL e branch.
- Escolha autenticação (`none`, `token`, `ssh`).
- Para GitHub HTTPS privado, use autenticação com:

    - `auth_mode=token`
    - **Usuário**: `x-access-token` (ou seu usuário Git)
    - **Senha/Token**: seu PAT do GitHub
- Marque **Definir como fonte ativa** se quiser usar imediatamente.

> Você pode cadastrar várias fontes, mas apenas **uma** fica ativa por vez.

### 2) Editar e excluir fonte

[](#2-editar-e-excluir-fonte)

Na listagem de fontes:

- Botão **Editar** abre a própria tela com os campos preenchidos.
- Botão **Excluir** remove a fonte após confirmação.

### 3) Testar conexão real

[](#3-testar-conexão-real)

Na tela de fontes, use **Testar conexão real da fonte**. O teste executa `git ls-remote` para validar acesso e listar versões/tags remotas.

Guia de atualização (fluxo recomendado)
---------------------------------------

[](#guia-de-atualização-fluxo-recomendado)

1. Vá em **Atualizações** (`/_updater/updates`).
2. Selecione o perfil e a fonte.
3. Escolha o modo (`merge`, `ff-only`, `tag`, `full update` se habilitado).
4. Mantenha **Dry-run antes** marcado (padrão).
5. Clique em **Simular (Dry-run)**.
6. Na tela da execução, clique em **Aprovar e executar** e informe a senha de admin.

> O backup FULL é obrigatório antes da atualização real via UI.

Notificações de atualização (opcional)
--------------------------------------

[](#notificações-de-atualização-opcional)

As notificações são opcionais e aceitam múltiplos destinatários:

```
UPDATER_NOTIFY_ENABLED=true
UPDATER_NOTIFY_TO=devops@empresa.com,ti@empresa.com,owner@empresa.com
UPDATER_TRIGGER_DRIVER=auto
```

Também é aceito `;` como separador de e-mails.

Troubleshooting (erros mais comuns)
-----------------------------------

[](#troubleshooting-erros-mais-comuns)

### Erro: `Falha ao aplicar atualização: O updater só pode ser executado via CLI.`

[](#erro-falha-ao-aplicar-atualização-o-updater-só-pode-ser-executado-via-cli)

Causa comum:

- execução sincronizada disparada pela UI sem permitir contexto HTTP.

Como resolver:

1. Atualize para a versão mais recente do pacote (esta versão já trata o fluxo UI com `--allow-http`).
2. Confirme `UPDATER_TRIGGER_DRIVER=sync` (homologação) ou `queue` (produção).
3. Rode:

```
php artisan config:clear
php artisan cache:clear
```

---

### Erro no `composer install`: "The HOME or COMPOSER\_HOME environment variable must be set"

[](#erro-no-composer-install-the-home-or-composer_home-environment-variable-must-be-set)

Isso acontece quando o updater roda em um ambiente sem variáveis de usuário (muito comum em **cron**, **supervisor**ou quando o PHP é executado com um usuário sem shell).

✅ A partir desta versão, o updater faz **fallback automático**:

- define `HOME` quando não existe;
- define `COMPOSER_HOME` e `COMPOSER_CACHE_DIR` automaticamente;
- cria os diretórios necessários se não existirem.

Se você quiser forçar valores específicos (opcional), pode exportar antes de rodar o comando:

```
export HOME=/home/seu-usuario
export COMPOSER_HOME=/home/seu-usuario/.composer
php artisan system:update:run --force
```

---

Página de manutenção (503) e Whitelabel
---------------------------------------

[](#página-de-manutenção-503-e-whitelabel)

Durante uma atualização, o updater ativa o *maintenance mode* e exibe uma página 503 própria.

### Default (sem .env)

[](#default-sem-env)

Se você não configurar nada, o updater usa automaticamente a view padrão do pacote:

- `laravel-updater::maintenance`

### Whitelabel por painel (prioritário)

[](#whitelabel-por-painel-prioritário)

No painel `/_updater/settings` você pode configurar tudo pela UI:

- textos de manutenção;
- cor primária;
- upload de logo do painel, favicon do painel e logo exclusiva da manutenção;
- comportamento de primeira execução sem `.git`;
- entrada em manutenção no início da atualização.

Essas configurações salvas no painel têm prioridade em relação ao fallback de configuração do projeto.

### Fallback por `.env` (opcional)

[](#fallback-por-env-opcional)

Se você preferir não usar upload no painel, também pode apontar logo/ícone por URL:

```
UPDATER_BRAND_LOGO_URL=https://seu-dominio.com.br/assets/logo.png
UPDATER_BRAND_FAVICON_URL=https://seu-dominio.com.br/assets/favicon.ico
UPDATER_BRAND_PRIMARY_COLOR=#0d6efd
UPDATER_MAINTENANCE_LOGO_URL=https://seu-dominio.com.br/assets/logo-manutencao.png
```

Se existir upload no painel, ele tem prioridade sobre as URLs do `.env`.

Na tela de configurações de branding, os campos indicam claramente o que é cada ativo: logo do painel, favicon do painel e logo da manutenção.

### Controles manuais de manutenção

[](#controles-manuais-de-manutenção)

No dashboard há botões para habilitar/desabilitar manutenção imediatamente.

Critérios de segurança aplicados:

- confirmação obrigatória digitando `MANUTENCAO`;
- quando autenticação da UI está habilitada, a ação exige usuário com 2FA ativo.

Além disso, o updater adiciona automaticamente exceção de manutenção para o prefixo configurado em `UPDATER_UI_PREFIX` (ex.: `/_updater`), para que o painel continue acessível durante a janela de manutenção.

Em versões de Laravel que não suportam `php artisan down --except`, o updater faz fallback automático sem `--except` para não quebrar o fluxo de update/manutenção.

No modo de atualização por tag, se a aplicação já estiver exatamente na tag alvo, o updater trata como execução válida (sem falso erro por revisão inalterada).

Atualização de arquivos publicados (config/views)
-------------------------------------------------

[](#atualização-de-arquivos-publicados-configviews)

O Laravel não sobrescreve automaticamente arquivos publicados em `config/` e `resources/views/`. Se você publicou `config/updater.php` ou views e quer atualizar para a versão mais recente do pacote (atenção: isso pode sobrescrever alterações), rode:

```
php artisan vendor:publish --tag=updater-config --force
php artisan vendor:publish --tag=updater-views --force
```

### Erro: `.git` não é criado automaticamente

[](#erro-git-não-é-criado-automaticamente)

Checklist:

1. `UPDATER_GIT_AUTO_INIT=true`
2. `UPDATER_GIT_REMOTE_URL` preenchida e acessível
3. `UPDATER_GIT_PATH` aponta para a pasta correta e com permissão de escrita do usuário do PHP
4. `git` disponível no servidor (`git --version`)

### Não aparecem atualizações disponíveis, mas o teste de conexão da fonte funciona

[](#não-aparecem-atualizações-disponíveis-mas-o-teste-de-conexão-da-fonte-funciona)

Isso normalmente indica divergência entre:

- a **fonte ativa no painel** (usada no teste de conexão), e
- `UPDATER_GIT_PATH` local (usado para calcular revisão local/remota).

Valide:

1. pasta de `UPDATER_GIT_PATH` é o mesmo projeto conectado à fonte ativa;
2. branch da fonte ativa bate com `UPDATER_GIT_BRANCH`;
3. repositório local possui upstream correto (`origin/main` por exemplo);
4. execute `php artisan system:update:check` para comparar com o status da UI.

> Dica: por padrão, o updater **não bloqueia o CHECK** por working tree dirty (somente leitura). Se você quiser bloquear também, configure:

```
UPDATER_GIT_ALLOW_DIRTY_CHECK=false
```

### Solução para erro “Diretório atual não é um repositório git válido”

[](#solução-para-erro-diretório-atual-não-é-um-repositório-git-válido)

Se a aplicação não estiver na mesma pasta do updater, configure `UPDATER_GIT_PATH` com o diretório real do projeto Laravel versionado em Git.

Exemplo:

```
UPDATER_GIT_PATH=/home/seu-usuario/htdocs/seu-projeto
UPDATER_GIT_REMOTE=origin
UPDATER_GIT_BRANCH=main
```

Se você quer inicializar um diretório vazio automaticamente (cenário avançado), habilite:

```
UPDATER_GIT_AUTO_INIT=true
UPDATER_GIT_REMOTE_URL=https://github.com/org/repositorio.git
```

> Recomendado para produção: manter `UPDATER_GIT_AUTO_INIT=false` e usar um diretório já versionado.

> Quando houver uma **fonte ativa** no painel, o updater usa automaticamente a URL/branch dessa fonte para bootstrap git (com `UPDATER_GIT_AUTO_INIT=true`), sem exigir `UPDATER_GIT_REMOTE_URL` manualmente.

Após alterar variáveis do updater em produção, execute também:

```
php artisan config:clear
php artisan cache:clear
```

Migrador idempotente definitivo (`updater:migrate`)
---------------------------------------------------

[](#migrador-idempotente-definitivo-updatermigrate)

### Por que acontece o erro `SQLSTATE[42S01]` / errno `1050`

[](#por-que-acontece-o-erro-sqlstate42s01--errno-1050)

Esse erro indica que a migration tentou criar uma tabela/view que já existe no banco (`Base table or view already exists`). Em ambientes reais isso ocorre por drift entre o banco e a tabela `migrations` (dump restore, merge manual, execução parcial/interrompida, ou banco adiantado).

### Como a reconciliação evita a falha

[](#como-a-reconciliação-evita-a-falha)

O comando `updater:migrate` roda **exatamente uma migration por vez** e, quando a falha é classificada como `ALREADY_EXISTS` segura:

1. confere se a migration já está na tabela `migrations`;
2. se não estiver, reconcilia registrando a migration com batch correto;
3. para constraints, valida via `information_schema.TABLE_CONSTRAINTS/KEY_COLUMN_USAGE` (MySQL/MariaDB);
4. continua para a próxima migration.

No modo `strict`, qualquer dúvida de inferência/compatibilidade interrompe com erro orientando intervenção manual.

### Configuração

[](#configuração)

```
UPDATER_MIGRATE_IDEMPOTENT=true
UPDATER_MIGRATE_MODE=tolerant
UPDATER_MIGRATE_RETRY_LOCKS=2
UPDATER_MIGRATE_RETRY_SLEEP_BASE=3
UPDATER_MIGRATE_DRY_RUN=false
UPDATER_MIGRATE_LOG_CHANNEL=stack
UPDATER_MIGRATE_RECONCILE_ALREADY_EXISTS=true
UPDATER_MIGRATE_REPORT_PATH="storage/logs/updater-migrate-{timestamp}.log"
```

### Comandos

[](#comandos)

```
# execução real (tolerante)
php artisan updater:migrate --force

# modo estrito
php artisan updater:migrate --force --mode=strict

# dry-run (não executa SQL)
php artisan updater:migrate --force --dry-run
```

### Retry/backoff de lock/deadlock

[](#retrybackoff-de-lockdeadlock)

Para falhas `LOCK_RETRYABLE` (deadlock, lock wait timeout, metadata lock), o updater aplica retry com backoff progressivo (`retry_sleep_base * 2^(tentativa-1) + (tentativa-1)`), por exemplo base=3: `3s`, `7s`, `15s`.

### Quando usar modo strict

[](#quando-usar-modo-strict)

Use `strict` em ambientes novos/limpos, onde drift não é esperado. Em produção com histórico heterogêneo, `mode=tolerant` tende a reduzir falhas por objetos já existentes sem editar migrations antigas.

### Nota sobre manutenção whitelabel

[](#nota-sobre-manutenção-whitelabel)

A view `laravel-updater::maintenance` agora possui fallback seguro: se o armazenamento de branding não estiver acessível no momento do `artisan down --render`, ela renderiza com valores de config (`updater.app.*` e `updater.maintenance.*`) em vez de falhar. Isso evita o cenário em que a aplicação não entra corretamente em manutenção por erro de renderização da view.

### Caso idempotente adicional: DROP INDEX inexistente (MySQL errno 1091)

[](#caso-idempotente-adicional-drop-index-inexistente-mysql-errno-1091)

O migrador idempotente trata `Can't DROP ... check that column/key exists` (`errno 1091`) como drift idempotente no modo tolerante. Nesse caso, valida no `information_schema.STATISTICS` se o índice já está ausente, reconcilia a migration e segue o pipeline sem editar migrations antigas.

### Correção de entrada em manutenção (REQUEST\_URI no CLI)

[](#correção-de-entrada-em-manutenção-request_uri-no-cli)

Quando o host dispara erro `Undefined array key "REQUEST_URI"` durante `artisan down --render`, o updater agora injeta variáveis de servidor mínimas (`REQUEST_URI`, `HTTP_HOST`, `SERVER_NAME`, `SERVER_PORT`, `HTTPS`) no comando de manutenção. Com isso a aplicação volta a entrar em manutenção e exibir a view whitelabel do pacote.

### Caso idempotente adicional: tabela inexistente em DROP (SQLSTATE 42S02 / errno 1146)

[](#caso-idempotente-adicional-tabela-inexistente-em-drop-sqlstate-42s02--errno-1146)

O classificador considera `42S02/1146` como idempotente **somente** quando o SQL indica operação de remoção segura (`drop table`, `drop index`, `alter table ... drop`, etc.). Se for consulta/uso normal (`select`, `update`, etc.), permanece `NON_RETRYABLE` para não mascarar erro real.

### Correção definitiva para erro de `ENCRYPTION_KEY` no `route:cache`

[](#correção-definitiva-para-erro-de-encryption_key-no-routecache)

Em alguns projetos, providers/helpers consultam `ENCRYPTION_KEY` via `env()/getenv()` durante comandos Artisan. Em execução não-interativa do updater, isso pode falhar mesmo com chave no `.env`.

O `ShellRunner` do pacote agora preserva o ambiente do processo e também faz fallback de leitura do `.env` (chaves `ENCRYPTION_KEY` e `APP_KEY`) para o comando filho. Isso evita quebra no `cache_clear` por falso negativo de chave ausente.

### Tratamento de falha de `route:cache` por nome de rota duplicado

[](#tratamento-de-falha-de-routecache-por-nome-de-rota-duplicado)

Se o host tiver rotas com nomes duplicados, o Laravel lança `LogicException` no `route:cache`. O updater agora pode seguir o pipeline sem abortar o update: registra warning e executa `route:clear`.

Controle por `.env`:

```
UPDATER_CACHE_IGNORE_ROUTE_CACHE_DUPLICATE_NAME=true
```

### Healthcheck em localhost durante update

[](#healthcheck-em-localhost-durante-update)

Para evitar falso negativo em ambientes onde `APP_URL`/healthcheck fica em `localhost`, o updater ignora healthcheck local por padrão.

Controle por `.env`:

```
UPDATER_HEALTHCHECK_SKIP_LOCALHOST=true
```

Painel lateral técnico (novo)
-----------------------------

[](#painel-lateral-técnico-novo)

A barra superior de versões/hash foi removida da interface.

Agora, o updater exibe o resumo técnico em um card responsivo no menu lateral (abaixo da navegação), incluindo:

- nuvem conectada e status de credenciais,
- upload automático de backup,
- fonte e perfil ativos,
- status de serviços (cURL, OpenSSL, ZIP),
- versões relevantes (Laravel, updater e PHP),
- tag/hash git da aplicação alvo,
- usuário autenticado (nome, quando disponível),
- data/hora atual em tempo real.

Esse card foi desenhado para manter legibilidade em desktop e mobile sem poluição visual.

Upload em nuvem autocontido (Dropbox / Google Drive / S3 / MinIO)
-----------------------------------------------------------------

[](#upload-em-nuvem-autocontido-dropbox--google-drive--s3--minio)

O `laravel-updater` possui fluxo próprio de upload em nuvem para backups, sem depender de `Storage::disk(...)` da aplicação hospedeira.

### Configuração na UI

[](#configuração-na-ui)

Em `/_updater/settings` você encontra os campos específicos por provedor:

- **Dropbox**: Access Token;
- **Google Drive**: Client ID, Client Secret, Refresh Token e Folder ID opcional;
- **S3 / MinIO**: Endpoint, Region, Bucket, Access Key, Secret Key e Path-Style.

Também é possível definir:

- **provider** ativo,
- **prefix** remoto,
- **auto\_upload** (upload automático pós-backup).

### Comportamento

[](#comportamento)

- O backup local continua concluindo mesmo se o upload em nuvem falhar.
- Upload manual por item de backup continua disponível na seção de backups.
- Configurações de nuvem são persistidas em runtime no banco do updater (`updater_runtime_settings`).

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance85

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

178

Last Release

69d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9a45a6dc1bcd0b954ac294e631322870b06750a38946d3f96ab9b7d5239e8094?d=identicon)[wkarts](/maintainers/wkarts)

---

Top Contributors

[![wkarts](https://avatars.githubusercontent.com/u/57051272?v=4)](https://github.com/wkarts "wkarts (385 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/argws-laravel-updater/health.svg)

```
[![Health](https://phpackages.com/badges/argws-laravel-updater/health.svg)](https://phpackages.com/packages/argws-laravel-updater)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[flarum/core

Delightfully simple forum software.

211.3M1.9k](/packages/flarum-core)[orchestra/canvas

Code Generators for Laravel Applications and Packages

20917.2M158](/packages/orchestra-canvas)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[illuminate/session

The Illuminate Session package.

9937.4M753](/packages/illuminate-session)[laragear/preload

Effortlessly make a Preload script for your Laravel application.

119363.5k](/packages/laragear-preload)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
