Repository: salahhusa9/laravel-updater
Branch: main
Commit: ab7fb4c20bd9
Files: 63
Total size: 82.3 KB
Directory structure:
gitextract_joqugs2b/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ └── config.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── dependabot-auto-merge.yml
│ ├── deploy-docs.yml
│ ├── fix-php-code-style-issues.yml
│ ├── run-tests.yml
│ └── update-changelog.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── config/
│ └── updater.php
├── database/
│ └── factories/
│ └── ModelFactory.php
├── phpunit.xml.dist
├── renovate.json
├── resources/
│ └── views/
│ └── .gitkeep
├── src/
│ ├── Commands/
│ │ ├── CheckCommand.php
│ │ └── UpdaterCommand.php
│ ├── Contracts/
│ │ ├── Pipeline.php
│ │ └── Repository.php
│ ├── Events/
│ │ ├── NewVersionAvailable.php
│ │ ├── UpdateFailed.php
│ │ └── UpdatedSuccessfully.php
│ ├── Exceptions/
│ │ ├── GitFailedException.php
│ │ └── GithubConfigException.php
│ ├── Facades/
│ │ └── Updater.php
│ ├── Helpers/
│ │ ├── Git.php
│ │ └── Helper.php
│ ├── Pipelines/
│ │ ├── ArtisanCallCacheClearPipe.php
│ │ ├── ArtisanCallConfigClearPipe.php
│ │ ├── ArtisanCallMigratePipe.php
│ │ ├── ArtisanCallOptimizePipe.php
│ │ ├── ArtisanCallRouteClearPipe.php
│ │ ├── ArtisanCallViewClearPipe.php
│ │ ├── GitPipe.php
│ │ └── SeedersPipe.php
│ ├── RepositorySource/
│ │ └── GithubRepository.php
│ ├── Updater.php
│ └── UpdaterServiceProvider.php
├── tests/
│ ├── ArchTest.php
│ ├── Commands/
│ │ ├── CheckCommandTest.php
│ │ └── UpdaterCommandTest.php
│ ├── ExampleTest.php
│ ├── GitTest.php
│ ├── HelperTest.php
│ ├── Pest.php
│ ├── Pipelines/
│ │ ├── ArtisanCallCacheClearPipeTest.php
│ │ ├── ArtisanCallConfigClearPipeTest.php
│ │ ├── ArtisanCallMigratePipeTest.php
│ │ ├── ArtisanCallOptimizePipeTest.php
│ │ ├── ArtisanCallRouteClearPipeTest.php
│ │ ├── ArtisanCallViewClearPipeTest.php
│ │ ├── GitPipeTest.php
│ │ └── SeedersPipeTest.php
│ ├── RepositorySource/
│ │ └── GithubRepositoryTest.php
│ ├── TestCase.php
│ └── UpdaterTest.php
└── workbench/
└── app/
└── Providers/
└── WorkbenchServiceProvider.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
================================================
FILE: .gitattributes
================================================
# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# Ignore all test and documentation with "export-ignore".
/.github export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpunit.xml.dist export-ignore
/art export-ignore
/docs export-ignore
/tests export-ignore
/workbench export-ignore
/.editorconfig export-ignore
/.php_cs.dist.php export-ignore
/psalm.xml export-ignore
/psalm.xml.dist export-ignore
/testbench.yaml export-ignore
/UPGRADING.md export-ignore
/phpstan.neon.dist export-ignore
/phpstan-baseline.neon export-ignore
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: [salahhusa9]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
================================================
FILE: .github/ISSUE_TEMPLATE/bug.yml
================================================
name: Bug Report
description: Report an Issue or Bug with the Package
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
We're sorry to hear you have a problem. Can you help us solve it by providing the following details.
- type: textarea
id: what-happened
attributes:
label: What happened?
description: What did you expect to happen?
placeholder: I cannot currently do X thing because when I do, it breaks X thing.
validations:
required: true
- type: textarea
id: how-to-reproduce
attributes:
label: How to reproduce the bug
description: How did this occur, please add any config values used and provide a set of reliable steps if possible.
placeholder: When I do X I see Y.
validations:
required: true
- type: input
id: package-version
attributes:
label: Package Version
description: What version of our Package are you running? Please be as specific as possible
placeholder: 2.0.0
validations:
required: true
- type: input
id: php-version
attributes:
label: PHP Version
description: What version of PHP are you running? Please be as specific as possible
placeholder: 8.2.0
validations:
required: true
- type: input
id: laravel-version
attributes:
label: Laravel Version
description: What version of Laravel are you running? Please be as specific as possible
placeholder: 9.0.0
validations:
required: true
- type: dropdown
id: operating-systems
attributes:
label: Which operating systems does with happen with?
description: You may select more than one.
multiple: true
options:
- macOS
- Windows
- Linux
- type: textarea
id: notes
attributes:
label: Notes
description: Use this field to provide any other notes that you feel might be relevant to the issue.
validations:
required: false
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Ask a question
url: https://github.com/salahhusa9/laravel-updater/discussions/new?category=q-a
about: Ask the community for help
- name: Request a feature
url: https://github.com/salahhusa9/laravel-updater/discussions/new?category=ideas
about: Share ideas for new features
- name: Report a security issue
url: https://github.com/salahhusa9/laravel-updater/security/policy
about: Learn how to notify us for sensitive bugs
================================================
FILE: .github/dependabot.yml
================================================
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependencies"
================================================
FILE: .github/workflows/dependabot-auto-merge.yml
================================================
name: dependabot-auto-merge
on: pull_request_target
permissions:
pull-requests: write
contents: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2.5.0
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Auto-merge Dependabot PRs for semver-minor updates
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Auto-merge Dependabot PRs for semver-patch updates
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
================================================
FILE: .github/workflows/deploy-docs.yml
================================================
# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Deploy Docs site to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["docs"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect package manager
id: detect-package-manager
run: |
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
echo "manager=yarn" >> $GITHUB_OUTPUT
echo "command=install" >> $GITHUB_OUTPUT
echo "runner=yarn" >> $GITHUB_OUTPUT
exit 0
elif [ -f "${{ github.workspace }}/package.json" ]; then
echo "manager=npm" >> $GITHUB_OUTPUT
echo "command=ci" >> $GITHUB_OUTPUT
echo "runner=npx --no-install" >> $GITHUB_OUTPUT
exit 0
else
echo "Unable to determine package manager"
exit 1
fi
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: "22"
cache: ${{ steps.detect-package-manager.outputs.manager }}
# - name: Setup Pages
# uses: actions/configure-pages@v3
# with:
# # Automatically inject basePath in your Next.js configuration file and disable
# # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized).
# #
# # You may remove this line if you want to manage the configuration yourself.
# static_site_generator: next
- name: Restore cache
uses: actions/cache@v4
with:
path: |
.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-
- name: Install dependencies
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
- name: Build with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next build
- name: Static HTML export with Next.js
run: ${{ steps.detect-package-manager.outputs.runner }} next export
- name: Upload artifact
uses: actions/upload-pages-artifact@v4
with:
path: ./out
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .github/workflows/fix-php-code-style-issues.yml
================================================
name: Fix PHP code style issues
on:
push:
paths:
- '**.php'
permissions:
contents: write
jobs:
php-code-styling:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Fix PHP code style issues
uses: aglipanci/laravel-pint-action@2.6
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: Fix styling
================================================
FILE: .github/workflows/run-tests.yml
================================================
name: run-tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest, windows-latest]
# php: [8.1, 8.2]
laravel: [10.*, 11.*, 12.*]
stability: [prefer-lowest, prefer-stable]
include:
- laravel: 10.*
testbench: 8.*
php: 8.1
- laravel: 11.*
testbench: 9.*
php: 8.2
- laravel: 12.*
testbench: 10.*
php: 8.3
name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo
coverage: none
- name: Setup problem matchers
run: |
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction
- name: List Installed Dependencies
run: composer show -D
- name: Execute tests
run: vendor/bin/pest --ci
================================================
FILE: .github/workflows/update-changelog.yml
================================================
name: "Update Changelog"
on:
release:
types: [released]
permissions:
contents: write
jobs:
update:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: main
- name: Update Changelog
uses: stefanzweifel/changelog-updater-action@v1
with:
latest-version: ${{ github.event.release.name }}
release-notes: ${{ github.event.release.body }}
- name: Commit updated CHANGELOG
uses: stefanzweifel/git-auto-commit-action@v7
with:
branch: main
commit_message: Update CHANGELOG
file_pattern: CHANGELOG.md
================================================
FILE: .gitignore
================================================
.idea
.phpunit.cache
build
composer.lock
coverage
docs
phpunit.xml
phpstan.neon
testbench.yaml
vendor
node_modules
.next
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to `laravel-updater` will be documented in this file.
## v1.3.0 - 2025-04-01
### What's Changed
* Bump aglipanci/laravel-pint-action from 2.4 to 2.5 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/62
* Update dependency illuminate/contracts to **v12** by @renovate in https://github.com/salahhusa9/laravel-updater/pull/63
* Update dependency node to v22 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/65
* chore(deps): update dependency orchestra/testbench to v10 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/64
> Thank you for using this package! ❤️
Consider supporting my work:
https://github.com/sponsors/salahhusa9
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.2.4...v1.3.0
## v1.2.4 - 2025-01-27
### What's Changed
* Update dependabot/fetch-metadata action to v2.3.0 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/58
* Update Updater.php to merge before and after update pipelines with existing pipelines by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/60
Thank you for using this package! ❤️
Consider supporting my work:
https://github.com/sponsors/salahhusa9
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.2.3...v1.2.4
## v1.2.3 - 2024-07-17
### What's Changed
* Update dependabot/fetch-metadata action to v2.2.0 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/52
* [Add sponsor message and link in Update Command](https://github.com/sponsors/salahhusa9)
> Thank you for using this package! ❤️
Consider supporting my work:
https://github.com/sponsors/salahhusa9
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.2.2...v1.2.3
## v1.2.2 - 2024-06-25
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.2.1...v1.2.2
## v1.2.1 - 2024-06-08
### What's Changed
* Update laravel in github action by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/44
* Bump aglipanci/laravel-pint-action from 2.3.1 to 2.4 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/45
* Update dependabot/fetch-metadata action to v2.1.0 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/46
* Remove symfony component process executable finder by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/50
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.2.0...v1.2.1
## v1.2.0 - 2024-04-01
### What's Changed
* Git checkout throw away local modifications by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/43
* Update dependency orchestra/testbench to v9 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/39
* Update dependabot/fetch-metadata action to v1.7.0 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/40
* Update dependabot/fetch-metadata action to v2 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/41
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.1.0...v1.2.0
## v1.1.0 - 2024-03-12
### What's Changed
* Add support of Laravel 11 by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/38
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.0.2...v1.1.0
## v1.0.2 - 2024-02-10
### What's Changed
* new ui output by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/37
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.0.1...v1.0.2
## v1.0.1 - 2024-02-03
### What's Changed
* Update actions/upload-pages-artifact action to v3 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/28
* Update actions/deploy-pages action to v4 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/27
* Bump aglipanci/laravel-pint-action from 2.3.0 to 2.3.1 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/30
* remove migration file and in configure Package by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/36
* Bump actions/cache from 3 to 4 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/32
* [Update exception classes to use RuntimeException instead of Exception](https://github.com/salahhusa9/laravel-updater/commit/705485c97efaa161da81b3cc825e2b20c1f43d6f)
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v1.0.0...v1.0.1
## Laravel Updater v1 - 2023-11-21
### What's Changed
- Update actions/setup-node action to v4 by @renovate in https://github.com/salahhusa9/laravel-updater/pull/14
- Git failed exception by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/17
- Tests pipelines by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/18
- Tests Repository Source by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/19
- Command test by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/20
- updater facade tests by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/21
- Remove Git Pull in update by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/22
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/compare/v0.0.1...v1.0.0
## Laravel Updater Beta - 2023-10-31
### What's Changed
- Bump aglipanci/laravel-pint-action from 2.2.0 to 2.3.0 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/1
- Patch 1 by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/5
- Pipelines by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/6
- Configure Renovate by @renovate in https://github.com/salahhusa9/laravel-updater/pull/4
- Bump stefanzweifel/git-auto-commit-action from 4 to 5 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/2
- Bump actions/checkout from 3 to 4 by @dependabot in https://github.com/salahhusa9/laravel-updater/pull/3
- Interface pipeline by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/10
- Fun docs by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/11
- Test by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/12
- Output in run by @salahhusa9 in https://github.com/salahhusa9/laravel-updater/pull/13
### New Contributors
- @dependabot made their first contribution in https://github.com/salahhusa9/laravel-updater/pull/1
- @salahhusa9 made their first contribution in https://github.com/salahhusa9/laravel-updater/pull/5
- @renovate made their first contribution in https://github.com/salahhusa9/laravel-updater/pull/4
**Full Changelog**: https://github.com/salahhusa9/laravel-updater/commits/v0.0.1
================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)
Copyright (c) salahhusa9 <salahhusa9@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# Laravel Updater
[](https://packagist.org/packages/salahhusa9/laravel-updater)

[](https://github.com/salahhusa9/laravel-updater/actions?query=workflow%3Arun-tests+branch%3Amain)
[](https://github.com/salahhusa9/laravel-updater/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain)
[](https://packagist.org/packages/salahhusa9/laravel-updater)
This is a useful package for update your laravel project with one command/click.
## Support us
You can support us by [buying me a coffee](https://github.com/sponsors/salahhusa9) ☕️ .
<!-- docs in salahhusa9.Com/laravel-updater -->
## Docs
You find the **docs** in [salahhusa9.com/laravel-updater](https://salahhusa9.com/laravel-updater)
## Testing
```bash
composer test
```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## Contributing
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
## Security Vulnerabilities
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
## Credits
- [salahhusa9](https://github.com/salahhusa9)
- [All Contributors](../../contributors)
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
================================================
FILE: composer.json
================================================
{
"name": "salahhusa9/laravel-updater",
"description": "Laravel Updater is a simple yet powerful package for updater your Laravel applications. It makes it easy to upgrade your application to the latest version with just one command.",
"keywords": [
"salahhusa9",
"laravel",
"laravel-updater",
"laravel package",
"laravel self updater",
"laravel package self updater",
"laravel package updater",
"laravel package update",
"laravel package update itself"
],
"homepage": "https://github.com/salahhusa9/laravel-updater",
"license": "MIT",
"authors": [
{
"name": "salahhusa9",
"email": "salahhusa9@gmail.com",
"role": "Developer"
}
],
"require": {
"php": "^8.1|^8.2",
"guzzlehttp/guzzle": "^7.8",
"illuminate/contracts": "^10.0|^11.0|^12.0",
"spatie/laravel-package-tools": "^1.0",
"symfony/process": "^6.3|^7.0"
},
"require-dev": {
"laravel/pint": "^1.0",
"nunomaduro/collision": "^7.8|^8.0",
"orchestra/testbench": "10.1.0",
"pestphp/pest": "^2.20|^3.0",
"pestphp/pest-plugin-arch": "^2.0|^3.0",
"pestphp/pest-plugin-laravel": "^2.0|^3.0"
},
"autoload": {
"psr-4": {
"Salahhusa9\\Updater\\": "src/",
"Salahhusa9\\Updater\\Database\\Factories\\": "database/factories/"
}
},
"autoload-dev": {
"psr-4": {
"Salahhusa9\\Updater\\Tests\\": "tests/",
"Workbench\\App\\": "workbench/app/"
}
},
"scripts": {
"post-autoload-dump": "@composer run prepare",
"clear": "@php vendor/bin/testbench package:purge-laravel-updater --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"build": [
"@composer run prepare",
"@php vendor/bin/testbench workbench:build --ansi"
],
"start": [
"Composer\\Config::disableProcessTimeout",
"@composer run build",
"@php vendor/bin/testbench serve"
],
"test": "vendor/bin/pest",
"test-coverage": "vendor/bin/pest --coverage",
"format": "vendor/bin/pint"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true
}
},
"extra": {
"laravel": {
"providers": [
"Salahhusa9\\Updater\\UpdaterServiceProvider"
],
"aliases": {
"Updater": "Salahhusa9\\Updater\\Facades\\Updater"
}
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
================================================
FILE: config/updater.php
================================================
<?php
// config for Salahhusa9/Updater
return [
'git_path' => 'git',
'repository_source' => \Salahhusa9\Updater\RepositorySource\GithubRepository::class,
'github_token' => env('GITHUB_TOKEN'),
'github_username' => env('GITHUB_USERNAME'),
'github_repository' => env('GITHUB_REPOSITORY'),
'github_timeout' => 100,
'maintenance_mode' => true,
'maintenance_mode_secret' => env('MAINTENANCE_MODE_SECRET', false),
'before_update_pipelines' => [
// you can add your own pipelines here
],
// run php artisan migrate after update?
'migrate' => false,
// run seeders after update?
'seeders' => [
// '\Database\Seeders\DatabaseSeeder::class',
],
// run php artisan cache:clear after update?
'cache:clear' => false,
// run php artisan view:clear after update?
'view:clear' => false,
// run php artisan config:clear after update?
'config:clear' => false,
// run php artisan route:clear after update?
'route:clear' => false,
// run php artisan optimize after update?
'optimize' => false,
'after_update_pipelines' => [
// you can add your own pipelines here
],
];
================================================
FILE: database/factories/ModelFactory.php
================================================
<?php
namespace Salahhusa9\Updater\Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/*
class ModelFactory extends Factory
{
protected $model = YourModel::class;
public function definition()
{
return [
];
}
}
*/
================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.2/phpunit.xsd"
backupGlobals="false"
bootstrap="vendor/autoload.php"
colors="true"
processIsolation="false"
stopOnFailure="false"
executionOrder="random"
failOnWarning="true"
failOnRisky="true"
failOnEmptyTestSuite="true"
beStrictAboutOutputDuringTests="true"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
>
<testsuites>
<testsuite name="Salahhusa9 Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage>
<report>
<html outputDirectory="build/coverage"/>
<text outputFile="build/coverage.txt"/>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>
<logging>
<junit outputFile="build/report.junit.xml"/>
</logging>
<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>
</phpunit>
================================================
FILE: renovate.json
================================================
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}
================================================
FILE: resources/views/.gitkeep
================================================
================================================
FILE: src/Commands/CheckCommand.php
================================================
<?php
namespace Salahhusa9\Updater\Commands;
use Illuminate\Console\Command;
use Salahhusa9\Updater\Events\NewVersionAvailable;
use Salahhusa9\Updater\Facades\Updater;
class CheckCommand extends Command
{
public $signature = 'updater:check';
public $description = 'Check for new versions';
public function handle(): int
{
$newVersionAvailable = Updater::newVersionAvailable();
if (! is_array($newVersionAvailable)) {
$this->components->info('No new version available');
return self::SUCCESS;
}
$this->components->info('New version available: '.$newVersionAvailable['latest_version']);
event(new NewVersionAvailable($newVersionAvailable['current_version'], $newVersionAvailable['latest_version']));
return self::SUCCESS;
}
}
================================================
FILE: src/Commands/UpdaterCommand.php
================================================
<?php
namespace Salahhusa9\Updater\Commands;
use Illuminate\Console\Command;
use Salahhusa9\Updater\Facades\Updater;
class UpdaterCommand extends Command
{
public $signature = 'updater:update';
public $description = 'Update the application';
public function handle(): int
{
$newVersionAvailable = Updater::newVersionAvailable();
if (! is_array($newVersionAvailable)) {
$this->components->error('No new version available');
return self::FAILURE;
}
$this->components->info('Updating to version '.$newVersionAvailable['latest_version']);
Updater::update(output: function ($message) {
$this->components->task($message);
});
$this->components->twoColumnDetail('Application updated', Updater::getCurrentVersion());
$this->components->info('
Thank you for using this package! ❤️
Consider supporting my work:
https://github.com/sponsors/salahhusa9
');
return self::SUCCESS;
}
}
================================================
FILE: src/Contracts/Pipeline.php
================================================
<?php
namespace Salahhusa9\Updater\Contracts;
interface Pipeline
{
public function handle($content, \Closure $next);
}
================================================
FILE: src/Contracts/Repository.php
================================================
<?php
namespace Salahhusa9\Updater\Contracts;
interface Repository
{
public function getLatestVersion(): string;
public function getLatestVersionData(): \Illuminate\Support\Collection;
public function getVersions(): array;
public function getVersionsData(): \Illuminate\Support\Collection;
}
================================================
FILE: src/Events/NewVersionAvailable.php
================================================
<?php
namespace Salahhusa9\Updater\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewVersionAvailable
{
use Dispatchable, SerializesModels;
public $currentVersion;
public $newVersion;
public function __construct($currentVersion, $newVersion)
{
$this->currentVersion = $currentVersion;
$this->newVersion = $newVersion;
}
}
================================================
FILE: src/Events/UpdateFailed.php
================================================
<?php
namespace Salahhusa9\Updater\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UpdateFailed
{
use Dispatchable, SerializesModels;
public $pastVersion;
public $newVersion;
public $exception;
public function __construct($pastVersion, $newVersion, $exception)
{
$this->pastVersion = $pastVersion;
$this->newVersion = $newVersion;
$this->exception = $exception;
}
}
================================================
FILE: src/Events/UpdatedSuccessfully.php
================================================
<?php
namespace Salahhusa9\Updater\Events;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UpdatedSuccessfully
{
use Dispatchable, SerializesModels;
public $pastVersion;
public $newVersion;
public function __construct($pastVersion, $newVersion)
{
$this->pastVersion = $pastVersion;
$this->newVersion = $newVersion;
}
}
================================================
FILE: src/Exceptions/GitFailedException.php
================================================
<?php
namespace Salahhusa9\Updater\Exceptions;
use RuntimeException;
class GitFailedException extends RuntimeException
{
/**
* GitFailedException constructor.
*
* @param string $message
*/
public function __construct($message)
{
parent::__construct($message);
}
}
================================================
FILE: src/Exceptions/GithubConfigException.php
================================================
<?php
namespace Salahhusa9\Updater\Exceptions;
use RuntimeException;
class GithubConfigException extends RuntimeException
{
/**
* GithubConfigException constructor.
*
* @param string $message
*/
public function __construct($message)
{
parent::__construct($message);
}
}
================================================
FILE: src/Facades/Updater.php
================================================
<?php
namespace Salahhusa9\Updater\Facades;
use Illuminate\Support\Facades\Facade;
/**
* @see \Salahhusa9\Updater\Updater
*
* @method static string update() Update the application to the latest version
* @method static array newVersionAvailable() Check if a new version is available
* @method static string getLatestVersion() Get the latest version
* @method static string getCurrentVersion() Get the current version
* @method static array getLatestVersionData() Get the latest version data
* @method static string versions() Get all versions
*/
class Updater extends Facade
{
protected static function getFacadeAccessor()
{
return \Salahhusa9\Updater\Updater::class;
}
}
================================================
FILE: src/Helpers/Git.php
================================================
<?php
namespace Salahhusa9\Updater\Helpers;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Exceptions\GitFailedException;
class Git
{
/**
* getCurrentCommit
*
* @return string
*
* @throws GitFailedException
*/
public static function getCurrentCommit()
{
$process = Process::run(self::gitPath().' log --pretty="%h" -n1 HEAD');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* getCurrentBranch
*
* @return string
*
* @throws GitFailedException
*/
public static function getCurrentBranch()
{
$process = Process::run(self::gitPath().' rev-parse --abbrev-ref HEAD');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* getCurrentTag
*
* @return string
*
* @throws GitFailedException
*/
public static function getCurrentTag()
{
$process = Process::run(self::gitPath().' describe --tags --abbrev=0');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* auth
*
* @return string
*
* @throws GitFailedException
*/
public static function auth()
{
$process = Process::run(self::gitPath().' remote set-url origin https://'.config('updater.github_username').':'.config('updater.github_token').'@github.com/'.config('updater.github_username').'/'.config('updater.github_repository').'.git');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* pull
*
* @return string
*
* @throws GitFailedException
*/
public static function pull()
{
$process = Process::run(self::gitPath().' pull');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* checkout
*
* @param mixed $branch
* @return string
*
* @throws GitFailedException
*/
public static function checkout($branch)
{
$process = Process::run(self::gitPath().' checkout '.$branch.' -f');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* fetch
*
* @return string
*
* @throws GitFailedException
*/
public static function fetch()
{
$process = Process::run(self::gitPath().' fetch');
if ($process->failed()) {
throw new GitFailedException('this command failed: '.$process->command().' with message: '.$process->errorOutput());
}
return trim($process->output());
}
/**
* gitPath
*
* @return string
*/
public static function gitPath()
{
$gitPath = config('updater.git_path', 'git');
return $gitPath;
}
}
================================================
FILE: src/Helpers/Helper.php
================================================
<?php
namespace Salahhusa9\Updater\Helpers;
class Helper
{
/**
* isVersion
*
* @param mixed $version
*/
public function isVersion($version): int|false
{
$pattern = '/^v(\d+\.\d+\.\d+)(-[a-zA-Z0-9]+(\.\d+)?)?$/';
return preg_match($pattern, $version);
}
}
================================================
FILE: src/Pipelines/ArtisanCallCacheClearPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallCacheClearPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start clearing cache');
}
Artisan::call('cache:clear');
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Cache cleared!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/ArtisanCallConfigClearPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallConfigClearPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start clearing config cache');
}
Artisan::call('config:clear');
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Config cache cleared!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/ArtisanCallMigratePipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallMigratePipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start migrating');
}
Artisan::call('migrate', [
'--force' => true,
]);
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Migrated!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/ArtisanCallOptimizePipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallOptimizePipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start optimizing');
}
Artisan::call('optimize');
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Optimized!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/ArtisanCallRouteClearPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallRouteClearPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start clearing route cache');
}
Artisan::call('route:clear');
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Route cache cleared!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/ArtisanCallViewClearPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class ArtisanCallViewClearPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start clearing view cache');
}
Artisan::call('view:clear');
if (is_callable($content['output'])) {
call_user_func($content['output'], 'View cache cleared!');
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/GitPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Salahhusa9\Updater\Contracts\Pipeline;
use Salahhusa9\Updater\Facades\Updater;
use Salahhusa9\Updater\Helpers\Git;
class GitPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
$version = $content['new_version'];
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start downloading version '.$version);
}
Git::auth();
Git::fetch();
$checkout = Git::checkout($version);
if ($checkout != 'TEST' and Updater::getCurrentVersion() != $version) {
if (is_callable($content['output'])) {
call_user_func($content['output'], 'git checkout failed: '.$checkout);
}
throw new \RuntimeException('git checkout failed: '.$checkout);
} else {
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Checkout success');
}
}
return $next($content);
}
}
================================================
FILE: src/Pipelines/SeedersPipe.php
================================================
<?php
namespace Salahhusa9\Updater\Pipelines;
use Closure;
use Illuminate\Support\Facades\Artisan;
use Salahhusa9\Updater\Contracts\Pipeline;
class SeedersPipe implements Pipeline
{
/**
* handle
*
* @param array $content
* @param mixed $next
* @return void
*/
public function handle($content, Closure $next)
{
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Start seeding');
}
$classes = config('updater.seeders', []);
foreach ($classes as $class) {
Artisan::call('db:seed', [
'--class' => $class,
'--force' => true,
]);
}
if (is_callable($content['output'])) {
call_user_func($content['output'], 'Seeded!');
}
return $next($content);
}
}
================================================
FILE: src/RepositorySource/GithubRepository.php
================================================
<?php
namespace Salahhusa9\Updater\RepositorySource;
use Illuminate\Support\Facades\Http;
use Salahhusa9\Updater\Contracts\Repository;
use Salahhusa9\Updater\Exceptions\GithubConfigException;
class GithubRepository implements Repository
{
/**
* getLatestVersion
*/
public function getLatestVersion(): string
{
$this->checkConfig();
return isset($this->getLatestVersionData()['message']) ? throw new \Exception($this->getLatestVersionData()['message']) : $this->getLatestVersionData()['tag_name'];
}
/**
* getLatestVersionData
*
* @return Illuminate\Support\Collection
*/
public function getLatestVersionData(): \Illuminate\Support\Collection
{
$this->checkConfig();
$response = Http::withHeaders([
'Accept' => 'application/vnd.github.v3+json',
'Authorization' => 'Bearer '.config('updater.github_token'),
'X-GitHub-Api-Version' => '2022-11-28',
])
->timeout(config('updater.github_timeout', 100))
->get('https://api.github.com/repos/'.config('updater.github_username').'/'.config('updater.github_repository').'/releases/latest');
return $response->collect();
}
/**
* getVersions
*/
public function getVersions(): array
{
$this->checkConfig();
$versionsData = $this->getVersionsData();
if (isset($versionsData['message'])) {
throw new \Exception($versionsData['message']);
}
return $versionsData->map(function ($version) {
return $version['tag_name'];
})->toArray();
}
/**
* getVersionsData
*
* @return Illuminate\Support\Collection
*/
public function getVersionsData(): \Illuminate\Support\Collection
{
$this->checkConfig();
$response = Http::withHeaders([
'Accept' => 'application/vnd.github.v3+json',
'Authorization' => 'Bearer '.config('updater.github_token'),
'X-GitHub-Api-Version' => '2022-11-28',
])
->timeout(config('updater.github_timeout', 100))
->get('https://api.github.com/repos/'.config('updater.github_username').'/'.config('updater.github_repository').'/releases');
return $response->collect();
}
/**
* checkConfig
*
* @return void
*/
public function checkConfig()
{
if (config('updater.github_token') == null) {
throw new GithubConfigException('Please set GITHUB_TOKEN in .env file');
}
if (config('updater.github_username') == null) {
throw new GithubConfigException('Please set GITHUB_USERNAME in .env file');
}
if (config('updater.github_repository') == null) {
throw new GithubConfigException('Please set GITHUB_REPOSITORY in .env file');
}
return true;
}
}
================================================
FILE: src/Updater.php
================================================
<?php
namespace Salahhusa9\Updater;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Pipeline;
use Salahhusa9\Updater\Contracts\Repository;
use Salahhusa9\Updater\Helpers\Git;
class Updater
{
private $output;
/**
* update
*/
public function update(?callable $output = null): string
{
if (! is_null($output) and ! is_callable($output)) {
throw new \RuntimeException('Output must be callable');
}
$this->output = $output;
if (is_array($this->newVersionAvailable())) {
return $this->updateTo($this->getLatestVersion());
} else {
return 'No new version available';
}
}
/**
* updateTo
*
* @param mixed $version
*/
private function updateTo($version): string
{
if (is_array($this->newVersionAvailable()) && $this->newVersionAvailable()['current_version'] != $version) {
$current_version_in_past = $this->newVersionAvailable()['current_version'];
try {
if (config('updater.maintenance_mode', false)) {
$this->output('Maintenance mode is on, turning it on');
Artisan::call(
'down',
config('updater.maintenance_mode_secret', false) ? [
'--secret' => config('updater.maintenance_mode_secret', false),
] : []
);
}
$pipelines = [
Pipelines\GitPipe::class,
];
if (config('updater.before_update_pipelines', false) && is_array(config('updater.before_update_pipelines')) && count(config('updater.before_update_pipelines')) > 0) {
$pipelines = array_merge($pipelines, config('updater.before_update_pipelines'));
}
if (config('updater.migrate', false)) {
$pipelines[] = Pipelines\ArtisanCallMigratePipe::class;
}
if (config('updater.seeders', false) && is_array(config('updater.seeders')) && count(config('updater.seeders')) > 0) {
$pipelines[] = Pipelines\SeedersPipe::class;
}
if (config('updater.cache:clear', false)) {
$pipelines[] = Pipelines\ArtisanCallCacheClearPipe::class;
}
if (config('updater.view:clear', false)) {
$pipelines[] = Pipelines\ArtisanCallViewClearPipe::class;
}
if (config('updater.config:clear', false)) {
$pipelines[] = Pipelines\ArtisanCallConfigClearPipe::class;
}
if (config('updater.route:clear', false)) {
$pipelines[] = Pipelines\ArtisanCallRouteClearPipe::class;
}
if (config('updater.optimize', false)) {
$pipelines[] = Pipelines\ArtisanCallOptimizePipe::class;
}
if (config('updater.after_update_pipelines', false) && is_array(config('updater.after_update_pipelines')) && count(config('updater.after_update_pipelines')) > 0) {
$pipelines = array_merge($pipelines, config('updater.after_update_pipelines'));
}
// check if pipelines is array and not empty and items is implemented Pipeline contract
if (is_array($pipelines) && count($pipelines) > 0) {
foreach ($pipelines as $pipeline) {
if (! is_subclass_of($pipeline, \Salahhusa9\Updater\Contracts\Pipeline::class)) {
throw new \RuntimeException('Pipeline '.$pipeline.' is not implemented Pipeline contract:'.\Salahhusa9\Updater\Contracts\Pipeline::class);
}
}
} else {
throw new \RuntimeException('Pipelines is not array or empty');
}
$this->output('Start Updating to version '.$version);
Pipeline::send([
'current_version' => $this->getCurrentVersion(),
'new_version' => $version,
'output' => $this->output,
])
->through($pipelines)
->then(
function ($content) {
return $content;
}
);
if (config('updater.maintenance_mode', false)) {
$this->output('Maintenance mode is on, turning it off');
Artisan::call('up');
}
event(new Events\UpdatedSuccessfully($current_version_in_past, $version));
return 'Updated to version '.$version;
} catch (\Throwable $th) {
if (config('updater.maintenance_mode', false)) {
$this->output('Maintenance mode is on, turning it off');
Artisan::call('up');
}
event(new Events\UpdateFailed($current_version_in_past, $version, $th->getMessage()));
throw $th;
}
} else {
$this->output('No new version available');
return 'No new version available';
}
}
/**
* output
*
* @param mixed $message
*/
public function output($message): void
{
if (is_callable($this->output)) {
call_user_func($this->output, $message);
}
}
/**
* newVersionAvailable
*
* @return bool
*/
public function newVersionAvailable(): bool|array
{
$currentVersion = $this->getCurrentVersion();
$latestVersion = $this->getLatestVersion();
if ($currentVersion != $latestVersion) {
return [
'current_version' => $currentVersion,
'latest_version' => $latestVersion,
];
}
return false;
}
/**
* getCurrentVersion
*/
public function getCurrentVersion(): string
{
$branch = Git::getCurrentBranch();
$tag = Git::getCurrentTag();
$head = $branch != 'HEAD' ? $branch : $tag;
return $head;
}
/**
* getLatestVersion
*/
public function getLatestVersion(): string
{
return Cache::remember('latest_version', 5, function () {
return app(Repository::class)->getLatestVersion();
});
}
/**
* getLatestVersionData
*/
public function getLatestVersionData(): array
{
return Cache::remember('latest_version_data', 5, function () {
return app(Repository::class)->getLatestVersionData()->toArray();
});
}
/**
* versions
*/
public function versions(): array
{
return Cache::remember('versions', 5, function () {
return app(Repository::class)->getVersions();
});
}
}
================================================
FILE: src/UpdaterServiceProvider.php
================================================
<?php
namespace Salahhusa9\Updater;
use Salahhusa9\Updater\Commands\CheckCommand;
use Salahhusa9\Updater\Commands\UpdaterCommand;
use Salahhusa9\Updater\Contracts\Repository;
use Salahhusa9\Updater\RepositorySource\GithubRepository;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
class UpdaterServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
/*
* This class is a Package Service Provider
*
* More info: https://github.com/spatie/laravel-package-tools
*/
$package
->name('laravel-updater')
->hasConfigFile()
->hasViews()
->hasCommands(UpdaterCommand::class, CheckCommand::class);
$this->app->singleton(Repository::class, function () {
return new (config('updater.repository_source', GithubRepository::class))();
});
}
}
================================================
FILE: tests/ArchTest.php
================================================
<?php
it('will not use debugging functions')
->expect(['dd', 'dump', 'ray'])
->each->not->toBeUsed();
================================================
FILE: tests/Commands/CheckCommandTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests;
use Illuminate\Support\Facades\Event;
use Salahhusa9\Updater\Commands\CheckCommand;
use Salahhusa9\Updater\Events\NewVersionAvailable;
use Salahhusa9\Updater\Facades\Updater;
class CheckCommandTest extends TestCase
{
/** @test */
public function it_does_not_show_any_message_if_no_new_version_is_available()
{
Updater::shouldReceive('newVersionAvailable')->once()->andReturn(false);
$this->artisan('updater:check')
->expectsOutputToContain('No new version available')
->assertExitCode(CheckCommand::SUCCESS);
}
/** @test */
public function it_shows_a_message_if_a_new_version_is_available()
{
Updater::shouldReceive('newVersionAvailable')->once()->andReturn([
'current_version' => '1.0.0',
'latest_version' => '1.1.0',
]);
$this->artisan('updater:check')
->expectsOutputToContain('New version available: 1.1.0')
->assertExitCode(CheckCommand::SUCCESS);
}
/** @test */
public function it_fires_a_new_version_available_event_if_a_new_version_is_available()
{
Event::fake();
Updater::shouldReceive('newVersionAvailable')->once()->andReturn([
'current_version' => '1.0.0',
'latest_version' => '1.1.0',
]);
$this->artisan('updater:check')
->expectsOutputToContain('New version available: 1.1.0');
Event::assertDispatched(NewVersionAvailable::class, function ($event) {
return $event->currentVersion === '1.0.0' && $event->newVersion === '1.1.0';
});
}
}
================================================
FILE: tests/Commands/UpdaterCommandTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Commands;
use Illuminate\Support\Facades\Http;
use Salahhusa9\Updater\Facades\Updater;
use Salahhusa9\Updater\Tests\TestCase;
class UpdaterCommandTest extends TestCase
{
/** @test */
public function it_updates_the_application()
{
// Mock the Updater facade to return a new version
Updater::shouldReceive('newVersionAvailable')
->once()
->andReturn([
'current_version' => 'v1.0.0',
'latest_version' => 'v1.0.1',
]);
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-updater/releases/latest' => Http::response([
'tag_name' => 'v1.0.1',
], 200),
]);
// Mock the Updater facade to return the update command
Updater::shouldReceive('getCurrentVersion')
->once()
->andReturn('v1.0.0');
// Mock the Updater facade to return the update command
Updater::shouldReceive('update')
->once()
->andReturn('Updated to version v1.0.1');
// Call the UpdaterCommand
$this->artisan('updater:update')
->expectsOutputToContain('Updating to version v1.0.1')
->expectsOutputToContain('Application updated') // in real life this should be v1.0.1 but we mock it to v1.0.0
// ->expectsOutputToContain('v1.0.0') // in real life this should be v1.0.1 but we mock it to v1.0.0
// ->expectsOutputToContain('You are now on version') // in real life this should be v1.0.1 but we mock it to v1.0.0
->assertExitCode(0);
}
/** @test */
public function it_does_not_update_when_no_new_version_available()
{
// Mock the Updater facade to return no new version
Updater::shouldReceive('newVersionAvailable')
->once()
->andReturn(false);
// Call the UpdaterCommand
$this->artisan('updater:update')
->expectsOutputToContain('No new version available')
->assertExitCode(1);
}
}
================================================
FILE: tests/ExampleTest.php
================================================
<?php
it('can test', function () {
expect(true)->toBeTrue();
});
================================================
FILE: tests/GitTest.php
================================================
<?php
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Tests\TestCase;
class GitTest extends TestCase
{
public function test_get_current_commit(): void
{
Process::fake([
'git log --pretty="%h" -n1 HEAD' => Process::result('commit-hash'),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
$this->assertEquals('commit-hash', Salahhusa9\Updater\Helpers\Git::getCurrentCommit());
}
public function test_get_current_commit_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git log --pretty="%h" -n1 HEAD' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::getCurrentCommit();
}
public function test_get_current_branch(): void
{
Process::fake([
'git rev-parse --abbrev-ref HEAD' => Process::result('branch-name'),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
$this->assertEquals('branch-name', Salahhusa9\Updater\Helpers\Git::getCurrentBranch());
}
public function test_get_current_branch_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::getCurrentBranch();
}
public function test_get_current_tag(): void
{
Process::fake([
'git describe --tags --abbrev=0' => Process::result('tag-name'),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
$this->assertEquals('tag-name', Salahhusa9\Updater\Helpers\Git::getCurrentTag());
}
public function test_get_current_tag_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git describe --tags --abbrev=0' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
// change config git_path to git, because git path changed between windows and linux
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::getCurrentTag();
}
public function test_get_git_path(): void
{
config()->set('updater.git_path', 'git');
$this->assertEquals('git', Salahhusa9\Updater\Helpers\Git::gitPath());
}
public function test_git_auth(): void
{
config()->set('updater.github_token', 'token');
config()->set('updater.github_username', 'username');
config()->set('updater.github_repository', 'repository');
Process::fake([
'git remote set-url origin https://'.config('updater.github_username').':'.config('updater.github_token').'@github.com/'.config('updater.github_username').'/'.config('updater.github_repository').'.git' => Process::result(''),
]);
config()->set('updater.git_path', 'git');
$this->assertEquals('', Salahhusa9\Updater\Helpers\Git::auth());
}
public function test_git_auth_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git remote set-url origin https://'.config('updater.github_username').':'.config('updater.github_token').'@github.com/'.config('updater.github_username').'/'.config('updater.github_repository').'.git' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::auth();
}
public function test_git_pull(): void
{
Process::fake([
'git pull' => Process::result(''),
]);
config()->set('updater.git_path', 'git');
$this->assertEquals('', Salahhusa9\Updater\Helpers\Git::pull());
}
public function test_git_pull_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git pull' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::pull();
}
public function test_git_checkout(): void
{
Process::fake([
'git checkout branch-name -f' => Process::result(''),
]);
config()->set('updater.git_path', 'git');
$this->assertEquals('', Salahhusa9\Updater\Helpers\Git::checkout('branch-name'));
}
public function test_git_checkout_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git checkout branch-name -f' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::checkout('branch-name');
}
public function test_git_fetch(): void
{
Process::fake([
'git fetch' => Process::result(''),
]);
config()->set('updater.git_path', 'git');
$this->assertEquals('', Salahhusa9\Updater\Helpers\Git::fetch());
}
public function test_git_fetch_failed(): void
{
$this->expectException(Salahhusa9\Updater\Exceptions\GitFailedException::class);
$this->expectExceptionMessage('Test error output');
Process::fake([
'git fetch' => Process::result(
output: 'Test output',
errorOutput: 'Test error output',
exitCode: 1,
),
]);
config()->set('updater.git_path', 'git');
Salahhusa9\Updater\Helpers\Git::fetch();
}
}
================================================
FILE: tests/HelperTest.php
================================================
<?php
use PHPUnit\Framework\TestCase;
use Salahhusa9\Updater\Helpers\Helper;
class HelperTest extends TestCase
{
public function test_is_version_returns_true_for_valid_version()
{
$helper = new Helper;
$this->assertEquals($helper->isVersion('v1.2.3'), 1);
}
public function test_is_version_returns_false_for_invalid_version()
{
$helper = new Helper;
$this->assertEqualsCanonicalizing($helper->isVersion('invalid-version'), 0);
}
}
================================================
FILE: tests/Pest.php
================================================
<?php
use Salahhusa9\Updater\Tests\TestCase;
uses(TestCase::class)->in(__DIR__);
================================================
FILE: tests/Pipelines/ArtisanCallCacheClearPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallCacheClearPipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallCacheClearPipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('cache:clear'),
]);
$messages = [
'Start clearing cache',
'Cache cleared!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallCacheClearPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/ArtisanCallConfigClearPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallConfigClearPipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallConfigClearPipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('config:clear'),
]);
$messages = [
'Start clearing config cache',
'Config cache cleared!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallConfigClearPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/ArtisanCallMigratePipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallMigratePipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallMigratePipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('migrate'),
]);
$messages = [
'Start migrating',
'Migrated!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallMigratePipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/ArtisanCallOptimizePipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallOptimizePipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallOptimizePipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('optimize'),
]);
$messages = [
'Start optimizing',
'Optimized!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallOptimizePipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/ArtisanCallRouteClearPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallRouteClearPipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallRouteClearPipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('route:clear'),
]);
$messages = [
'Start clearing route cache',
'Route cache cleared!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallRouteClearPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/ArtisanCallViewClearPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\ArtisanCallViewClearPipe;
use Salahhusa9\Updater\Tests\TestCase;
class ArtisanCallViewClearPipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('view:clear'),
]);
$messages = [
'Start clearing view cache',
'View cache cleared!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(ArtisanCallViewClearPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/GitPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Pipelines\GitPipe;
use Salahhusa9\Updater\Tests\TestCase;
class GitPipeTest extends TestCase
{
public function test_run_handle()
{
Process::fake([
'*' => Process::result('1.0.0'), // this for return $version in getCurrentVersion()
]);
$messages = [
'Start downloading version 1.0.0',
'Checkout success',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
'new_version' => '1.0.0',
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(GitPipe::class)->handle($content, $next);
}
public function test_run_handle_with_error()
{
$this->expectException(\Exception::class);
Process::fake([
'*' => Process::result('error'), // this for throw new \Exception('git checkout failed: '.$checkout); becouse $checkout = Git::checkout($version); return error
]);
$messages = [
'Start downloading version 1.0.0',
'git checkout failed: error',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
'new_version' => '1.0.0',
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
app()->make(GitPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/Pipelines/SeedersPipeTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\Pipelines;
use Salahhusa9\Updater\Pipelines\SeedersPipe;
use Salahhusa9\Updater\Tests\TestCase;
class SeedersPipeTest extends TestCase
{
public function test_run_handle()
{
$messages = [
'Start seeding',
'Seeded!',
];
$content = [
'output' => function ($message) use ($messages) {
$this->assertTrue(in_array($message, $messages));
},
];
$next = function ($result) use ($content) {
$this->assertEquals($result, $content);
};
config()->set('updater.seeders', [
]);
app()->make(SeedersPipe::class)->handle($content, $next);
}
}
================================================
FILE: tests/RepositorySource/GithubRepositoryTest.php
================================================
<?php
namespace Salahhusa9\Updater\Tests\RepositorySource;
use Illuminate\Support\Facades\Http;
use Salahhusa9\Updater\Exceptions\GithubConfigException;
use Salahhusa9\Updater\RepositorySource\GithubRepository;
class GithubRepositoryTest extends \Salahhusa9\Updater\Tests\TestCase
{
/** @test */
public function config_check()
{
// set env
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-updater');
$githubRepository = new GithubRepository;
$this->assertTrue($githubRepository->checkConfig());
}
/** @test */
public function config_check_exception()
{
$this->expectException(GithubConfigException::class);
$githubRepository = new GithubRepository;
$this->assertTrue($githubRepository->checkConfig());
}
/** @test */
public function it_can_get_latest_version()
{
// set env
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-updater');
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-updater/releases/latest' => Http::response([
'tag_name' => 'v1.0.0',
], 200),
]);
$githubRepository = new GithubRepository;
$this->assertEquals('v1.0.0', $githubRepository->getLatestVersion());
}
/** @test */
public function it_can_get_latest_version_data()
{
// set env
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-updater');
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-updater/releases/latest' => Http::response([
'tag_name' => 'v1.0.0',
], 200),
]);
$githubRepository = new GithubRepository;
$this->assertIsArray($githubRepository->getLatestVersionData()->toArray());
}
/** @test */
public function it_can_get_versions()
{
// set env
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-updater');
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-updater/releases' => Http::response([
[
'tag_name' => 'v1.0.0',
],
[
'tag_name' => 'v1.0.1',
],
], 200),
]);
$githubRepository = new GithubRepository;
$this->assertIsArray($githubRepository->getVersions());
}
/** @test */
public function it_can_get_versions_data()
{
// set env
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-updater');
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-updater/releases' => Http::response([
[
'tag_name' => 'v1.0.0',
],
[
'tag_name' => 'v1.0.1',
],
], 200),
]);
$githubRepository = new GithubRepository;
$this->assertIsArray($githubRepository->getVersionsData()->toArray());
}
}
================================================
FILE: tests/TestCase.php
================================================
<?php
namespace Salahhusa9\Updater\Tests;
use Illuminate\Database\Eloquent\Factories\Factory;
use Orchestra\Testbench\TestCase as Orchestra;
use Salahhusa9\Updater\UpdaterServiceProvider;
class TestCase extends Orchestra
{
protected function setUp(): void
{
parent::setUp();
Factory::guessFactoryNamesUsing(
fn (string $modelName) => 'Salahhusa9\\Updater\\Database\\Factories\\'.class_basename($modelName).'Factory'
);
}
protected function getPackageProviders($app)
{
return [
UpdaterServiceProvider::class,
];
}
public function getEnvironmentSetUp($app)
{
config()->set('database.default', 'testing');
/*
$migration = include __DIR__.'/../database/migrations/create_laravel-updater_table.php.stub';
$migration->up();
*/
}
}
================================================
FILE: tests/UpdaterTest.php
================================================
<?php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Process;
use Salahhusa9\Updater\Facades\Updater;
use Salahhusa9\Updater\Tests\TestCase;
class UpdaterTest extends TestCase
{
public function test_get_current_version()
{
config()->set('updater.git_path', 'git');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
]);
$this->assertEquals('1.0.0', Updater::getCurrentVersion());
}
public function test_get_latest_version()
{
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-test/releases/latest' => Http::response([
'tag_name' => '1.0.1',
], 200),
]);
config()->set('updater.git_path', 'git');
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-test');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull' => '',
'git checkout 1.0.1' => 'TEST',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
$this->assertEquals('1.0.1', Updater::getLatestVersion());
}
public function test_get_latest_version_data()
{
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-test/releases/latest' => Http::response([
'tag_name' => '1.0.1',
], 200),
]);
config()->set('updater.git_path', 'git');
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-test');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull' => '',
'git checkout 1.0.1' => 'TEST',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
$this->assertEquals(['tag_name' => '1.0.1'], Updater::getLatestVersionData());
}
public function test_versions()
{
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-test/releases' => Http::response([
[
'tag_name' => '1.0.0',
],
[
'tag_name' => '1.1.0',
],
[
'tag_name' => '2.0.0',
],
], 200),
]);
config()->set('updater.git_path', 'git');
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-test');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull' => '',
'git checkout 1.0.1' => 'TEST',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
$this->assertEquals(['1.0.0', '1.1.0', '2.0.0'], Updater::versions());
}
public function test_new_version_available()
{
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-test/releases/latest' => Http::response([
'tag_name' => '1.0.1',
], 200),
]);
config()->set('updater.git_path', 'git');
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-test');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull' => '',
'git checkout 1.0.1' => 'TEST',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
$this->assertEquals(['current_version' => '1.0.0', 'latest_version' => '1.0.1'], Updater::newVersionAvailable());
}
public function test_update()
{
Event::fake();
// Artisan::fake();
Http::fake([
'https://api.github.com/repos/salahhusa9/laravel-test/releases/latest' => Http::response([
'tag_name' => '1.0.1',
], 200),
]);
config()->set('updater.git_path', 'git');
config()->set('updater.github_token', 'salahhusa9');
config()->set('updater.github_username', 'salahhusa9');
config()->set('updater.github_repository', 'laravel-test');
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull' => '',
'git checkout 1.0.1 -f' => 'TEST',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
// Artisan::shouldReceive('call')->once()->with('up');
$this->assertEquals('Updated to version 1.0.1', Updater::update());
// Test update failure
Process::fake([
'git rev-parse --abbrev-ref HEAD' => 'HEAD',
'git describe --tags --abbrev=0' => '1.0.0',
'git pull origin HEAD' => '',
'git checkout 1.0.1 -f' => '...',
'git remote set-url origin https://salahhusa9:salahhusa9@github.com/salahhusa9/laravel-test.git' => '',
'git fetch' => '',
]);
$this->expectException(Exception::class);
$this->expectExceptionMessage('git checkout failed: ...');
Updater::update();
}
}
================================================
FILE: workbench/app/Providers/WorkbenchServiceProvider.php
================================================
<?php
namespace Workbench\App\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;
class WorkbenchServiceProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
//
}
/**
* Bootstrap services.
*/
public function boot(): void
{
Route::view('/', 'welcome');
}
}
gitextract_joqugs2b/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug.yml
│ │ └── config.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── dependabot-auto-merge.yml
│ ├── deploy-docs.yml
│ ├── fix-php-code-style-issues.yml
│ ├── run-tests.yml
│ └── update-changelog.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── config/
│ └── updater.php
├── database/
│ └── factories/
│ └── ModelFactory.php
├── phpunit.xml.dist
├── renovate.json
├── resources/
│ └── views/
│ └── .gitkeep
├── src/
│ ├── Commands/
│ │ ├── CheckCommand.php
│ │ └── UpdaterCommand.php
│ ├── Contracts/
│ │ ├── Pipeline.php
│ │ └── Repository.php
│ ├── Events/
│ │ ├── NewVersionAvailable.php
│ │ ├── UpdateFailed.php
│ │ └── UpdatedSuccessfully.php
│ ├── Exceptions/
│ │ ├── GitFailedException.php
│ │ └── GithubConfigException.php
│ ├── Facades/
│ │ └── Updater.php
│ ├── Helpers/
│ │ ├── Git.php
│ │ └── Helper.php
│ ├── Pipelines/
│ │ ├── ArtisanCallCacheClearPipe.php
│ │ ├── ArtisanCallConfigClearPipe.php
│ │ ├── ArtisanCallMigratePipe.php
│ │ ├── ArtisanCallOptimizePipe.php
│ │ ├── ArtisanCallRouteClearPipe.php
│ │ ├── ArtisanCallViewClearPipe.php
│ │ ├── GitPipe.php
│ │ └── SeedersPipe.php
│ ├── RepositorySource/
│ │ └── GithubRepository.php
│ ├── Updater.php
│ └── UpdaterServiceProvider.php
├── tests/
│ ├── ArchTest.php
│ ├── Commands/
│ │ ├── CheckCommandTest.php
│ │ └── UpdaterCommandTest.php
│ ├── ExampleTest.php
│ ├── GitTest.php
│ ├── HelperTest.php
│ ├── Pest.php
│ ├── Pipelines/
│ │ ├── ArtisanCallCacheClearPipeTest.php
│ │ ├── ArtisanCallConfigClearPipeTest.php
│ │ ├── ArtisanCallMigratePipeTest.php
│ │ ├── ArtisanCallOptimizePipeTest.php
│ │ ├── ArtisanCallRouteClearPipeTest.php
│ │ ├── ArtisanCallViewClearPipeTest.php
│ │ ├── GitPipeTest.php
│ │ └── SeedersPipeTest.php
│ ├── RepositorySource/
│ │ └── GithubRepositoryTest.php
│ ├── TestCase.php
│ └── UpdaterTest.php
└── workbench/
└── app/
└── Providers/
└── WorkbenchServiceProvider.php
SYMBOL INDEX (131 symbols across 39 files)
FILE: src/Commands/CheckCommand.php
class CheckCommand (line 9) | class CheckCommand extends Command
method handle (line 15) | public function handle(): int
FILE: src/Commands/UpdaterCommand.php
class UpdaterCommand (line 8) | class UpdaterCommand extends Command
method handle (line 14) | public function handle(): int
FILE: src/Contracts/Pipeline.php
type Pipeline (line 5) | interface Pipeline
method handle (line 7) | public function handle($content, \Closure $next);
FILE: src/Contracts/Repository.php
type Repository (line 5) | interface Repository
method getLatestVersion (line 7) | public function getLatestVersion(): string;
method getLatestVersionData (line 9) | public function getLatestVersionData(): \Illuminate\Support\Collection;
method getVersions (line 11) | public function getVersions(): array;
method getVersionsData (line 13) | public function getVersionsData(): \Illuminate\Support\Collection;
FILE: src/Events/NewVersionAvailable.php
class NewVersionAvailable (line 8) | class NewVersionAvailable
method __construct (line 16) | public function __construct($currentVersion, $newVersion)
FILE: src/Events/UpdateFailed.php
class UpdateFailed (line 8) | class UpdateFailed
method __construct (line 18) | public function __construct($pastVersion, $newVersion, $exception)
FILE: src/Events/UpdatedSuccessfully.php
class UpdatedSuccessfully (line 8) | class UpdatedSuccessfully
method __construct (line 16) | public function __construct($pastVersion, $newVersion)
FILE: src/Exceptions/GitFailedException.php
class GitFailedException (line 7) | class GitFailedException extends RuntimeException
method __construct (line 14) | public function __construct($message)
FILE: src/Exceptions/GithubConfigException.php
class GithubConfigException (line 7) | class GithubConfigException extends RuntimeException
method __construct (line 14) | public function __construct($message)
FILE: src/Facades/Updater.php
class Updater (line 17) | class Updater extends Facade
method getFacadeAccessor (line 19) | protected static function getFacadeAccessor()
FILE: src/Helpers/Git.php
class Git (line 8) | class Git
method getCurrentCommit (line 17) | public static function getCurrentCommit()
method getCurrentBranch (line 35) | public static function getCurrentBranch()
method getCurrentTag (line 53) | public static function getCurrentTag()
method auth (line 71) | public static function auth()
method pull (line 89) | public static function pull()
method checkout (line 108) | public static function checkout($branch)
method fetch (line 126) | public static function fetch()
method gitPath (line 142) | public static function gitPath()
FILE: src/Helpers/Helper.php
class Helper (line 5) | class Helper
method isVersion (line 12) | public function isVersion($version): int|false
FILE: src/Pipelines/ArtisanCallCacheClearPipe.php
class ArtisanCallCacheClearPipe (line 9) | class ArtisanCallCacheClearPipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/ArtisanCallConfigClearPipe.php
class ArtisanCallConfigClearPipe (line 9) | class ArtisanCallConfigClearPipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/ArtisanCallMigratePipe.php
class ArtisanCallMigratePipe (line 9) | class ArtisanCallMigratePipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/ArtisanCallOptimizePipe.php
class ArtisanCallOptimizePipe (line 9) | class ArtisanCallOptimizePipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/ArtisanCallRouteClearPipe.php
class ArtisanCallRouteClearPipe (line 9) | class ArtisanCallRouteClearPipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/ArtisanCallViewClearPipe.php
class ArtisanCallViewClearPipe (line 9) | class ArtisanCallViewClearPipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/Pipelines/GitPipe.php
class GitPipe (line 10) | class GitPipe implements Pipeline
method handle (line 19) | public function handle($content, Closure $next)
FILE: src/Pipelines/SeedersPipe.php
class SeedersPipe (line 9) | class SeedersPipe implements Pipeline
method handle (line 18) | public function handle($content, Closure $next)
FILE: src/RepositorySource/GithubRepository.php
class GithubRepository (line 9) | class GithubRepository implements Repository
method getLatestVersion (line 14) | public function getLatestVersion(): string
method getLatestVersionData (line 26) | public function getLatestVersionData(): \Illuminate\Support\Collection
method getVersions (line 44) | public function getVersions(): array
method getVersionsData (line 64) | public function getVersionsData(): \Illuminate\Support\Collection
method checkConfig (line 84) | public function checkConfig()
FILE: src/Updater.php
class Updater (line 11) | class Updater
method update (line 18) | public function update(?callable $output = null): string
method updateTo (line 38) | private function updateTo($version): string
method output (line 151) | public function output($message): void
method newVersionAvailable (line 163) | public function newVersionAvailable(): bool|array
method getCurrentVersion (line 181) | public function getCurrentVersion(): string
method getLatestVersion (line 194) | public function getLatestVersion(): string
method getLatestVersionData (line 204) | public function getLatestVersionData(): array
method versions (line 214) | public function versions(): array
FILE: src/UpdaterServiceProvider.php
class UpdaterServiceProvider (line 12) | class UpdaterServiceProvider extends PackageServiceProvider
method configurePackage (line 14) | public function configurePackage(Package $package): void
FILE: tests/Commands/CheckCommandTest.php
class CheckCommandTest (line 10) | class CheckCommandTest extends TestCase
method it_does_not_show_any_message_if_no_new_version_is_available (line 13) | public function it_does_not_show_any_message_if_no_new_version_is_avai...
method it_shows_a_message_if_a_new_version_is_available (line 23) | public function it_shows_a_message_if_a_new_version_is_available()
method it_fires_a_new_version_available_event_if_a_new_version_is_available (line 36) | public function it_fires_a_new_version_available_event_if_a_new_versio...
FILE: tests/Commands/UpdaterCommandTest.php
class UpdaterCommandTest (line 9) | class UpdaterCommandTest extends TestCase
method it_updates_the_application (line 12) | public function it_updates_the_application()
method it_does_not_update_when_no_new_version_available (line 48) | public function it_does_not_update_when_no_new_version_available()
FILE: tests/GitTest.php
class GitTest (line 6) | class GitTest extends TestCase
method test_get_current_commit (line 8) | public function test_get_current_commit(): void
method test_get_current_commit_failed (line 20) | public function test_get_current_commit_failed(): void
method test_get_current_branch (line 39) | public function test_get_current_branch(): void
method test_get_current_branch_failed (line 51) | public function test_get_current_branch_failed(): void
method test_get_current_tag (line 70) | public function test_get_current_tag(): void
method test_get_current_tag_failed (line 82) | public function test_get_current_tag_failed(): void
method test_get_git_path (line 101) | public function test_get_git_path(): void
method test_git_auth (line 108) | public function test_git_auth(): void
method test_git_auth_failed (line 123) | public function test_git_auth_failed(): void
method test_git_pull (line 141) | public function test_git_pull(): void
method test_git_pull_failed (line 152) | public function test_git_pull_failed(): void
method test_git_checkout (line 170) | public function test_git_checkout(): void
method test_git_checkout_failed (line 181) | public function test_git_checkout_failed(): void
method test_git_fetch (line 199) | public function test_git_fetch(): void
method test_git_fetch_failed (line 210) | public function test_git_fetch_failed(): void
FILE: tests/HelperTest.php
class HelperTest (line 6) | class HelperTest extends TestCase
method test_is_version_returns_true_for_valid_version (line 8) | public function test_is_version_returns_true_for_valid_version()
method test_is_version_returns_false_for_invalid_version (line 15) | public function test_is_version_returns_false_for_invalid_version()
FILE: tests/Pipelines/ArtisanCallCacheClearPipeTest.php
class ArtisanCallCacheClearPipeTest (line 9) | class ArtisanCallCacheClearPipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/ArtisanCallConfigClearPipeTest.php
class ArtisanCallConfigClearPipeTest (line 9) | class ArtisanCallConfigClearPipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/ArtisanCallMigratePipeTest.php
class ArtisanCallMigratePipeTest (line 9) | class ArtisanCallMigratePipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/ArtisanCallOptimizePipeTest.php
class ArtisanCallOptimizePipeTest (line 9) | class ArtisanCallOptimizePipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/ArtisanCallRouteClearPipeTest.php
class ArtisanCallRouteClearPipeTest (line 9) | class ArtisanCallRouteClearPipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/ArtisanCallViewClearPipeTest.php
class ArtisanCallViewClearPipeTest (line 9) | class ArtisanCallViewClearPipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
FILE: tests/Pipelines/GitPipeTest.php
class GitPipeTest (line 9) | class GitPipeTest extends TestCase
method test_run_handle (line 11) | public function test_run_handle()
method test_run_handle_with_error (line 36) | public function test_run_handle_with_error()
FILE: tests/Pipelines/SeedersPipeTest.php
class SeedersPipeTest (line 8) | class SeedersPipeTest extends TestCase
method test_run_handle (line 10) | public function test_run_handle()
FILE: tests/RepositorySource/GithubRepositoryTest.php
class GithubRepositoryTest (line 9) | class GithubRepositoryTest extends \Salahhusa9\Updater\Tests\TestCase
method config_check (line 12) | public function config_check()
method config_check_exception (line 25) | public function config_check_exception()
method it_can_get_latest_version (line 35) | public function it_can_get_latest_version()
method it_can_get_latest_version_data (line 54) | public function it_can_get_latest_version_data()
method it_can_get_versions (line 73) | public function it_can_get_versions()
method it_can_get_versions_data (line 97) | public function it_can_get_versions_data()
FILE: tests/TestCase.php
class TestCase (line 9) | class TestCase extends Orchestra
method setUp (line 11) | protected function setUp(): void
method getPackageProviders (line 20) | protected function getPackageProviders($app)
method getEnvironmentSetUp (line 27) | public function getEnvironmentSetUp($app)
FILE: tests/UpdaterTest.php
class UpdaterTest (line 10) | class UpdaterTest extends TestCase
method test_get_current_version (line 12) | public function test_get_current_version()
method test_get_latest_version (line 24) | public function test_get_latest_version()
method test_get_latest_version_data (line 49) | public function test_get_latest_version_data()
method test_versions (line 74) | public function test_versions()
method test_new_version_available (line 107) | public function test_new_version_available()
method test_update (line 132) | public function test_update()
FILE: workbench/app/Providers/WorkbenchServiceProvider.php
class WorkbenchServiceProvider (line 8) | class WorkbenchServiceProvider extends ServiceProvider
method register (line 13) | public function register(): void
method boot (line 21) | public function boot(): void
Condensed preview — 63 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (92K chars).
[
{
"path": ".editorconfig",
"chars": 220,
"preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_"
},
{
"path": ".gitattributes",
"chars": 705,
"preview": "# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test and"
},
{
"path": ".github/FUNDING.yml",
"chars": 738,
"preview": "# These are supported funding model platforms\n\ngithub: [salahhusa9]\npatreon: # Replace with a single Patreon username\nop"
},
{
"path": ".github/ISSUE_TEMPLATE/bug.yml",
"chars": 2174,
"preview": "name: Bug Report\ndescription: Report an Issue or Bug with the Package\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n - type:"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 502,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Ask a question\n url: https://github.com/salahhusa9/laravel-updat"
},
{
"path": ".github/dependabot.yml",
"chars": 321,
"preview": "# Please see the documentation for all configuration options:\n# https://help.github.com/github/administering-a-repositor"
},
{
"path": ".github/workflows/dependabot-auto-merge.yml",
"chars": 1054,
"preview": "name: dependabot-auto-merge\non: pull_request_target\n\npermissions:\n pull-requests: write\n contents: write\n\njobs:\n depe"
},
{
"path": ".github/workflows/deploy-docs.yml",
"chars": 3468,
"preview": "# Sample workflow for building and deploying a Next.js site to GitHub Pages\n#\n# To get started with Next.js see: https:/"
},
{
"path": ".github/workflows/fix-php-code-style-issues.yml",
"chars": 510,
"preview": "name: Fix PHP code style issues\n\non:\n push:\n paths:\n - '**.php'\n\npermissions:\n contents: write\n\njobs:\n php-co"
},
{
"path": ".github/workflows/run-tests.yml",
"chars": 1643,
"preview": "name: run-tests\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n test:\n runs-on: ${{ m"
},
{
"path": ".github/workflows/update-changelog.yml",
"chars": 677,
"preview": "name: \"Update Changelog\"\n\non:\n release:\n types: [released]\n\npermissions:\n contents: write\n\njobs:\n update:\n runs"
},
{
"path": ".gitignore",
"chars": 122,
"preview": ".idea\n.phpunit.cache\nbuild\ncomposer.lock\ncoverage\ndocs\nphpunit.xml\nphpstan.neon\ntestbench.yaml\nvendor\nnode_modules\n\n.nex"
},
{
"path": "CHANGELOG.md",
"chars": 6745,
"preview": "# Changelog\n\nAll notable changes to `laravel-updater` will be documented in this file.\n\n## v1.3.0 - 2025-04-01\n\n### What"
},
{
"path": "LICENSE.md",
"chars": 1095,
"preview": "The MIT License (MIT)\n\nCopyright (c) salahhusa9 <salahhusa9@gmail.com>\n\nPermission is hereby granted, free of charge, to"
},
{
"path": "README.md",
"chars": 1892,
"preview": "# Laravel Updater\n\n[: string;\n\n"
},
{
"path": "src/Events/NewVersionAvailable.php",
"chars": 421,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\nuse Illuminate\\Queue\\Seriali"
},
{
"path": "src/Events/UpdateFailed.php",
"chars": 477,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\nuse Illuminate\\Queue\\Seriali"
},
{
"path": "src/Events/UpdatedSuccessfully.php",
"chars": 409,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\nuse Illuminate\\Queue\\Seriali"
},
{
"path": "src/Exceptions/GitFailedException.php",
"chars": 313,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Exceptions;\n\nuse RuntimeException;\n\nclass GitFailedException extends RuntimeExceptio"
},
{
"path": "src/Exceptions/GithubConfigException.php",
"chars": 319,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Exceptions;\n\nuse RuntimeException;\n\nclass GithubConfigException extends RuntimeExcep"
},
{
"path": "src/Facades/Updater.php",
"chars": 704,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\n/**\n * @see \\Salahhusa9\\Updater\\Up"
},
{
"path": "src/Helpers/Git.php",
"chars": 3668,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Helpers;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Exceptions\\"
},
{
"path": "src/Helpers/Helper.php",
"chars": 312,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Helpers;\n\nclass Helper\n{\n /**\n * isVersion\n *\n * @param mixed $vers"
},
{
"path": "src/Pipelines/ArtisanCallCacheClearPipe.php",
"chars": 706,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/ArtisanCallConfigClearPipe.php",
"chars": 722,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/ArtisanCallMigratePipe.php",
"chars": 733,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/ArtisanCallOptimizePipe.php",
"chars": 693,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/ArtisanCallRouteClearPipe.php",
"chars": 718,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/ArtisanCallViewClearPipe.php",
"chars": 714,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/Pipelines/GitPipe.php",
"chars": 1185,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Salahhusa9\\Updater\\Contracts\\Pipeline;\nuse Salahhusa9\\U"
},
{
"path": "src/Pipelines/SeedersPipe.php",
"chars": 867,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Pipelines;\n\nuse Closure;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Salahhusa9\\Upda"
},
{
"path": "src/RepositorySource/GithubRepository.php",
"chars": 2921,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\RepositorySource;\n\nuse Illuminate\\Support\\Facades\\Http;\nuse Salahhusa9\\Updater\\Contr"
},
{
"path": "src/Updater.php",
"chars": 7125,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater;\n\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Support\\Facades\\Cache;\nuse "
},
{
"path": "src/UpdaterServiceProvider.php",
"chars": 970,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater;\n\nuse Salahhusa9\\Updater\\Commands\\CheckCommand;\nuse Salahhusa9\\Updater\\Commands\\Upda"
},
{
"path": "tests/ArchTest.php",
"chars": 111,
"preview": "<?php\n\nit('will not use debugging functions')\n ->expect(['dd', 'dump', 'ray'])\n ->each->not->toBeUsed();\n"
},
{
"path": "tests/Commands/CheckCommandTest.php",
"chars": 1657,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests;\n\nuse Illuminate\\Support\\Facades\\Event;\nuse Salahhusa9\\Updater\\Commands\\CheckC"
},
{
"path": "tests/Commands/UpdaterCommandTest.php",
"chars": 2103,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Commands;\n\nuse Illuminate\\Support\\Facades\\Http;\nuse Salahhusa9\\Updater\\Facades"
},
{
"path": "tests/ExampleTest.php",
"chars": 70,
"preview": "<?php\n\nit('can test', function () {\n expect(true)->toBeTrue();\n});\n"
},
{
"path": "tests/GitTest.php",
"chars": 7344,
"preview": "<?php\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Tests\\TestCase;\n\nclass GitTest extends TestCase\n{\n"
},
{
"path": "tests/HelperTest.php",
"chars": 492,
"preview": "<?php\n\nuse PHPUnit\\Framework\\TestCase;\nuse Salahhusa9\\Updater\\Helpers\\Helper;\n\nclass HelperTest extends TestCase\n{\n p"
},
{
"path": "tests/Pest.php",
"chars": 83,
"preview": "<?php\n\nuse Salahhusa9\\Updater\\Tests\\TestCase;\n\nuses(TestCase::class)->in(__DIR__);\n"
},
{
"path": "tests/Pipelines/ArtisanCallCacheClearPipeTest.php",
"chars": 861,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/ArtisanCallConfigClearPipeTest.php",
"chars": 879,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/ArtisanCallMigratePipeTest.php",
"chars": 838,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/ArtisanCallOptimizePipeTest.php",
"chars": 844,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/ArtisanCallRouteClearPipeTest.php",
"chars": 873,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/ArtisanCallViewClearPipeTest.php",
"chars": 867,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/GitPipeTest.php",
"chars": 1741,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Illuminate\\Support\\Facades\\Process;\nuse Salahhusa9\\Updater\\Pip"
},
{
"path": "tests/Pipelines/SeedersPipeTest.php",
"chars": 734,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\Pipelines;\n\nuse Salahhusa9\\Updater\\Pipelines\\SeedersPipe;\nuse Salahhusa9\\Updat"
},
{
"path": "tests/RepositorySource/GithubRepositoryTest.php",
"chars": 3647,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests\\RepositorySource;\n\nuse Illuminate\\Support\\Facades\\Http;\nuse Salahhusa9\\Updater"
},
{
"path": "tests/TestCase.php",
"chars": 872,
"preview": "<?php\n\nnamespace Salahhusa9\\Updater\\Tests;\n\nuse Illuminate\\Database\\Eloquent\\Factories\\Factory;\nuse Orchestra\\Testbench\\"
},
{
"path": "tests/UpdaterTest.php",
"chars": 6261,
"preview": "<?php\n\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Support\\Facades\\Event;\nuse Illuminate\\Support\\Facades\\Http"
},
{
"path": "workbench/app/Providers/WorkbenchServiceProvider.php",
"chars": 409,
"preview": "<?php\n\nnamespace Workbench\\App\\Providers;\n\nuse Illuminate\\Support\\Facades\\Route;\nuse Illuminate\\Support\\ServiceProvider;"
}
]
About this extraction
This page contains the full source code of the salahhusa9/laravel-updater GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 63 files (82.3 KB), approximately 22.4k tokens, and a symbol index with 131 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.