Repository navigation
Can't install forked extension #9759
Copy link
Copy link
Closed
Labels
enhancementa request to improve CLIa request to improve CLIgh-extensionrelating to the gh extension commandrelating to the gh extension commandhelp wantedContributions welcomeContributions welcome
Description
Describe the bug
I have forked an extension and made some improvements. While waiting for the PR to the upstream repo to be reviewed/merged I'd like to share my progress with my colleagues, however I'm unable to install the extension from my fork.
gh version 2.54.0 (2024-08-01)
https://github.com/cli/cli/releases/tag/v2.54.0
Steps to reproduce the behavior
I have tried following commands:
$ gh extensions install IvanRibakov/gh-workflow-stats
$ gh extensions install IvanRibakov/gh-workflow-stats --force
$ gh extensions install IvanRibakov/gh-workflow-stats --force --pin f2286ac
but all of them return the same cryptic error message:
extension is not installable: missing executable
Expected vs actual behavior
Expecting to be able to install an extension from a public fork of a public repo while being able to install the extension from the upstream without issues, instead getting a non-descriptive error.
Logs
Logs
$ GH_DEBUG=api gh extensions install https://github.com/IvanRibakov/gh-workflow-stats --pin f2286ac --force
* Request at 2024-10-15 13:12:09.106395563 +0200 CEST m=+0.050985944
* Request to https://api.github.com/repos/IvanRibakov/gh-workflow-stats/releases/latest
> GET /repos/IvanRibakov/gh-workflow-stats/releases/latest HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Type: application/json; charset=utf-8
> Time-Zone: Europe/Madrid
> User-Agent: GitHub CLI 2.54.0
> X-Gh-Cache-Ttl: 30s
⢿< HTTP/2.0 404 Not Found
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 15 Oct 2024 11:12:14 GMT
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Accepted-Oauth-Scopes: repo
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Api-Version-Selected: 2022-11-28
< X-Github-Media-Type: github.v3; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: 9D5A:37C4BC:D9552DD:DCC2930:670E4E0E
< X-Oauth-Scopes: delete:packages, read:org, repo, workflow, write:packages
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4955
< X-Ratelimit-Reset: 1728991844
< X-Ratelimit-Resource: core
< X-Ratelimit-Used: 45
< X-Xss-Protection: 0
{
"message": "Not Found",
"documentation_url": "https://docs.github.com/rest/releases/releases#get-the-latest-release",
"status": "404"
}
* Request took 5.302112651s
* Request at 2024-10-15 13:12:14.408536288 +0200 CEST m=+5.353126669
* Request to https://api.github.com/repos/IvanRibakov/gh-workflow-stats
> GET /repos/IvanRibakov/gh-workflow-stats HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Type: application/json; charset=utf-8
> Time-Zone: Europe/Madrid
> User-Agent: GitHub CLI 2.54.0
> X-Gh-Cache-Ttl: 30s
...
{
...
"name": "gh-workflow-stats",
"full_name": "IvanRibakov/gh-workflow-stats",
"private": false,
...
}
* Request took 254.775396ms
* Request at 2024-10-15 13:12:14.663345618 +0200 CEST m=+5.607935989
* Request to https://api.github.com/repos/IvanRibakov/gh-workflow-stats/contents/gh-workflow-stats
> GET /repos/IvanRibakov/gh-workflow-stats/contents/gh-workflow-stats HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Type: application/json; charset=utf-8
> Time-Zone: Europe/Madrid
> User-Agent: GitHub CLI 2.54.0
> X-Gh-Cache-Ttl: 30s
⣾< HTTP/2.0 404 Not Found
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 15 Oct 2024 11:12:14 GMT
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Accepted-Oauth-Scopes:
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Api-Version-Selected: 2022-11-28
< X-Github-Media-Type: github.v3; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: 9D5A:37C4BC:D95549D:DCC2AE7:670E4E0E
< X-Oauth-Scopes: delete:packages, read:org, repo, workflow, write:packages
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4953
< X-Ratelimit-Reset: 1728991844
< X-Ratelimit-Resource: core
< X-Ratelimit-Used: 47
< X-Xss-Protection: 0
{
"message": "Not Found",
"documentation_url": "https://docs.github.com/rest/repos/contents#get-repository-content",
"status": "404"
}
* Request took 282.202949ms
extension is not installable: missing executable
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementa request to improve CLIa request to improve CLIgh-extensionrelating to the gh extension commandrelating to the gh extension commandhelp wantedContributions welcomeContributions welcome
Activity
IvanRibakov commentedon Oct 15, 2024
@williammartin thanks for your help with #9760.
I think that can almost allow me to close this one as well. Just one question - what exactly must
--pinpoint to?The docs say:
but clearly it can't be any commit ref since repo is unlikely to contain a commit with the pre-built binary. Is this commit ref simply used to find the release from which to source the binary?
williammartin commentedon Oct 15, 2024
Hey @IvanRibakov,
Thanks for the detailed bug report. I agree that:
Is not a very useful error message. Before figuring out what we do next, let me explain how the extension installation works.
First, we check whether there are installable release artifacts for the given repo and if so, we download the binary and put it in the extension cache. For example, with your upstream extension:
This is known colloquially as a "binary extension".
If the repo doesn't have a release artifact, then we check whether the given repo contains a script of the same name. If there is a script then we
clonethe repo into the extension cache. For example:This is known colloquially as a "script extension".
In your case, since you forked a binary extension but your repo doesn't have any of the release assets, it falls back to checking whether you have a script and then errors when it doesn't find one.
As in #9760, you can probably understand that it's a bit out of scope for us to build a binary extension.
Let me think about what we could do here. Obviously "missing executable" is very unhelpful to start with.
williammartin commentedon Oct 15, 2024
--pinmeans different things depending on whether it is a binary extension or a script extension. As you call out, pinning to areffor a binary extension doesn't make sense. However for a script extension, when we clone the repo locally, we will check out that ref and use the script in there. For example:williammartin commentedon Oct 15, 2024
I'm using the term "script" colloquially because really it's just checking if there is a file with the given name in the provided repo. Even though the codebase refers to it as
script, it could be a binary. It's just that we wouldn't expect binaries to be checked in I suppose.In any case, I think we could do with:
helptext to explain whatinstallis actually looking for.missing executableerror message, though I'll have to think about whether anyone might be relying on the error message in a script.IvanRibakov commentedon Oct 15, 2024
Thanks for the detailed explanation!
It's a pity you had to resort to quoting the source code to explain the extensions mechanism. I have found the Github CLI manual very useful in the past, but it seems that the extensions concept is not as well documented as other (presumably more popular) commands.
I think that is spot on!
williammartin commentedon Oct 23, 2024
Acceptance Criteria
When I run
gh extension install --helpThen there is an explanation of how
ghlooks to install a remote extension.See previous comments for details on what that entails.
Given I have a repo that does not have a release artifact or script that would be acceptable as an extension
When I run
gh extension install <repo>Then I get an informative error message along the lines of "extension is not installable: no acceptable release artifact or script found in the "