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

private submodule checkout fails @v2 #116

Closed
tvainika opened this issue Dec 18, 2019 · 86 comments
Closed

private submodule checkout fails @v2 #116

tvainika opened this issue Dec 18, 2019 · 86 comments
Assignees
Labels
enhancement New feature or request

Comments

@tvainika
Copy link

I've private git submodule, which contains our shared i18n resouces, with same organization owner as my main repo

I've configured git submodule in main repository as

$ cat .gitmodules
[submodule "xxx-i18n"]
	path = xxx-i18n
	url = ../xxx-i18n
	branch = master

Then I added this one from README to my github action workflow.

name: CI

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Checkout submodules
      shell: bash
      run: |
        auth_header="$(git config --local --get http.https://github.com/.extraheader)"
        git submodule sync --recursive
        git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1

I expected this to work.

Instead I got

Checkout submodules
2s
##[error]Process completed with exit code 1.
Run auth_header="$(git config --local --get http.https://github.com/.extraheader)"
  auth_header="$(git config --local --get http.https://github.com/.extraheader)"
  git submodule sync --recursive
  git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
  shell: /bin/bash --noprofile --norc -e -o pipefail {0}
Submodule 'xxx-i18n' (https://github.com/myprivateorg/xxx-i18n) registered for path 'xxx-i18n'
Cloning into '/home/runner/work/my-main-repo/my-main-repo/xxx-i18n'...
remote: Repository not found.
fatal: repository 'https://github.com/myprivateorg/xxx-i18n/' not found
fatal: clone of 'https://github.com/myprivateorg/xxx-i18n' into submodule path '/home/runner/work/my-main-repo/my-main-repo/xxx-i18n' failed
Failed to clone 'xxx-i18n'. Retry scheduled
Cloning into '/home/runner/work/my-main-repo/my-main-repo/xxx-i18n'...
remote: Repository not found.
fatal: repository 'https://github.com/myprivateorg/xxx-i18n/' not found
fatal: clone of 'https://github.com/myprivateorg/xxx-i18n' into submodule path '/home/runner/work/my-main-repo/my-main-repo/xxx-i18n' failed
Failed to clone 'xxx-i18n' a second time, aborting
##[error]Process completed with exit code 1.
@eberkund
Copy link

Sub-modules support was removed in v2, I'm not sure why though

https://github.com/actions/checkout/releases/tag/v2.0.0

@tvainika
Copy link
Author

Sub-modules support was removed in v2, I'm not sure why though

I understood that it refers to another syntax with: submodules as the README I linked gives this new syntax I used.

@tvainika tvainika changed the title submodule checkout fails @v2 private submodule checkout fails @v2 Dec 19, 2019
@da1nerd
Copy link

da1nerd commented Dec 27, 2019

I also need to have sub-module support. When I use v2, there's no .git directory so I cannot perform any commands like checking out sub-modules. For now I'm using v1 to continue my development.

@rodrigorn
Copy link

I have the exact same issue but I just made it work using the Checkout multiple repos (private) example

    - name: Checkout submodule
      uses: actions/checkout@v2.0.0
      with:
        token: '${{ secrets.GITHUB_PAT }}'
        repository: myOrg/myRepo
        path: path/to/submodule
        ref: 'master'

This is working just as a workaround and might not be practical for a project with a lot of submodules, but I hope it helps until #72 is resolved

@ashwinvis
Copy link

@rodrigorn It works for some use cases. Even with a single submodule, it can become inconsistent when the master branch myOrg/myRepo adds commits which are not tracked by the main repo.

@jleni
Copy link

jleni commented Jan 2, 2020

This is actually blocking us from using GitHub actions. I hope it can be prioritized..

@ericsciple
Copy link
Contributor

@tvainika the default token embedded in the main repo does not have access to fetch other private repositories. Instead if you supply token: ${{ secrets.MY_GITHUB_PAT }} then it should work.

@ericsciple
Copy link
Contributor

@neutrinog no .git folder indicates git 2.18 or higher is not in your PATH. I updated the readme earlier today to make that more clear.

@jleni
Copy link

jleni commented Jan 5, 2020

I have the exact same issue but I just made it work using the Checkout multiple repos (private) example

    - name: Checkout submodule
      uses: actions/checkout@v2.0.0
      with:
        token: '${{ secrets.GITHUB_PAT }}'
        repository: myOrg/myRepo
        path: path/to/submodule
        ref: 'master'

This is working just as a workaround and might not be practical for a project with a lot of submodules, but I hope it helps until #72 is resolved

@ericsciplec @rodrigorn is there a better alternative? I would like to avoid maintaining submodule hashes/branches in two different places. This is very error prone..

@m-hilgendorf
Copy link

I'm having the same issue, came here from the readme where it has a section on "Checkout Submodules" that does not work at all for me (I can't checkout any submodule, public or private).

