aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/installation/fetch_artifact_release_info.ts
blob: 1ad3b8338ba9b8077650e6c6b93bf62c5976677c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import fetch from "node-fetch";
import { GithubRepo, ArtifactReleaseInfo } from "./interfaces";
import { log } from "../util";

const GITHUB_API_ENDPOINT_URL = "https://api.github.com";

/**
 * Fetches the release with `releaseTag` from GitHub `repo` and
 * returns metadata about `artifactFileName` shipped with
 * this release.
 *
 * @throws Error upon network failure or if no such repository, release, or artifact exists.
 */
export async function fetchArtifactReleaseInfo(
    repo: GithubRepo,
    artifactFileName: string,
    releaseTag: string
): Promise<ArtifactReleaseInfo> {

    const repoOwner = encodeURIComponent(repo.owner);
    const repoName = encodeURIComponent(repo.name);

    const apiEndpointPath = `/repos/${repoOwner}/${repoName}/releases/tags/${releaseTag}`;

    const requestUrl = GITHUB_API_ENDPOINT_URL + apiEndpointPath;

    log.debug("Issuing request for released artifacts metadata to", requestUrl);

    const response = await fetch(requestUrl, { headers: { Accept: "application/vnd.github.v3+json" } });

    if (!response.ok) {
        log.error("Error fetching artifact release info", {
            requestUrl,
            releaseTag,
            artifactFileName,
            response: {
                headers: response.headers,
                status: response.status,
                body: await response.text(),
            }
        });

        throw new Error(
            `Got response ${response.status} when trying to fetch ` +
            `"${artifactFileName}" artifact release info for ${releaseTag} release`
        );
    }

    // We skip runtime type checks for simplicity (here we cast from `any` to `GithubRelease`)
    const release: GithubRelease = await response.json();

    const artifact = release.assets.find(artifact => artifact.name === artifactFileName);

    if (!artifact) {
        throw new Error(
            `Artifact ${artifactFileName} was not found in ${release.name} release!`
        );
    }

    return {
        releaseName: release.name,
        releaseDate: new Date(release.published_at),
        downloadUrl: artifact.browser_download_url
    };

    // We omit declaration of tremendous amount of fields that we are not using here
    interface GithubRelease {
        name: string;
        // eslint-disable-next-line camelcase
        published_at: string;
        assets: Array<{
            name: string;
            // eslint-disable-next-line camelcase
            browser_download_url: string;
        }>;
    }
}