Skip to content

feat: Trigger Lagoon Deployments for App Instances#56

Merged
dan2k3k4 merged 15 commits intomainfrom
add-trigger-deploy-and-lagoon-command
Mar 17, 2026
Merged

feat: Trigger Lagoon Deployments for App Instances#56
dan2k3k4 merged 15 commits intomainfrom
add-trigger-deploy-and-lagoon-command

Conversation

@dan2k3k4
Copy link
Member

@dan2k3k4 dan2k3k4 commented Dec 24, 2025

Introduces the ability to trigger Lagoon deployments for Polydock App Instances directly from the Polydock Engine.

Adds two new Artisan commands for bulk or single-instance deployments and integrates a "Trigger Deploy" action into the Filament Admin UI.

Key Changes

  1. New Console Commands
    • polydock:instances:run-lagoon-command:
      • Method: Uses the Lagoon GraphQL API (via FreedomtechHosting\FtLagoonPhp\Client).
      • Features:
        • Supports concurrency (default: 1) for faster bulk operations.
        • Interactive mode allows selecting specific instances from a list (unless --force is used).
        • Handles authentication via SSH key exchange for Lagoon tokens.
    • polydock:instances:trigger-deploy:
      • Method: Wrapper around the system's lagoon CLI tool.
      • Features: Simple execution of lagoon deploy -p [project] -e [branch] for running instances.
  2. Admin UI Updates
    • ViewPolydockAppInstance:
      • Added a Trigger Deploy header action.
      • Displays a modal confirming the branch and showing the "Last Deployment Date".
      • Executes the deployment via the local lagoon CLI.
  3. Model Updates
    • PolydockAppInstance: Added getName() and setName() convenience methods.
    1. Testing
    • Added tests/Feature/Console/Commands/RunLagoonCommandOnAppInstancesTest.php covering:
      • Serial vs. Concurrent execution.
      • Variable-only deployments.
      • Error handling for missing metadata.
      • Interactive prompts.

How to Test

CLI (API-based):

# Dry run / Interactive selection
php artisan polydock:instances:run-lagoon-command {app_uuid}

# Force run on all instances concurrently
php artisan polydock:instances:run-lagoon-command {app_uuid} --force --concurrency=5

CLI (Lagoon CLI-based):
php artisan polydock:instances:trigger-deploy {app_uuid}

Admin UI:

  1. Navigate to a Polydock App Instance view page.
  2. Click the new Trigger Deploy button in the header.
  3. Confirm the action in the modal.

@dan2k3k4 dan2k3k4 requested a review from bomoko December 24, 2025 20:14
@dan2k3k4 dan2k3k4 force-pushed the add-trigger-deploy-and-lagoon-command branch 2 times, most recently from cef3c95 to 579e6f6 Compare February 15, 2026 18:58
@dan2k3k4 dan2k3k4 changed the title chore: artisan add trigger lagoon deploy and run lagoon commands on app instances feat: Trigger Lagoon Deployments for App Instances Feb 15, 2026
@dan2k3k4 dan2k3k4 requested a review from bomoko February 23, 2026 14:01
@dan2k3k4 dan2k3k4 force-pushed the add-trigger-deploy-and-lagoon-command branch from cfba370 to 5d83b74 Compare February 23, 2026 14:15
@dan2k3k4 dan2k3k4 force-pushed the add-trigger-deploy-and-lagoon-command branch from 9a578d4 to 33fd4c6 Compare February 25, 2026 13:18
- chore: trigger deploy via api instead of lagoon cli
- chore: find by uuid
- chore: only cache token for 2min
@dan2k3k4 dan2k3k4 force-pushed the add-trigger-deploy-and-lagoon-command branch from 0c16e85 to 0edf925 Compare February 26, 2026 17:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Lagoon deployment/command triggering capabilities for Polydock App Instances from both Artisan commands and the Filament Admin UI, leveraging the freedomtech-hosting/ft-lagoon-php GraphQL client and SSH-based token retrieval.

Changes:

  • Introduces new Lagoon-related Artisan commands for bulk/single-instance deploy triggers and for running allowed commands across instances (with optional concurrency).
  • Adds a Filament “Trigger Deploy” header action (with last deployment lookup) on the App Instance view page.
  • Updates Lagoon/Amazee AI related dependencies and enhances Lagoon token initialization diagnostics.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Feature/Filament/CreatePolydockAppInstanceTest.php Import ordering tweak.