@rodrigorn
Copy link

rodrigorn commented Jan 7, 2020

@ericsciplec @rodrigorn is there a better alternative? I would like to avoid maintaining submodule hashes/branches in two different places. This is very error prone..

I agree completely but haven't found any better solution yet

@Lauszus
Copy link

Lauszus commented Jan 13, 2020

FYI this is what I have been using:

- name: Checkout submodule
  run: |
    git config --file=.gitmodules submodule.lib/YOUR_SUBMODULE.url https://${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com/ORG/YOUR_SUBMODULE.git
    git submodule sync
    git submodule update --init --recursive

@ashwinvis
Copy link

@Lauszus is the CI_TOKEN a personal access token?

@Lauszus
Copy link

Lauszus commented Jan 13, 2020

@ashwinvis yes it is. I have updated my comment to make it more clear.

@jleni
Copy link

jleni commented Jan 13, 2020

mm.. I am tempted to make a python script that does what @Lauszus suggests automatically for for all repositories defined in .gitmodules
@ericsciple what is the timeline for a real fix/improvement to the action?

@Lauszus
Copy link

Lauszus commented Jan 13, 2020

@jleni here's a version that will checkout all repositories defined in .gitmodules :)

It works for both ssh and https:

- name: Checkout submodules using a PAT
  run: |
    git config --file .gitmodules --get-regexp url | while read url; do
      git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
    done
    git submodule sync
    git submodule update --init --recursive

@jleni
Copy link

jleni commented Jan 13, 2020

oh wow! that's awesome!! thanks!!

@samkit-jain
Copy link

@tvainika the default token embedded in the main repo does not have access to fetch other private repositories. Instead if you supply token: ${{ secrets.MY_GITHUB_PAT }} then it should work.

The url in .gitmodules needs to be the https one for this to work.

Example .gitmodules

[submodule "module"]
	path = module
	url = https://github.com/example/module

Example action.yml

name: Test

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          token: ${{ secrets.MY_GITHUB_PAT }}

      - name: Checkout submodules
        shell: bash
        run: |
          auth_header="$(git config --local --get http.https://github.com/.extraheader)"
          git submodule sync --recursive
          git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1

@Lauszus
Copy link

Lauszus commented Jan 15, 2020

@samkit-jain yeah, that is why I ended up using my code above: #116 (comment), as my private repositories use ssh and I do not want to change all my submodules just because of the CI.

@ericsciple
Copy link
Contributor

@Lauszus +1 good point. i think adding inputs for ssh support + submodule support would create a generally frictionless experience for folks looking to checkout submodules.

@daveespo
Copy link

As an alternative to @Lauszus solution to rewrite the .gitmodules file with the HTTP authentication info and a PAT, you could use this Action

https://github.com/webfactory/ssh-agent

You can generate an SSH keypair and add the public key to the repository you need access to (a normal Deploy Key) and then add the private key as a secret in your repo that's running the GH Action

I'm not suggesting this is great, but until there's native support for at least something resembling same-org mutual authentication for actions, this may be as good as it gets.

@alicia
Copy link

alicia commented Feb 7, 2020

Similar to some of the comments above, I got it working with the following, where GITHUB_ACCESS_TOKEN is a personal access token in the format username:token, that is base64 encoded. Would be great for submodules and private submodules to be supported more directly.

git config --global url."https://github.com/".insteadOf "git@github.com:"
git submodule sync --recursive
git -c "http.extraheader=Authorization: basic ${GITHUB_ACCESS_TOKEN}" -c protocol.version=2 submodule update --init --force --recursive --depth=1

@jwsi
Copy link

jwsi commented Feb 7, 2020

I got frustrated switching my submodules from SSH to HTTPS and dealing with PATs so I decided to build my own action for those wishing to checkout private or public submodules via SSH in their workflows: submodule-checkout

@r-k-b
Copy link

r-k-b commented Feb 9, 2020

thanks to @alicia 's work, we also got private ssh submodules working! However, we ended up with a slightly different result:

