One of the most common issues users can experience when setting up a Deploy project is a submodule related error. These can be tricky to diagnose, so, in this post we'll be outlining a number of common errors and checks that can be made in the event of one.
When adding code to your app from another source, for example a library or plugin, you can use Git submodules. Submodules are, in essence, an external Git repository kept as a subdirectory in your own repo.
Git repositories reference submodules using a .gitmodules file which tells Git where to get the submodule from and where the files need to reside in your repository. This allows you to easily update your repository with a new version of the submodule when it has been updated at source.
The most common error experienced occurs when the files have been cloned from another repository, but not added as a submodule meaning no reference has been created. This often results in the following error displayed in Deploy:
No submodule mapping found for path/to/directory
For reference, the normal procedure for adding a new submodule is as follows:
$ git submodule add https://source-repository-url/repository.git path/to/directory
Once this process has completed, a mapping entry will be added to .gitmodules like so:
[submodule "path/to/directory"] path = path/to/directory url = https://source-repository-url/repository.git
If that file and entry is not present, Deploy will not be able to clone the submodule's files and the mapping error will be displayed. In this instance, you can update .gitmodules to contain the correct mapping using the above format as reference.
If you've made any changes, just run the following command to update Git locally:
$ git submodule sync
Then the command below to ensure that everything is present and correct. If it is, you'll see a commit reference checked out from the source repository.
$ git submodule status 012345689abcdef path/to/directory (heads/master)
In a lot of cases such as Wordpress, plugins and themes added as submodules in your repository won't require authentication as they're hosted on public repositories on Github.
However, submodules may be hosted within a private repository. Deploy's process doesn't allow interaction when authenticating with a remote repository, which would normally allow you to enter a username and password in the same way as a local terminal or Git client. Therefore, you'll need to add the repository using SSH authentication.
If needed, you can modify your .gitmodules file to use an SSH URL instead of HTTP, with the following format:
The SSH URL can be easily retrieved from your repository host via the main browser, normally located just above your list of files. If this change is needed, you can run git submodule sync to update it.
For Deploy to be able to authenticate using SSH, your project's public key will need to be added to the source repository's deployment keys. We have a number of articles that describe the process in further detail for the main supported repository hosts in our documentation:
- Adding a deployment key to Bitbucket
- Adding a deployment key to Codebase
- Adding a deployment key to Github
- Adding a deployment key to Gitlab
Otherwise, on a self-hosted repository server it will be a case of adding the key to your authorized_keys file.
Github does have a restriction that only allows a deployment key to be used on a single repository, but they offer a solution whereby you can create a machine user and assign the deployment key to that user, which will then be given access to multiple Github repositories, allowing you to add the key to multiple submodules and/or your main repository, depending on where that's hosted.
More information on this can be found in Github's documentation.
Changes to submodules
Another error that can be difficult to diagnose is the following:
fatal: reference is not a tree: 123456789abcdef Unable to checkout '123456789abcdef' in submodule path 'my-submodule'
This occurs when the local, checked out commit reference doesn't exist in the remote, either because it no longer exists in the remote, or more likely that changes have been committed locally and not pushed there. If it's the later and the changes do need to be pushed, simply navigate to the submodule directory and push them to the remote:
$ cd my-submodule $ git push
Otherwise, if the changes are not intended, you can cd to the submodule directory and checkout a reference that does exist in the remote:
$ cd my-submodule $ git checkout abcdef123456789
Then git submodule status can be run from your root directory to ensure that you now have the correct reference checked out. Once resolved, push the changes and you should be good to go.