Skip to content

Feature/dev pull command - #18

Merged
sak0a merged 21 commits into
masterfrom
feature/dev-pull-command
Feb 7, 2026
Merged

sak0a merged 21 commits into
masterfrom
feature/dev-pull-command

Conversation

@sak0a

@sak0a sak0a commented Feb 7, 2026

Copy link
Copy Markdown
Owner

This pull request introduces a new development command for the Notur framework, allowing developers to pull unreleased commits directly from GitHub and update their local framework installation for testing. It also adds a new configuration option for specifying the GitHub repository and updates documentation to reflect these features and the new framework version.

New development features:

  • Added the notur:dev:pull Artisan command (src/Console/Commands/DevPullCommand.php), which downloads a branch or commit from GitHub, replaces files in vendor/notur/notur/, rebuilds the frontend bridge, and supports --no-rebuild and --dry-run options.
  • Registered the DevPullCommand in the service provider (src/NoturServiceProvider.php) so it is available in Artisan. [1] [2]

Configuration enhancements:

  • Added a new repository config key to config/notur.php for specifying the GitHub repository used by notur:dev:pull (defaults to sak0a/notur).

Documentation updates:

  • Updated the admin guide (website/docs/admin/guide.md) to document the new notur:dev:pull command and explain its usage and configuration. [1] [2]
  • Added a changelog entry for version 1.2.4, summarizing the new command, config key, and version bump.

Version bump:

  • Increased the framework version to 1.2.4 in config/notur.php and updated the command count in documentation. [1] [2]

sak0a added 2 commits February 7, 2026 08:39
- Introduced 'repository' configuration in notur.php for GitHub source code.
- Registered DevPullCommand in NoturServiceProvider for enhanced development workflow.
…ntegration

