Skip to content
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

Add a basic SelfUpdateCommand using phar-updater v1 #51

Merged
merged 19 commits into from
Jul 15, 2017

Conversation

padraic
Copy link
Collaborator

@padraic padraic commented Jun 14, 2017

Implements #45

Assumes using Github releases to host a signed phar.

Copy link
Member

@theofidry theofidry left a comment

Choose a reason for hiding this comment

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

First (not in-depth) review

{
$this
->setName('self-update')
->setDescription('Update php-scoper.phar to most recent stable build.')
Copy link
Member

Choose a reason for hiding this comment

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

can the name be changed? I mean the user may have renamed php-scoper.phar to something else e.g. php-scoper or scoper

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Phar::running() should return the file path with the local name, I think.

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
$this->version = $this->getApplication()->getVersion();
Copy link
Member

Choose a reason for hiding this comment

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

can this be done in the constructor?

*/
private function getStableUpdater(): Updater
{
$updater = new Updater();
Copy link
Member

Choose a reason for hiding this comment

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

I didn't check the updater API but is there any reason why the strategy cannot be se in the updater constructor?

Copy link
Member

Choose a reason for hiding this comment

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

can we create the updater in the constructor or better use DI (for mocking in unit tests)?

$oldVersion = $updater->getOldVersion();

if ($result) {
$this->output->writeln('php-scoper has been updated.');
Copy link
Member

Choose a reason for hiding this comment

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

PHP-Scoper

if ($result) {
$this->output->writeln('php-scoper has been updated.');
$this->output->writeln(sprintf(
'Current version is: %s.',
Copy link
Member

Choose a reason for hiding this comment

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

<comment>%s</comment>

$newVersion
));
$this->output->writeln(sprintf(
'Previous version was: %s.',
Copy link
Member

Choose a reason for hiding this comment

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

<comment>%s</comment>

} catch (\Exception $e) {
$this->output->writeln(sprintf('Error: %s', $e->getMessage()));
}
$this->output->write(PHP_EOL);
Copy link
Member

Choose a reason for hiding this comment

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

newLine() or writeln('')

));
}
} catch (\Exception $e) {
$this->output->writeln(sprintf('Error: %s', $e->getMessage()));
Copy link
Member

Choose a reason for hiding this comment

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

is the rollback done in the updater in case of failure? If so we don't actually need to catch the exception as we'll have more information by throwing letting the Console handling the exception

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The basic update flow is to backup the original phar (leaving original still in place), download the new phar to a temporary directory, validate it, and then copy it to the original phar location (overwrite). On error, the temporary copy would be deleted. The rollback is largely in the event that an update is valid, but broken or incompatible for any reason and you want the old version back.

@padraic
Copy link
Collaborator Author

padraic commented Jun 14, 2017

@theofidry Yeah, still a bit of work to tidy this up. Will be tomorrow though :). The output can probably go to a logger somewhere too.

@padraic padraic force-pushed the feature/self-update branch from d618d36 to 97712e7 Compare June 15, 2017 20:07
@padraic
Copy link
Collaborator Author

padraic commented Jun 15, 2017

@theofidry Will look into testing tomorrow. Just cleaned it up and simplified.

@padraic padraic force-pushed the feature/self-update branch from 5c5a604 to 4a0370f Compare June 19, 2017 17:48
@padraic padraic force-pushed the feature/self-update branch from 4a0370f to f4a8cef Compare July 11, 2017 17:17
if ($input->getOption('check')) {
$this->printAvailableUpdates();

return;
Copy link
Member

Choose a reason for hiding this comment

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

return 0;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Null is converted to 0 status automatically isn't it? No harm being explicit though.

/**
* @return Updater
*/
private function getStableUpdater(): Updater
Copy link
Member

Choose a reason for hiding this comment

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

createUpdater()?

Copy link
Member

Choose a reason for hiding this comment

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

Also I think the phpdoc is unneeded here

} else {
$this->logger->updateNotNeeded($oldVersion);
}
} catch (\Exception $e) {
Copy link
Member

Choose a reason for hiding this comment

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

What kind of error can we get? If it's a generic one maybe we should use Throwable instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Any day now I'll wake up and remember PHP 7 was released ;).

@padraic
Copy link
Collaborator Author

padraic commented Jul 11, 2017

Made a few updates. For reference, the local box.json should have added the following new fields not in dist copy:

    "git-version": "git-version",
    "algorithm": "OPENSSL",
    "key": "/path/to/your/private.pem",
    "key-pass": true

Box version we use is pointing at Symfony/Console 3.x as an option, but the underlying commands are not updated to use the Question helper (still using Dialog). Adjusted our own vendor-bin/composer.json to fix.

I may temporarily hijack the 0.1.0 Github release for practical download/rollback testing tomorrow.

The phar will emit a semantic version based off of box's git-version, so it will be one of:

  • x.y.z (typical stable version when phar is build to a tagged commit.
  • x.y.z+15-g0818afa (where + marks anything after as metadata, 15 is the commit count since previous tagged commit, and 0818afa is the current short commit hash prefix with g by box.

@theofidry
Copy link
Member

Box version we use is pointing at Symfony/Console 3.x as an option, but the underlying commands are not updated to use the Question helper (still using Dialog). Adjusted our own vendor-bin/composer.json to fix.

I'm not following. You mean it allows symfony/console 3.x but actually the code is still using 2.x code which as been removed in 3.x?

Nevermind, actually saw that which confirms it. Seems fine by me really 👍

I'm must stay I'm still not sure how the phar updater works exactly as I'm only used to the Composer one.

@padraic
Copy link
Collaborator Author

padraic commented Jul 11, 2017

@theofidry That's the problem - still using Symfony 2's Dialog helper in the background.

The updater works a lot like Composer's - I doubt there's a huge difference between them at the basic level. The differences are all extras to the basic workflow: phar signature support, the strategies (all essentially varying methods of where/how to check for updates, and where to download any updates).

@padraic padraic changed the title [WIP] Add a basic SelfUpdateCommand using phar-updater v1 Add a basic SelfUpdateCommand using phar-updater v1 Jul 13, 2017
@padraic padraic force-pushed the feature/self-update branch from aa19456 to 1c1b9f2 Compare July 13, 2017 20:29
@padraic
Copy link
Collaborator Author

padraic commented Jul 13, 2017

@theofidry All wrapped up here!

Copy link
Member

@theofidry theofidry left a comment

Choose a reason for hiding this comment

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

Some minor comments and I think we're good

$this->logger->updateNotNeeded($oldVersion);
}
} catch (\Throwable $e) {
$this->logger->error($e);
Copy link
Member

Choose a reason for hiding this comment

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

we're not failing here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mostly, it's just to add some preceding text to assure users the phar was not replaced. We could let the Throwable just fall through, but I always find that a bit untidy.

Copy link
Member

Choose a reason for hiding this comment

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

Not sure about this though as we rule out any way for the user to know why it failed. I think throwing the throwable after logging the message would be fine


private function getLocalPharName(): string
{
return basename(\PHAR::running());
Copy link
Member

Choose a reason for hiding this comment

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

This command doesn't work without a PHAR, but can we ensure it fails gracefully?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can you clarify? The SelfUpdateCommand only ever exists in a PHAR, so the above running() call should always succeed.


public function updateSuccess(string $newVersion, string $oldVersion)
{
$this->io->writeln('PHP-Scoper has been updated.');
Copy link
Member

Choose a reason for hiding this comment

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

with SymfonyStyle you also have success(), error() and such for some fancy styling

@theofidry
Copy link
Member

Hum Travis is now failing because of the missing pubkey...

@padraic
Copy link
Collaborator Author

padraic commented Jul 14, 2017

Hmm, phar-updater checks it up front instead of waiting for a request for a pub key to run checks: https://github.com/humbug/phar-updater/blob/master/src/Updater.php#L112

It should be changed in the updater package for these scenarios (unsigned testing). I'll open an issue there. In the meantime, we can probably suppress that exception. For actual updating in RL, the phar itself won't even run if the pubkey were missing.

@padraic padraic force-pushed the feature/self-update branch from 190d945 to 27d97ac Compare July 15, 2017 13:10
@padraic
Copy link
Collaborator Author

padraic commented Jul 15, 2017

@theofidry All comments should be addressed now. Made one change to makefile so we ignore, only during tests, any local box.json (e.g. with privkey config) and use the dist copy instead.

Copy link
Member

@theofidry theofidry left a comment

Choose a reason for hiding this comment

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

Looks good to me. Could you just take a look at Scrutinizer before merging to see if the introduced issues are relevant or not?

@padraic
Copy link
Collaborator Author

padraic commented Jul 15, 2017

@theofidry Made a couple of changes. The remainder on Scrutinizer we can't fix from outside phar-updater.

@theofidry theofidry merged commit 557dce1 into humbug:master Jul 15, 2017
@padraic padraic deleted the feature/self-update branch July 15, 2017 21:33
@theofidry theofidry mentioned this pull request Jul 20, 2017
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.

2 participants