0

I have a project that uses another GitHub project of mine as a dependency. I have two requirements for my Composer configuration for this dependency:

  • When I'm working locally, I need composer install --prefer-source to symlink to my local copy of the dependency so I can run git commands inside the dependency.
  • When my build process is running, I need composer install --prefer-dist to install directly from the GitHub repository with no symlinking.

Previously I had used the following inside composer.json to achieve the first requirement:

  "require": {
    "narthur/natlib": "@dev"
  },
  "repositories": [
    {
      "type": "path",
      "url": "../natlib",
      "options": {
        "symlink": true
      }
    }
  ]

After some work, I came up with this, which manages to satisfy the second requirement:

  "require": {
    "narthur/natlib": "@dev"
  },
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "narthur/natlib",
        "version": "2019.06.20",
        "dist": {
          "type": "zip",
          "url": "https://github.com/narthur/natlib/archive/master.zip"
        },
        "source": {
          "type": "path",
          "url": "../natlib",
          "reference": "master",
          "options": {
            "symlink": true
          }
        }
      }
    }
  ]

This works great in CI. But when I delete my local vendor/ dir and composer.lock file and run composer install --prefer-source, I get the following exception:

[LogicException]
Downloader "Composer\Downloader\PathDownloader" is a dist type downloader and can not be used to download source for package narthur/natlib-2019.06.20.0

I tried separating them into two repository entries like this:

{
  "type": "path",
  "url": "../natlib",
  "options": {
    "symlink": true
  }
},
{
  "type": "package",
  "package": {
    "name": "narthur/natlib",
    "version": "2019.06.20",
    "dist": {
      "type": "zip",
      "url": "https://github.com/narthur/natlib/archive/master.zip"
    }
  }
}

This works locally, symlinking the dependency, but fails in CI, because Composer stops at the first matching repository entry:

Order is significant here. When looking for a package, Composer will look from the first to the last repository, and pick the first match.

How can I configure Composer to behave the way I want, such that locally the --prefer-source flag will symlink the dependency, while in CI the --prefer-dist flag will pull in the repository?

Information I've found:

Nathan Arthur
  • 8,287
  • 7
  • 55
  • 80
  • 1
    You could work around the mentioned limit for dist repositories (having to specify the location of the archive) by specyfing the release url for your github-repository, e.g. `https://github.com/narthur/natlib/releases/latest`. Does that help? – dbrumann Jun 21 '19 at 06:11
  • @dbrumann Yes! That helped me fix the CI part of this. I've updated my question to show what I have now. Unfortunately, it's still not symlinking the dependency locally when I use `--prefer-source`. – Nathan Arthur Jun 21 '19 at 16:16

1 Answers1

0

I realized my requirements were probably unnecessary. Since my dependency is hosted on GitHub, I can pull it the same way locally and remotely, and make changes to the dependency inside its vendor folder, pushing back to GitHub from there.

Here's what I'm using now:

  "require": {
    "narthur/natlib": "@dev"
  },
  "repositories": [
    {
      "type": "vcs",
      "url": "https://github.com/narthur/natlib"
    }
  ]

One gotcha I ran into when making this shift was that I initially tried going with a package-type repository instead of a simple vcs-type one. This didn't work because it caused Composer to ignore the dependency's composer.json file, preventing it from being autoloaded. After switching to the simple vcs entry above, everything works perfectly.

Nathan Arthur
  • 8,287
  • 7
  • 55
  • 80