- Bumped framework version to 1.2.4 in configuration.
- Introduced `notur:dev:pull` command to facilitate pulling updates from GitHub, including options for specific branches and dry-run functionality.
- Added `repository` configuration key for GitHub source management.
- Updated documentation to reflect new command and configuration changes.
Copilot AI review requested due to automatic review settings February 7, 2026 16:44
@sak0a sak0a self-assigned this Feb 7, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf01adb5a7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +305 to +318
private function resolvePackageManager(string $cwd): string
{
if (file_exists($cwd . '/bun.lockb') || file_exists($cwd . '/bun.lock')) {
return 'bun';
}
if (file_exists($cwd . '/pnpm-lock.yaml')) {
return 'pnpm';
}
if (file_exists($cwd . '/yarn.lock')) {
return 'yarn';
}

return 'bun';
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Detect npm installs in package manager selection

If the pulled framework (or a fork) uses npm and only has a package-lock.json, resolvePackageManager still falls back to bun, which will fail on systems without Bun and prevents the rebuild steps from running even though npm is available. This makes notur:dev:pull unreliable for npm-based setups. Consider checking for package-lock.json and returning npm (or defaulting to npm when no lock file is found).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@codex adress this feedback

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

Testing

  • ⚠️ not run (not requested)

View task →

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Notur development workflow for pulling unreleased framework code from GitHub into the local Composer-installed framework directory, with corresponding config and documentation updates.

Changes:

  • Introduces notur:dev:pull Artisan command to download/extract a GitHub commit and optionally rebuild bridge assets.
  • Registers the new command and adds notur.repository configuration (default sak0a/notur).
  • Updates docs/changelog and bumps framework version to 1.2.4.

Reviewed changes

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

Show a summary per file
File Description
src/Console/Commands/DevPullCommand.php New command that fetches commit info, downloads/extracts zipball, replaces vendor/notur/notur, and rebuilds frontend assets.
src/NoturServiceProvider.php Registers the new DevPullCommand with Artisan.
config/notur.php Bumps version to 1.2.4 and adds repository config key.
website/docs/admin/guide.md Documents notur:dev:pull usage and the new repository config option.
website/docs/reference/changelog.md Adds 1.2.4 changelog entry describing the new command/config.
CLAUDE.md Updates documented Artisan command count/list to include notur:dev:pull.

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

Comment on lines +320 to +349
private function runProcess(string $command, string $cwd): int
{
$process = proc_open(
$command,
[1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes,
$cwd,
);

if (!is_resource($process)) {
return 1;
}

$output = stream_get_contents($pipes[1]);
$errors = stream_get_contents($pipes[2]);

fclose($pipes[1]);
fclose($pipes[2]);

$exitCode = proc_close($process);

if ($output) {
$this->line($output);
}
if ($errors && $exitCode !== 0) {
$this->error($errors);
}

return $exitCode;
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

runProcess() is duplicated from BuildCommand with identical implementation. Consider extracting this into a shared helper/trait (or a small internal service) so process execution behavior stays consistent across commands and future fixes only need to be made once.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +53
public function handle(): int
{
$branch = $this->argument('branch');
$commit = $this->argument('commit');
$ref = $commit ?? $branch;
$isDryRun = (bool) $this->option('dry-run');
$noRebuild = (bool) $this->option('no-rebuild');

$repo = config('notur.repository', self::DEFAULT_REPO);
$noturRoot = base_path('vendor/notur/notur');

$client = new Client([
'timeout' => 30,
'connect_timeout' => 10,
'headers' => [
'Accept' => 'application/vnd.github.v3+json',
'User-Agent' => 'Notur-DevPull/1.0',
],
]);

// Step 1: Fetch commit info
$this->info("Fetching commit info for '{$ref}' from {$repo}...");

try {
$commitInfo = $this->fetchCommitInfo($client, $repo, $ref);
} catch (\Throwable $e) {
$this->error("Failed to fetch commit info: {$e->getMessage()}");
return 1;
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

There are integration tests for other Artisan commands under tests/Integration/Console/, but this new command has no coverage. Consider adding tests that fake the GitHub API responses and exercise at least the --dry-run path and error handling paths (e.g. invalid ref / download failure).

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner 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 +193 to +199
private function fetchCommitInfo(Client $client, string $repo, string $ref): array
{
$url = self::GITHUB_API_BASE . "/repos/{$repo}/commits/{$ref}";

try {
$response = $client->get($url);
} catch (GuzzleException $e) {

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

$ref is interpolated directly into the GitHub API URL. Branch names commonly contain slashes (e.g. feature/foo), which will break the /commits/{ref} path and cause 404s. URL-encode the ref (and ideally validate/sanitize it) before building the request URL.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner 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 +234 to +248
private function extractArchive(string $zipPath, string $targetDir): string
{
if (!is_dir($targetDir)) {
mkdir($targetDir, 0755, true);
}

$zip = new \ZipArchive();
$result = $zip->open($zipPath);

if ($result !== true) {
throw new \RuntimeException("Failed to open zip archive (error code: {$result})");
}

$zip->extractTo($targetDir);
$zip->close();

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

ZipArchive::extractTo() is called on an untrusted zip without validating entry paths. A crafted archive could use path traversal (e.g. ../) to write outside the temp directory before files are copied into vendor/. Validate all zip entry names (no absolute paths, no .. segments) and/or extract entries manually to a controlled location.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner 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 +103 to +112
// Step 4: Extract to temp directory
$tmpDir = sys_get_temp_dir() . '/notur-dev-pull-extract-' . uniqid();

try {
$innerDir = $this->extractArchive($tmpZip, $tmpDir);
} catch (\Throwable $e) {
$this->error("Extraction failed: {$e->getMessage()}");
@unlink($tmpZip);
return 1;
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

If extraction fails, the temporary extraction directory created at $tmpDir is not cleaned up, which can leak directories in the system temp folder. Ensure the catch block deletes $tmpDir (when it exists) before returning.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner 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 thread src/Console/Commands/DevPullCommand.php
Comment on lines +269 to +296
foreach ($preserveDirs as $dir) {
$dirPath = $noturRoot . '/' . $dir;
if (is_dir($dirPath)) {
if (!is_dir($tmpPreserve)) {
mkdir($tmpPreserve, 0755, true);
}
rename($dirPath, $tmpPreserve . '/' . $dir);
}
}

// Delete old vendor/notur/notur/ contents
if (is_dir($noturRoot)) {
$this->deleteDirectory($noturRoot);
}

// Copy new files
$this->copyDirectory($sourcePath, $noturRoot);

// Restore preserved directories
foreach ($preserveDirs as $dir) {
$tmpSource = $tmpPreserve . '/' . $dir;
if (is_dir($tmpSource)) {
$destPath = $noturRoot . '/' . $dir;
if (is_dir($destPath)) {
$this->deleteDirectory($destPath);
}
rename($tmpSource, $destPath);
}

Copilot AI Feb 7, 2026

Copy link

Choose a reason for hiding this comment

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

rename() results are not checked when preserving/restoring vendor/ and node_modules/. If a rename fails (permissions, locks, etc.), the command can silently proceed and later delete/overwrite directories, potentially losing install artifacts. Check the return values and abort with a clear error if a preserve/restore move fails.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Owner 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

Copilot AI commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

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

Copilot AI commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

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

Copilot AI commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

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

Copilot AI commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

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

Copilot AI commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

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

sak0a and others added 8 commits February 7, 2026 18:09
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
sak0a and others added 6 commits February 7, 2026 18:18
Add integration tests for DevPullCommand
URL-encode branch refs in DevPullCommand GitHub API requests
Co-authored-by: sak0a <24781653+sak0a@users.noreply.github.com>
Add error checking for rename() calls in DevPullCommand
Fix temp directory leak on extraction failure in DevPullCommand
- Removed the constructor dependency for the HTTP client and added a private method `resolveClient()` to handle client instantiation.
- Moved validation for the Notur installation directory to occur before making changes, ensuring better error handling for directory existence and writability.
@sak0a
sak0a merged commit 2727d8d into master Feb 7, 2026
11 checks passed
@sak0a
sak0a deleted the feature/dev-pull-command branch February 7, 2026 17:37
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.

3 participants