Laravel-Backpack / community-forum

A workspace to discuss improvement and feature ideas, before they're actually implemented.
28 stars 0 forks source link

Deploy Backpack with atomic releases. #1043

Closed pxpm closed 1 week ago

pxpm commented 2 weeks ago

Hi @pxpm yes i can chat direct with you.. here ? Anyway i explain here my problem: All my applications are now all based on Laravale 11 and Backpack V6.x

All my applications are on Github repositories and we use two main branches: master_dev and master_prod

The deployment takes place automatically on my servers managed by runcloud.io which allows you to have a history of the last 5 publications so you can go back very quickly in case of problems

My collaborators and I develop and do the first tests locally, then we push to master_dev and do further tests, when everything is ok we push to master_prod

Now there is the need to have a "storage" that is outside the "root app" so that user files are preserved

I would like to know what the optimal configuration is regarding: backpack basset

For both local and production environments

PS. I think this could be useful to all Backpack customers and perhaps should be posted in your https://backpackforlaravel.com/docs/

Regards

Mauro

Originally posted by @blondie63 in https://github.com/Laravel-Backpack/CRUD/issues/5331#issuecomment-2173150743

pxpm commented 2 weeks ago

Hey @blondie63 , I would rather we talk in another issue, since it does not seem to be related to the other topic, at least in the other topic nothing is mentioned about atomic deployments, or anything similar.

From what I read in the docs of runcloud about atomic deployments and symlinking, there is nothing particular different. It says your storage folder should be empty in the git repository (as it is expected), and you can add your own deployments scripts.

Can you share you deployment script ? I am assuming you are using something like stated in the docs: https://runcloud.io/docs/laravel-atomic-deployment

So those deployment scripts, should be able to run artisan commands: optimize:clear, storage:link, basset:clear, basset:cache, optimize ?

Cheers

blondie63 commented 2 weeks ago

ok my problem is not about scripts, my problem is deciding how to configure the disks on filesystem.php and which ones to use for basset and cruds that have upload fields so that user files are not lost at each deployment. Keep in mind that each deployment creates a new folder for the app and in fact Runcloud provides for the creation of special Symlinks which it calls Directory (https://runcloud.io/docs/symlink-in-atomic-deployment#directory) to separate the files user

Regards

pxpm commented 2 weeks ago

I think that refers to different files. Because the user files don't change in each deployment (if I upload my profile picture I expect it to be the same picture after you release a new version of your app).

But for assets, they should be "regenerated" on each deployment as you can update your dependencies like:

- @basset('https://cdn.com/select2/1.0.0')
+ @baset('https://cdn.com/select2/2.3.0')

And usually that's done in those deployment scripts on any Laravel application.

For example in Forge, this is a snippet of something you can use as a deployment script:

git pull origin $FORGE_SITE_BRANCH

$FORGE_COMPOSER install --no-dev --no-interaction --prefer-dist --optimize-autoloader

$FORGE_PHP artisan optimize:clear
$FORGE_PHP artisan view:clear
$FORGE_PHP artisan basset:clear

#some stuff here omited

if [ -f artisan ]; then
    $FORGE_PHP artisan migrate --force
    $FORGE_PHP artisan basset:cache
    $FORGE_PHP artisan optimize
fi

You should probably also add storage:link because I assume in atomic deployments that the link is broken when a new folder is created to deploy.

To user uploaded files you should add them to a disk, laravel comes with public by default but feel free to read the Laravel docs and configure your own disk, and then do the process described in the docs page you shared to keep user uploaded files through deployments. Or alternatively upload them to an s3 bucket or similar.

I never used runcloud, but it's possible to run those kind of scripts as far as I've read in the docs and should be enough to get it going.

Let me know.

Cheers

blondie63 commented 2 weeks ago

Maybe I didn't explain myself well but I'll try again! Normally the php artisan storage:link command creates a link between "rootapp"/public/storage and "rootapp"/storage/app/public which is an internal folder

Runcloud will allow you to have external storage and therefore you need to create a Symlink that points and is recreated at each deployment:

AtomicDeploy_root

The problem is understanding which disk to use... if basset uses "public" which is inside the /storage folder then I have to use another disk for user files (CRUD uploads) Right ?

I think this is a very common management or am I wrong?

pxpm commented 2 weeks ago

I don't think you are wrong at all.

In most of the apps, the default configs for basset and file uploads should work out of the box. In your case, since you are using atomic releases you most likely need to tweak it as you noticed, since "basset files" shouldn't be treated as "user files".

You can add a disk that stores the basset files in the public/ folder directly, not in storage and that also works just fine as well.

// in config/filesystem.php add a new disk

'bassetAssets' => [
            'driver'     => 'local',
            'root'       => public_path(),
            'url'        => env('APP_URL'),
            'visibility' => 'public',
            'throw'      => false,
        ],

Configure basset to use that disk, in your .env: BASSET_DISK=bassetAssets

When you run php artisan basset:cache the files will be placed in public/basset.

Add that folder to .gitignore so they don't appear as changes.

Basset is now loading the assets from your public folder instead of the default storage. image

You can tell basset to store the files in s3, it defeats the purpose of "internalizing" the assets in your app, but basset does not care about it, basset just accepts a place to store and retrieve files. Where to do that is completely up to you.

Does this take you on the right path ?

Cheers

blondie63 commented 2 weeks ago

@pxpm Ok for basset but for user files? Do I have to create a specific disk for these files too?

Regards

pxpm commented 2 weeks ago

@pxpm Ok for basset but for user files? Do I have to create a specific disk for these files too?

Regards

I don't think you need to create any specific disk for them. You can use the default Laravel public disk, and follow https://runcloud.io/docs/symlink-in-atomic-deployment#directory to have the storage persistent.

If the storage:link gets broken on each release, you need to add it to your deployment script.

I use Deployer sometimes with atomic releases, the output/order of the stuff should be something along this lines:

✈︎ Deploying main on xxx.xxx.xxx.xxx
✔ Executing task deploy:prepare
✔ Executing task deploy:lock
✔ Executing task deploy:release
➤ Executing task deploy:update_code
✔ Ok
✔ Executing task deploy:shared
✔ Executing task deploy:vendors
✔ Executing task deploy:writable
✔ Executing task artisan:storage:link
✔ Executing task artisan:view:clear
✔ Executing task artisan:cache:clear
✔ Executing task artisan:config:cache
✔ Executing task artisan:optimize
✔ Executing task deploy:symlink
✔ Executing task deploy:unlock
✔ Executing task cleanup
Successfully deployed!

I don't think I can help you more than you can do by yourself by searching on the internet and banging your head for a while trying to make stuff work (as everyone else).

Think of it like this, forget you are using Backpack ... imagine that your app creates some .json files using Laravel Filesystem with the default public disk. Just go to your app and create those files manually if needed using Storage::disk('public')->put() in a tinker session or create a test application to play around with it.

Make sure you can release your app and those files are still available on the current deployment. When that is working, any file upload to that same public disk will work the same.

Backpack does not add anything special in the mix here.

Hope that helps 🙏

Cheers

blondie63 commented 2 weeks ago

ok @pxpm Thanks, i've to study a little :)

pxpm commented 2 weeks ago

ok @pxpm Thanks, i've to study a little :)

You are almost there. 🙏 Basset is out of the way as the solution I gave you does not require a symlink. (and it's a perfectly fine solution).

Figure out the file uploads with the persistent storage and you are golden 🏅

Good luck mate!

Cheers