Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions library/Tiger/Module/Github.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,15 @@ public static function latestRef($org, $repo)
}

/**
* GitHub's codeload tarball URL for a ref (redirects; download() follows).
* The GitHub API tarball endpoint for a ref — a 302 to a signed codeload URL (download() follows).
*
* We use the API endpoint (`api.github.com/repos/{org}/{repo}/tarball/{ref}`), NOT the web archive
* path (`github.com/{org}/{repo}/archive/{ref}.tar.gz`): the web path 404s for a PRIVATE repo even
* with a valid bearer token, whereas the API endpoint honours the token and 302s to a signed codeload
* URL (which then needs no auth — curl drops the Authorization header on the cross-host redirect). The
* API endpoint works for public repos too, so this one URL serves both the public directory and an
* authenticated private/company source. (The licensed/authority path mints its own signed URL and does
* not come through here.)
*
* @param string $org the repo owner
* @param string $repo the repo name
Expand All @@ -127,7 +135,7 @@ public static function latestRef($org, $repo)
*/
public static function tarballUrl($org, $repo, $ref)
{
return "https://github.com/{$org}/{$repo}/archive/" . rawurlencode((string) $ref) . '.tar.gz';
return self::API . "/repos/{$org}/{$repo}/tarball/" . rawurlencode((string) $ref);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions tests/Unit/Module/GithubParseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

/**
* Tiger_Module_Github — the pure, network-free surface: parseRepo (every URL/slug shape it must accept or
* reject) and tarballUrl (the codeload archive URL it builds, ref-encoded). The HTTP methods (fetchRaw /
* reject) and tarballUrl (the API tarball URL it builds, ref-encoded). The HTTP methods (fetchRaw /
* latestRef / download / get / _http) are live-network territory and are exercised only in integration.
*/
#[CoversClass(Tiger_Module_Github::class)]
Expand Down Expand Up @@ -41,15 +41,15 @@ public function parse_repo_returns_null_for_garbage(): void
}

#[Test]
public function tarball_url_builds_a_ref_encoded_codeload_archive_url(): void
public function tarball_url_builds_a_ref_encoded_api_tarball_url(): void
{
$this->assertSame(
'https://github.com/acme/widget/archive/v1.2.0.tar.gz',
'https://api.github.com/repos/acme/widget/tarball/v1.2.0',
Tiger_Module_Github::tarballUrl('acme', 'widget', 'v1.2.0')
);
// A ref with a slash (a branch like release/1.x) is percent-encoded.
$this->assertSame(
'https://github.com/acme/widget/archive/release%2F1.x.tar.gz',
'https://api.github.com/repos/acme/widget/tarball/release%2F1.x',
Tiger_Module_Github::tarballUrl('acme', 'widget', 'release/1.x')
);
}
Expand Down
8 changes: 5 additions & 3 deletions tests/Unit/Module/GithubTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,17 @@ public function unrecognizedReferencesParseToNull(): void
// ---- tarballUrl ------------------------------------------------------------

#[Test]
public function tarballUrlBuildsCodeloadWithAnEncodedRef(): void
public function tarballUrlBuildsTheApiEndpointWithAnEncodedRef(): void
{
// The API tarball endpoint — honours a bearer token for PRIVATE repos (the web /archive/ path
// 404s for those) and 302s to codeload; works for public repos too.
$this->assertSame(
'https://github.com/WebTigers/TigerDocs/archive/v1.2.3-beta.tar.gz',
'https://api.github.com/repos/WebTigers/TigerDocs/tarball/v1.2.3-beta',
Tiger_Module_Github::tarballUrl('WebTigers', 'TigerDocs', 'v1.2.3-beta')
);
// A ref with a slash (a branch like feature/x) is rawurlencoded so the URL stays well-formed.
$this->assertSame(
'https://github.com/o/r/archive/feature%2Fx.tar.gz',
'https://api.github.com/repos/o/r/tarball/feature%2Fx',
Tiger_Module_Github::tarballUrl('o', 'r', 'feature/x')
);
}
Expand Down
Loading