on: push
jobs:
  check-elm:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Checkout submodules
      shell: bash
      run: |
        # From https://github.com/actions/checkout/issues/116#issuecomment-583221947
        git config --global url."https://github.com/".insteadOf "git@github.com:"
        git submodule sync --recursive
        git -c "http.extraheader=Authorization: basic ${{secrets.GITHUB_ACCESS_TOKEN}}" -c protocol.version=2 submodule update --init --force --recursive --depth=1
    - uses: actions/setup-node@v1
      with:
        node-version: '8.16.0'
    - run: npm run test

The main difference being ${{secrets.GITHUB_ACCESS_TOKEN}} rather than ${GITHUB_ACCESS_TOKEN}.

@chrispat
Copy link
Member

Please see #81 (comment) for some background on why we chose to not implement support for submodules in the initial version of the v2 action.

And keep an eye on the pull requests for a document discussing what features we are looking at adding.

@davidhesselbomvcc
Copy link

davidhesselbomvcc commented Feb 21, 2020

I tried

    steps:
    - uses: actions/checkout@v2
      with:
        token: ${{ secrets.RUNNER_TOKEN }}
        lfs: true
    - name: Checkout submodules
      shell: bash
      run: |
        auth_header="$(git config --local --get http.https://github.com/.extraheader)"
        git submodule sync --recursive
        git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1

but it fails due to LFS stuff:

Downloading [file in the submodule]
Error downloading object: file in the submodule: Smudge error: Error downloading file in the submodule: LFS: Client error: https://github-cloud.s3.amazonaws.com/[a very long URL]

Any ideas?

EDIT: Actually, the result is identical after removing the lfs: true line. Am I using that option wrong?
EDIT2: Replacing that last line with GIT_LFS_SKIP_SMUDGE=1 git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 did it for me.

@766F6964
Copy link

766F6964 commented Mar 4, 2020

@jleni here's a version that will checkout all repositories defined in .gitmodules :)

It works for both ssh and https:

- name: Checkout submodules using a PAT
  run: |
    git config --file .gitmodules --get-regexp url | while read url; do
      git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
    done
    git submodule sync
    git submodule update --init --recursive

This solution seems to work perfectly for linux runners.
However, windows runners seem to have problems with the formatting the syntax.
I am being prompted with the following error:

Run git config --file .gitmodules --get-regexp url | while read url; do
At D:\a\_temp\c3191bea-0f4b-4580-bbb4-1ddf2bbfd947.ps1:2 char:68
+ git config --file .gitmodules --get-regexp url | while read url; do
+                                                                    ~
Missing statement body in do loop.
+ CategoryInfo          : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingLoopStatement

Is this a problem with powershell formatting the commands incorrectly?
Do you have a workaround that works for windows runners too?

@ashwinvis
Copy link

@766F6964 it does not work because it uses piping, while loop and and read which are available in bash. You should try #116 (comment) instead.

@erichfw
Copy link

erichfw commented Aug 15, 2021

For me, the issue was that the default token used by the github action didn't have access to clone the submodule repository. I provided access by creating a new secret in my private repo that contains a copy of my SSH github-private key. This private key provides access to both repositories. For more security, you could also use a more restrictive PAT and the token a keyword. Note that the key used needs to have access to both repositories cos it will be used for cloning the parent repository and the submodule repository.

  steps:
    - uses: actions/checkout@v2
      with: 
        submodules: true
        ssh-key: ${{ secrets.xxx}}

@vavsab
Copy link

vavsab commented Aug 15, 2021

For me, the issue was that the default token used by the github action didn't have access to clone the submodule repository. I provided access by creating a new secret in my private repo that contains a copy of my SSH github-private key. This private key provides access to both repositories. For more security, you could also use a more restrictive PAT and the token a keyword. Note that the key used needs to have access to both repositories cos it will be used for cloning the parent repository and the submodule repository.

  steps:
    - uses: actions/checkout@v2
      with: 
        submodules: true
        ssh-key: ${{ secrets.xxx}}

Did you succeed to add the same SSH public key into 2 repos? In my case github throws an error when I try to add it to the 2nd repo.

@fbernaly
Copy link

What worked: create new personal access token (PAT)

    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        token: ${{ secrets.MY_REPO_PAT }}
        submodules: recursive

This worked for me!! Thanks @ashwinvis

@TiagoGalvaoChange
Copy link

