35

I am trying to run a build for a Node.js project using GitHub Actions. As part of the npm install, I need to install an npm module directly from a private GitHub repository (not from GPR!).

In the package.json I have:

"dependencies": {
  ...
  "my-module": "github:<org>/<my-module>#master",
  ...
},

However, when running npm install, I get:

npm ERR! git@github.com: Permission denied (publickey). npm ERR! fatal: Could not read from remote repository.

The repository is part of my own organization, and locally (i.e. from my machine) it works. How can I make this run?

I have already tried setting the NODE_AUTH_TOKEN environment variable, but it didn't make a difference. Although you find this suggestion quite often, it seems to only address GPR. What I would like to avoid is having to hardcode the token into the package.json file. Any thoughts on this?

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • Does this answer your question? [npm install private github repositories by dependency in package.json](https://stackoverflow.com/questions/23210437/npm-install-private-github-repositories-by-dependency-in-package-json) – smac89 Jan 08 '20 at 19:00
  • More specifically, this answer in the above linked question: https://stackoverflow.com/a/40312033/2089675 – smac89 Jan 08 '20 at 19:01
  • This didn't work for me. – Golo Roden Jan 09 '20 at 13:28
  • I'm not sure what didn't work, but you may also want to try changing the url that you use for the repo. From the error message you are getting, it looks like npm is trying to resolve the url, using ssh instead of http(s). In that question page I linked, some answers show a different syntax for working with http(s) urls and this may aid in ensuring that the github token is used rather than expecting an ssh key – smac89 Jan 09 '20 at 15:37

4 Answers4

36

This is how I have managed to install dependencies from private GitHub repositories.

Dependencies in package.json can be added as follows. The github: prefix is optional. Specifying the #branch or #tag is also optional.

    "dependencies": {
        ...
        "myrepo": "username/myrepo#master",
        "myotherrepo": "github:username/myotherrepo"
    },

Here is an example workflow. PAT is a repo scoped Personal Access Token. It is important to disable persisted credentials on actions/checkout, otherwise they will override your PAT. Note that the git config change persists between steps so you only need to run it once per job.

      - uses: actions/checkout@v2
        with:
          persist-credentials: false
      - uses: actions/setup-node@v1
        with:
          node-version: 12.x
      - run: git config --global url."https://${{ secrets.PAT }}@github.com/".insteadOf ssh://git@github.com/
      - run: npm ci
      ...
peterevans
  • 34,297
  • 7
  • 84
  • 83
  • 2
    works like a charm, this is very useful in case a project has modules but the source is github private repos and not NPM – Allloush Oct 26 '20 at 08:00
  • prefixing a package with `github:` doesn't work at all – Alexander Ciesielski Nov 06 '20 at 16:37
  • Thanks! that work like a charm, including the `github:` prefix. I will also mention that one needs to create the `PAT` secret in the repository secrets – Assaf Sapir May 19 '21 at 06:28
  • @peterevans God bless you, my dude My package file was already using HTTPS URL to the private repo so I changed the ssh://git@github.com/ to https://github.com in the answer and it worked like a charm – Safeer Raees Nov 25 '21 at 10:13
  • Which OAuth scopes do I need to define on the PAT I create for this to work? `public_repo`? Or perhaps `read:packages`? I'm surprised not to see a scope called `private_repo` or something like that… – Shawn May 04 '22 at 22:59
  • 1
    I followed this and it says `npm ERR! remote: Support for password authentication was removed on August 13, 2021.` – Himakar Reddy Jan 25 '23 at 18:18
  • 1
    `git config --global url."https://github-actions:${{ secrets.TOKEN }}@github.com/".insteadOf ssh://git@github.com/` This worked for me. – Himakar Reddy Jan 25 '23 at 22:51
8

A very straightforward solution that requires only read-only access to the repo. Uses GitHub's Deploy Keys and the following action https://github.com/webfactory/ssh-agent

1. Provide a private repo in package.json in the following format:

"dependencies": {
    "repo": "git+ssh://git@github.com:user/private_repo.git",
}

2. Generate a deploy key locally on your machine. Use empty passphrase

ssh-keygen -f my_key

3. Create a deploy key via GitHub UI (prefer read-only). Use contents of my_key.pub

Deploy keys

4. Create a GitHub Actions secret named REPO_SSH_KEY for the target repo via GitHub UI - the one that will be running GitHub Actions. Use contents of my_key – it is a private key

SSH secret

5. Update the GitHub Actions workflow file to look like this

# ...
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Add SSH key to chekout a private repo
        uses: webfactory/ssh-agent@v0.5.4
        with:
          ssh-private-key: ${{ secrets.REPO_SSH_KEY }}

      - name: Checkout code
        uses: actions/checkout@v2
      
      # ...
      # the rest of the steps, including npm install
      # that will successfully access the private repo
Dmytro
  • 5,443
  • 2
  • 52
  • 50
1

From the error and the way you've included the dependency (in package.json), it seems you are not passing authentication credentials (token, ssh.

Refer to this documentation for specifics on Git URLs as Dependencies

It can be done via https and oauth or ssh.

https and oauth: create an access token that has "repo" scope and then use this syntax:

"package-name": "git+https://<github_token>:x-oauth-basic@github.com/<user>/<repo>.git"

or

ssh: Setup ssh and then use this syntax:

"package-name": "git+ssh://git@github.com:<user>/<repo>.git"
(note the use of colon instead of slash before user)
3rdeye7
  • 536
  • 4
  • 25
  • 1
    You can use `x-oauth-basic` approach but make sure to add `persist-credentials: false` to the checkout action as mentioned in a response above. – cSn Dec 14 '20 at 20:04
-3

You should edit your .npmrc file. You can also use npm config

npm config set @myco:registry http://reg.example.com

Please see the following thread for more information: Is there any way to configure multiple registries in a single npmrc file

Ziv Yatziv
  • 133
  • 5