tests/Feature/Console/Commands/RunLagoonCommandOnAppInstancesTest.php Adds feature tests for the new command execution workflow.
config/polydock.php Changes Amazee AI backend provider debug default.
composer.json Bumps Lagoon/Polydock-related package versions.
composer.lock Locks updated dependency graph (incl. new packages).
app/Services/LagoonClientService.php Centralizes Lagoon client config + SSH token retrieval + GraphQL initialization.
app/PolydockServiceProviders/PolydockServiceProviderFTLagoon.php Improves token caching/error diagnostics; throws on missing token.
app/PolydockEngine/Engine.php Adjusts required-variable validation and backfills Lagoon runtime defaults on legacy instances.
app/Filament/Admin/Resources/UserRemoteRegistrationResource.php Removes unused import.
app/Filament/Admin/Resources/PolydockAppInstanceResource/Pages/ViewPolydockAppInstance.php Adds “Trigger Deploy” action + last deployment display via Lagoon API.
app/Console/Commands/TriggerLagoonDeployOnAppInstances.php New bulk deploy-trigger command (API-based, optional concurrency).
app/Console/Commands/TriggerLagoonDeployOnAppInstance.php New single-instance deploy-trigger command (API-based).
app/Console/Commands/RunLagoonCommandOnAppInstances.php New bulk command-runner via Lagoon API with allowlist + optional concurrency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +41
file_put_contents(base_path('tests/fixtures/lagoon-private-key'), 'dummy-key');

$this->app->instance('polydock.lagoon.token_fetcher', fn () => 'fake-token');

$mock = \Mockery::mock(Client::class);
$mock->shouldReceive('setLagoonToken')->with('fake-token')->once();
$mock->shouldReceive('initGraphqlClient')->once();
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LagoonClientService::getLagoonToken() invokes the bound polydock.lagoon.token_fetcher callable with the $config array, but the test binds a zero-arg closure. This will throw an ArgumentCountError when the command runs. Bind a callable that accepts the config parameter (e.g., fn (array $config) => 'fake-token') or change the service to support zero-arg fetchers.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Comment on lines +161 to +183
$phpBinary = PHP_BINARY;
$artisan = base_path('artisan');
$commandBase = [
$phpBinary,
$artisan,
'polydock:instances:run-lagoon-command',
$appUuid,
'--force',
];

if ($envOverride) {
$commandBase[] = "--environment={$envOverride}";
}
if ($variablesOnly) {
$commandBase[] = '--variables-only';
}

$pool = Process::pool(function (Pool $pool) use ($instances, $commandBase) {
foreach ($instances as $instance) {
$command = array_merge($commandBase, ["--instance-id={$instance->id}"]);
$pool->as($instance->id)->command($command);
}
});
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concurrent mode builds a child-process command for polydock:instances:run-lagoon-command but omits the required command_name argument and points at the wrong command entirely for deployments. As written, the spawned processes will fail to start (and no deploy will be triggered). Consider adding an --instance-id worker mode to this command and have the pool call polydock:instances:trigger-deploy (or call polydock:app-instance:trigger-deploy per instance) with the correct args/options instead of run-lagoon-command.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI commented Mar 16, 2026

@dan2k3k4 I've opened a new pull request, #96, to work on those changes. Once the pull request is ready, I'll request review from you.

dan2k3k4 and others added 2 commits March 16, 2026 12:33
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…/ViewPolydockAppInstance.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI commented Mar 16, 2026

@dan2k3k4 I've opened a new pull request, #97, to work on those changes. Once the pull request is ready, I'll request review from you.