@vavsab when using shaunco/ssh-agent@git-repo-mapping
have you faced the need of pointing to a submodule using repo-mappings with the need to point to specific branch?
with .gitmodules file there is the possibility of defining branch...

@vavsab
Copy link

vavsab commented Dec 8, 2021

@vavsab when using shaunco/ssh-agent@git-repo-mapping have you faced the need of pointing to a submodule using repo-mappings with the need to point to specific branch? with .gitmodules file there is the possibility of defining branch...

@TiagoGalvaoChange no, I haven't. My .gitmodules only contain links to specific commits. So you may fork and add more logic to it to cover your case.

@arolus
Copy link

arolus commented Jul 22, 2022

Maybe it will help somebody. This solution works when you want to keep flexibility of URL repos and still use GitHub Actions with Deploy Keys to access private submodules:

  - name: Checkout
    uses: actions/checkout@v2

  - name: Clone Submodule
    run: |
        mkdir -p $HOME/.ssh
        echo '${{ secrets.SUBMODULE_REPO_DEPLOY_KEY }}' > $HOME/.ssh/ssh.key
        chmod 600 $HOME/.ssh/ssh.key
        export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/ssh.key"
        git submodule set-url <path-to-submodule> git@github.com:<organization/submodule>.git
        git submodule update --init --recursive
        git submodule set-url <path-to-submodule> https://github.com/<organization/submodule>.git
        unset GIT_SSH_COMMAND

@sfullerbeckman
Copy link

sfullerbeckman commented Sep 20, 2022

Maybe it will help somebody. This solution works when you want to keep flexibility of URL repos and still use GitHub Actions with Deploy Keys to access private submodules:

  - name: Checkout
    uses: actions/checkout@v2

  - name: Clone Submodule
    run: |
        mkdir -p $HOME/.ssh
        echo '${{ secrets.SUBMODULE_REPO_DEPLOY_KEY }}' > $HOME/.ssh/ssh.key
        chmod 600 $HOME/.ssh/ssh.key
        export GIT_SSH_COMMAND="ssh -i $HOME/.ssh/ssh.key"
        git submodule set-url <path-to-submodule> git@github.com:<organization/submodule>.git
        git submodule update --init --recursive
        git submodule set-url <path-to-submodule> https://github.com/<organization/submodule>.git
        unset GIT_SSH_COMMAND

@arolus , that doesn't seem to work. The yaml actions file doesn't understand the unset and export keywords

@sfullerbeckman
Copy link

@jleni here's a version that will checkout all repositories defined in .gitmodules :)
It works for both ssh and https:

- name: Checkout submodules using a PAT
  run: |
    git config --file .gitmodules --get-regexp url | while read url; do
      git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
    done
    git submodule sync
    git submodule update --init --recursive

This worked for me. Thanks a lot! 👍

How did this work for you, @iamsushi10 ? I am getting this error.

image

@sfullerbeckman
Copy link

sfullerbeckman commented Sep 21, 2022

@jleni here's a version that will checkout all repositories defined in .gitmodules :)

It works for both ssh and https:

- name: Checkout submodules using a PAT
  run: |
    git config --file .gitmodules --get-regexp url | while read url; do
      git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
    done
    git submodule sync
    git submodule update --init --recursive

I get this error when trying to use your script...

Run git config --file .gitmodules --get-regexp url | while read url; do
sed: -e expression #1, char 86: unterminated `s' command

The script look fine though. Do you know what the issue is @Lauszus ?

@Lauszus
Copy link

Lauszus commented Oct 3, 2022

@jleni here's a version that will checkout all repositories defined in .gitmodules :)
It works for both ssh and https:

- name: Checkout submodules using a PAT
  run: |
    git config --file .gitmodules --get-regexp url | while read url; do
      git config --file=.gitmodules $(echo "$url" | sed -E "s/git@github.com:|https:\/\/github.com\//https:\/\/${{ secrets.CI_PAT }}:${{ secrets.CI_PAT }}@github.com\//")
    done
    git submodule sync
    git submodule update --init --recursive

I get this error when trying to use your script...

Run git config --file .gitmodules --get-regexp url | while read url; do
sed: -e expression #1, char 86: unterminated `s' command

The script look fine though. Do you know what the issue is @Lauszus ?

From your error output it looks like you are running Windows. I don't think my script works with Windows.

albertz added a commit to rwth-i6/returnn that referenced this issue Nov 17, 2022
Need to checkout submodules in CI.

actions/checkout#116
@asaf-kali
Copy link

asaf-kali commented Apr 9, 2023

For anyone who gets here in the future, adding to @fbernaly's comment, when creating a PAT:

  1. Repository access -> Only select repositories -> Give access to both main repo and submodule repo.
  2. Permissions -> Repository permissions -> Give Read-only access to Contents and Metadata.

image

@richw-kai
Copy link

It's a little concerning that the only solution here is to create a PAT. The point of a Github Action is to centralise the deployment process for an organisation, that organisation may have multiple private repositories, for example defining graphql or protobuf contracts. They need importing into each repo during the build process as submodules. To rely on PAT for this process is a security concern as well as an availability risk. If the person who creates the PAT leaves the company, the whole company will now be unable to deploy due to a quite deep down and hidden error within this process.

What is the recommended solution for allowing an organisation to deploy code that references submodules from within their own organisation?

@sfullerbeckman
Copy link

It's a little concerning that the only solution here is to create a PAT. The point of a Github Action is to centralise the deployment process for an organisation, that organisation may have multiple private repositories, for example defining graphql or protobuf contracts. They need importing into each repo during the build process as submodules. To rely on PAT for this process is a security concern as well as an availability risk. If the person who creates the PAT leaves the company, the whole company will now be unable to deploy due to a quite deep down and hidden error within this process.

What is the recommended solution for allowing an organisation to deploy code that references submodules from within their own organisation?

Oh that is true, @richw-kai. I didn't think of that issue with the PAT. I was so focussed on getting it to work in the first place!

@charlielito
Copy link

It's a little concerning that the only solution here is to create a PAT. The point of a Github Action is to centralise the deployment process for an organisation, that organisation may have multiple private repositories, for example defining graphql or protobuf contracts. They need importing into each repo during the build process as submodules. To rely on PAT for this process is a security concern as well as an availability risk. If the person who creates the PAT leaves the company, the whole company will now be unable to deploy due to a quite deep down and hidden error within this process.

What is the recommended solution for allowing an organisation to deploy code that references submodules from within their own organisation?

Because of that, I use GitHub App Installation access tokens which are not directly tied to a user but instead tied to the GitHub App installed in your organization. I use this action to use a previously configured and installed GitHub App to get a special token with more privileges (like access to other organization repos). This other action also seems to do the same. Then, my action would look like:

name: Some test
on:
  pull_request:
jobs:
  some_job:
    runs-on: ubuntu-22.04
    name: Some action
    steps:
      - name: Get token
        id: get_token
        uses: machine-learning-apps/actions-app-token@master
        with:
          APP_PEM: ${{ secrets.AUTH_APP_PEM }}
          APP_ID: ${{ secrets.AUTH_APP_ID }}
      - name: Checkout repository and submodules
        uses: actions/checkout@v3
        with:
          submodules: recursive
          token: ${{ steps.get_token.outputs.app_token }}

@mcolussi-bigw
Copy link

Because of that, I use GitHub App Installation access tokens which are not directly tied to a user but instead tied to the GitHub App installed in your organization.

This worked for me and probably the best solution so far to not tie the submodule checkout permissions to a specific user. The only requirement is the GitHub App needs the read-only to the "Contents" permission.

@Cloudef
Copy link

Cloudef commented Sep 15, 2023

Can't believe there's still no better way to do this

@zhu0629
Copy link

zhu0629 commented Jan 29, 2024

how can i checkout submodules on pull reqeust ???

      - name: Checkout
        if: github.actor == 'dependabot[bot]'
        uses: actions/checkout@v3
        with:
          token: ${{ github.token }}
          submodules: recursive

      - name: Checkout
        if: github.actor != 'dependabot[bot]'
        uses: actions/checkout@v3
        with:
          token: ${{ secrets.GH_PAT }}
          submodules: recursive

${{ github.token }} -> can't checkout submodules -> pull-request can use github.token
${{ secrets.GH_PAT }} -> can checkout submodules -> pull-request can't use secrets

@sfullerbeckman
Copy link

sfullerbeckman commented Jan 29, 2024

This worked for me. After checking out the main repository, my pipeline runs this action to checkout any submodules. It's a little bit hacky, but it has worked for me.

- name: Checkout the repo
        uses: actions/checkout@v3.1.0
        with:
          persist-credentials: false

- name: Checkout submodule
        run: |
          git submodule sync --recursive
          git -c protocol.version=2 submodule update --init --force --depth=1 --recursive

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests