Repository navigation
[Feat] Add Go, Rust and Python application runtimes #1290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| <?php | ||
|
|
||
| namespace App\RuntimePresets; | ||
|
|
||
| use App\Enums\WebMode; | ||
| use App\Support\RepositoryFiles; | ||
| use App\Tooling\GoTooling; | ||
|
|
||
| class Go extends AbstractRuntimePreset | ||
| { | ||
| public static function id(): string | ||
| { | ||
| return 'go'; | ||
| } | ||
|
|
||
| public static function label(): string | ||
| { | ||
| return 'Go'; | ||
| } | ||
|
|
||
| public function versions(): array | ||
| { | ||
| return GoTooling::supportedVersions(); | ||
| } | ||
|
|
||
| public function tooling(): ?string | ||
| { | ||
| return GoTooling::id(); | ||
| } | ||
|
|
||
| public function webMode(): WebMode | ||
| { | ||
| return WebMode::PROXY; | ||
| } | ||
|
|
||
| public function startCommand(): ?string | ||
| { | ||
| return './app'; | ||
| } | ||
|
|
||
| public function detect(RepositoryFiles $files): ?array | ||
| { | ||
| if (! $files->has('go.mod') || $files->has('composer.json')) { | ||
| return null; | ||
| } | ||
| $constraint = $files->get('.go-version'); | ||
| if (! $constraint && preg_match('/^go\h+(\d+\.\d+(?:\.\d+)?)/m', $files->get('go.mod') ?? '', $match)) { | ||
| $constraint = '>='.$match[1]; | ||
| } | ||
|
|
||
| return $this->compatibleVersions($constraint); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| <?php | ||
|
|
||
| namespace App\RuntimePresets; | ||
|
|
||
| use App\Enums\WebMode; | ||
| use App\Support\RepositoryFiles; | ||
| use App\Tooling\PythonTooling; | ||
|
|
||
| class Python extends AbstractRuntimePreset | ||
| { | ||
| public static function id(): string | ||
| { | ||
| return 'python'; | ||
| } | ||
|
|
||
| public static function label(): string | ||
| { | ||
| return 'Python'; | ||
| } | ||
|
|
||
| public function versions(): array | ||
| { | ||
| return PythonTooling::supportedVersions(); | ||
| } | ||
|
|
||
| public function tooling(): ?string | ||
| { | ||
| return PythonTooling::id(); | ||
| } | ||
|
|
||
| public function webMode(): WebMode | ||
| { | ||
| return WebMode::PROXY; | ||
| } | ||
|
|
||
| public function startCommand(): ?string | ||
| { | ||
| return '.venv/bin/python main.py'; | ||
| } | ||
|
|
||
| public function detect(RepositoryFiles $files): ?array | ||
| { | ||
| if ((! $files->has('requirements.txt') && ! $files->has('pyproject.toml') && ! $files->has('setup.py')) || $files->has('composer.json')) { | ||
| return null; | ||
| } | ||
|
|
||
| return $this->compatibleVersions($files->get('.python-version') ?? $files->tomlString('pyproject.toml', 'project', 'requires-python')); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| <?php | ||
|
|
||
| namespace App\RuntimePresets; | ||
|
|
||
| use App\Enums\WebMode; | ||
| use App\Support\RepositoryFiles; | ||
| use App\Tooling\RustTooling; | ||
|
|
||
| class Rust extends AbstractRuntimePreset | ||
| { | ||
| public static function id(): string | ||
| { | ||
| return 'rust'; | ||
| } | ||
|
|
||
| public static function label(): string | ||
| { | ||
| return 'Rust'; | ||
| } | ||
|
|
||
| public function versions(): array | ||
| { | ||
| return RustTooling::supportedVersions(); | ||
| } | ||
|
|
||
| public function tooling(): ?string | ||
| { | ||
| return RustTooling::id(); | ||
| } | ||
|
|
||
| public function webMode(): WebMode | ||
| { | ||
| return WebMode::PROXY; | ||
| } | ||
|
|
||
| public function startCommand(): ?string | ||
| { | ||
| return './target/release/app'; | ||
| } | ||
|
|
||
| public function detect(RepositoryFiles $files): ?array | ||
| { | ||
| if (! $files->has('Cargo.toml') || $files->has('composer.json')) { | ||
| return null; | ||
| } | ||
|
|
||
| $file = $files->has('rust-toolchain') ? 'rust-toolchain' : 'rust-toolchain.toml'; | ||
| $constraint = $files->tomlString($file, 'toolchain', 'channel') ?? ($file === 'rust-toolchain' ? $files->get($file) : null); | ||
|
|
||
| return $this->compatibleVersions($constraint); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,28 @@ public function get(string $path): ?string | |
| return $this->contents[$path]; | ||
| } | ||
|
|
||
| /** | ||
| * Reads single-line quoted hints from a TOML table, ignoring multiline string bodies. | ||
| */ | ||
| public function tomlString(string $path, string $table, string $key): ?string | ||
| { | ||
| $contents = preg_replace( | ||
| <<<'REGEX' | ||
| /"""(?:\\.|(?!""").)*"""|'''.*?'''|(?:"(?:\\.|[^"\\\r\n])*"|'[^'\r\n]*'|#[^\r\n]*)(*SKIP)(*F)/s | ||
| REGEX, | ||
| '', | ||
| $this->get($path) ?? '', | ||
| ) ?? ''; | ||
| if (! preg_match('/^\h*\[\h*'.preg_quote($table, '/').'\h*\]\h*(?:#[^\r\n]*)?\r?$(.*?)(?=^\h*\[|\z)/ms', $contents, $section)) { | ||
| return null; | ||
| } | ||
| if (! preg_match('/^\h*'.preg_quote($key, '/').'\h*=\h*(["\'])([^"\'\r\n]*)\1\h*(?:#[^\r\n]*)?\r?$/m', $section[1], $value)) { | ||
| return null; | ||
| } | ||
|
|
||
| return $value[2]; | ||
|
Comment on lines
+52
to
+56
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| /** | ||
| * @return array<string, mixed> | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php | ||
|
|
||
| namespace App\Tooling; | ||
|
|
||
| class GoTooling extends AbstractMiseTooling | ||
| { | ||
| public static function id(): string | ||
| { | ||
| return 'go'; | ||
| } | ||
|
|
||
| public static function label(): string | ||
| { | ||
| return 'Go'; | ||
| } | ||
|
|
||
| public static function description(): string | ||
| { | ||
| return 'Go toolchain used to build Go applications during deployment.'; | ||
| } | ||
|
|
||
| public static function supportedVersions(): array | ||
| { | ||
| return ['1.27', '1.26', '1.25']; | ||
| } | ||
|
|
||
| public static function commands(): array | ||
| { | ||
| return ['go', 'gofmt']; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php | ||
|
|
||
| namespace App\Tooling; | ||
|
|
||
| class RustTooling extends AbstractMiseTooling | ||
| { | ||
| public static function id(): string | ||
| { | ||
| return 'rust'; | ||
| } | ||
|
|
||
| public static function label(): string | ||
| { | ||
| return 'Rust'; | ||
| } | ||
|
|
||
| public static function description(): string | ||
| { | ||
| return 'Rust toolchain used to build Rust applications during deployment.'; | ||
| } | ||
|
|
||
| public static function supportedVersions(): array | ||
| { | ||
| return ['1.99', '1.98', '1.97']; | ||
| } | ||
|
|
||
| public static function commands(): array | ||
| { | ||
| return ['cargo', 'rustc', 'rustup', 'rustfmt']; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| go mod download | ||
| go build -o app . |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| python -m venv .venv | ||
| if [ -f requirements.txt ]; then | ||
| .venv/bin/python -m pip install -r requirements.txt | ||
| elif [ -f pyproject.toml ] || [ -f setup.py ]; then | ||
| .venv/bin/python -m pip install . | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| if [ -f Cargo.lock ]; then | ||
| cargo build --release --locked | ||
| else | ||
| cargo build --release | ||
| fi |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
rg -n 'class PythonTooling|supportedVersions|runtime_version|mise use|pip install' app/Tooling app/Actions/Application resources/deployment-scripts/presets/pythonRepository: vitodeploy/vito
Length of output: 1592
Script executed:
Repository: vitodeploy/vito
Length of output: 16321
Script executed:
Repository: vitodeploy/vito
Length of output: 6600
Script executed:
Repository: vitodeploy/vito
Length of output: 7848
Web query:
mise python@3.12 version resolution latest patch "mise use python@3.12" documentationResult:
Web query:
pip install Requires-Python enforcement "requires a different Python" pyproject requires-python PEP 440 ==3.12.4Result:
Script executed:
Repository: vitodeploy/vito
Length of output: 4778
Web query:
pip "Requires-Python" check local project "pip install ." error "requires a different Python" pip resolver UnsupportedPythonVersionResult:
Stop suggesting
3.12for an exact patchrequires-pythonpin.satisfies()compares only the minor segment when the tooling version has two segments, so==3.12.4matches3.12. Detection then suggests3.12, and Mise installs the newest 3.12.x release. When the repository has norequirements.txt,pip install .rejects that interpreter. Exclude the suggestion when the pin is exact, or warn before deployment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow-up:
cb3f21a3c17484c80f1bed23b5104fde96d3ed8d.Confirmed the limitation, and documented it explicitly in the Applications guide. The standard Python preset exposes minor series (3.14/3.13/3.12/3.11); both the picker and server-side validation enforce that catalogue. Detection is a best-effort hint, not an exact patch resolver.
Dropping 3.12 here would invoke the existing all-versions fallback and normally preselect 3.14, while returning 3.12.4 would fail supported-version validation. A static creation-form alert is also hidden under Advanced and would not reliably warn before the default automatic deployment.
I’m deferring exact-patch provisioning or a reliably visible detection-warning contract to separate work rather than silently changing the tooling model in this runtime-presets PR. The documentation now calls out
==3.12.4specifically and directs strict-toolchain projects to a prepared Custom runtime/plugin. Leaving this thread open as a documented limitation for maintainer visibility, not claiming the exact-patch case is fixed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@saeedvaziry Understood. The documented limitation does not fix exact-patch provisioning, but your explanation shows why dropping
3.12or returning3.12.4is not a safe local fix.This finding remains open for maintainer visibility, as requested. I will not press for a tooling-model change in this PR.
Would you like me to open a follow-up GitHub issue for exact-patch provisioning or a warning that is visible before automatic deployment?
You are interacting with an AI system.