…not Artisan CLI wrapper) (#97)

* refactor: use LagoonClientService directly in Trigger Deploy admin action
* fix: update token_fetcher closures in tests to accept array config parameter
@dan2k3k4 dan2k3k4 merged commit 577b5bf into main Mar 17, 2026
1 check passed
@dan2k3k4 dan2k3k4 deleted the add-trigger-deploy-and-lagoon-command branch March 17, 2026 06:36
dan2k3k4 added a commit that referenced this pull request Mar 17, 2026
* feat: Trigger Lagoon Deployments for App Instances (#56)

* chore: artisan add trigger lagoon deploy and run lagoon commands on app instances

* chore: add a button to trigger a deploy from app instance

* Use upstream lib Ssh code

* chore: add support for buildVariables

* chore: only cache token for 2min

* chore: tweak label

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: fix deploy cmd

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: cleanup test ssh

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: run pint

* feat: add api token management, app class discovery, and enhanced store/app configuration (#68)

feat: add Lagoon Script Configuration section with lifecycle scripts for app management
feat: enhance registration response with additional Lagoon project details
fix: update response keys in RegisterController for consistency with underscore naming convention
fix error for missing lagoon-auto-idle variables, including tests
feat: add Lagoon runtime settings to Polydock Store App configuration and infolist
feat: implement API token management and access control with middleware
fix: handle null appInstance in user remote registration URL generation
chore: add amazeeio/polydock-app-amazeeclaw dependency to composer.json
chore: update dependencies in composer.json and composer.lock to latest versions
chore: move internal package dependencies to ^0.1
chore: refresh composer lock for v0.1.1 package releases
chore: update polydock-app-amazeeclaw requirement and lockfile so Polydoc consumes the new store-level app-specific configuration field behavior.
chore: update polydock-engine to consume the latest amazeeclaw release and refresh composer.lock via Dockerized composer to keep dependency resolution reproducible.
fix: update route for instance registration and add authentication middleware
fix: changed the route for showing instance registration from '/instances/{uuid}' to '/register/{uuid}' and added a TODO comment regarding future CRUD endpoint implementation.
fix: wrong helpertext for autoIdle - only allow 0/1 (off/on)
chore: artisan add trigger lagoon deploy and run lagoon commands on app instances
chore: add a button to trigger a deploy from app instance
chore: use upstream lib Ssh code
chore: add support for buildVariables
chore: update error handling for trigger deploy
chore: trigger deploy via api instead of lagoon cli
chore: only cache token for 2min
chore: enable debug with env var options
chore: fix concurrent calling
chore: create and cleanup ssh keys in tests
chore: implement getSearchResultsUsing to prevent memory-heavy query
chore: lookup uuid for instance

---------

Co-authored-by: Michael Schmid <michael.schmid@amazee.io>

* chore: Adds wildcards to allow removing multiple emails at once (#31)

* Adds wildcards
* chore: update app/Console/Commands/RemoveAppInstancesByEmail.php

---------

Co-authored-by: Blaize Kaye <blaize.kaye@amazee.io>
Co-authored-by: Dan Lemon <daniel.lemon@amazee.io>

* chore: add scramble docs / openapi endpoint (#91)

* chore: add endpoints for moad

- chore: switch to scramble
- chore: force openapi output to be `api/openapi.json` endpoint

* chore: check for running instance

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: bump deps

* Bump league/commonmark from 2.8.0 to 2.8.1 (#92)

Bumps [league/commonmark](https://github.com/thephpleague/commonmark) from 2.8.0 to 2.8.1.
- [Release notes](https://github.com/thephpleague/commonmark/releases)
- [Changelog](https://github.com/thephpleague/commonmark/blob/2.8/CHANGELOG.md)
- [Commits](thephpleague/commonmark@2.8.0...2.8.1)

---
updated-dependencies:
- dependency-name: league/commonmark
  dependency-version: 2.8.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump rollup from 4.53.5 to 4.59.0 (#89)

Bumps [rollup](https://github.com/rollup/rollup) from 4.53.5 to 4.59.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](rollup/rollup@v4.53.5...v4.59.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-version: 4.59.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump minimatch and editorconfig (#90)

Bumps [minimatch](https://github.com/isaacs/minimatch) and [editorconfig](https://github.com/editorconfig/editorconfig-core-js). These dependencies needed to be updated together.

Updates `minimatch` from 9.0.1 to 9.0.7
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](isaacs/minimatch@v9.0.1...v9.0.7)

Updates `editorconfig` from 1.0.4 to 1.0.7
- [Release notes](https://github.com/editorconfig/editorconfig-core-js/releases)
- [Changelog](https://github.com/editorconfig/editorconfig-core-js/blob/main/CHANGELOG.md)
- [Commits](editorconfig/editorconfig-core-js@v1.0.4...v1.0.7)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 9.0.7
  dependency-type: indirect
- dependency-name: editorconfig
  dependency-version: 1.0.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: fix import of DB facade

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Add feature tests for TriggerLagoonDeployOnAppInstances command (#101)

* Initial plan

* feat: add TriggerLagoonDeployOnAppInstancesTest feature tests

Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

* Pre-fetch Lagoon token once in coordinator to avoid per-worker SSH bursts (#100)

* Initial plan

* Pre-fetch Lagoon token once in coordinator; pass to concurrent workers via env var

Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

* chore: trigger deploy

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: enhance validation

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Enforce Sanctum token abilities on authenticated API routes (#102)

* Initial plan

* feat: apply instances.read/write ability middleware to API routes

Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

* chore: fix tests

* fix: use isolated temp directory for SSH key in skipped-metadata test (#103)

* Initial plan

* fix: use temp directory for key file in test_it_skips_instances_missing_metadata

Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Michael Schmid <michael.schmid@amazee.io>
Co-authored-by: Blaize Kaye <blaize.kaye@gmail.com>
Co-authored-by: Blaize Kaye <blaize.kaye@amazee.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: dan2k3k4 <158704+dan2k3k4@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants