evolution / wordpress

Rapidly create, develop, & deploy WordPress across multiple environments.
MIT License
200 stars 18 forks source link

Autoupdate reverting commits that are not yet deployed #175

Closed EvanK closed 6 years ago

EvanK commented 6 years ago

In the scope of our auto updates, there are two copies of the site on the updating server; the deployed copy, and the cloned copy.

Currently, the update script will:

  1. apply any updates (via wp-cli) against the deployed copy
  2. create a fresh clone in a temp directory, on the given branch
  3. copy specific files and directories from the deployed to the cloned
  4. commit any changes to the clone and push to the git origin

Say your versioned site has three revisions:

  A ------- Initial commit (3 days ago)
  B ------- Bug fix (24 hours ago)
  C ------- Style fix (12 hours ago)

Let's say you create the site in revision A and deploy it. Later, someone else comes along and makes two new revisions on the same branch, but does not immediately deploy them.

Now your deployed copy is on revision A, but the cloned copy is created on revision C (because git clones the latest or HEAD revision of a given branch on checkout).

By applying the deployed copy on top of the cloned copy, we effectively (and unwittingly) revert B and C, and commit it as revision D. I've tested and reproduced this scenario:

evo-updates-bug

To address this, the update script will take additional steps when creating the cloned copy:

  1. create a fresh clone on the given branch
  2. checkout the clone to the same revision as the deployed copy
  3. apply the changes from the deployed to the cloned
  4. generate a diff file of said changes
  5. checkout the clone to the HEAD revision of the branch, and apply the diff against it
  6. commit any changes as normal

This will ensure that we don't revert any not yet deployed commits, but still create a new commit at the HEAD of the branch. I've tested this fix in the same scenario as above:

evo-updates-fix

Note: this fix will require reprovisioning of a remote server (to ensure the update script is itself updated), and so needs to bump the minor version rather than the patch version.