Skip to content

Commit

Permalink
feat: integration tests for /dl/:filename
Browse files Browse the repository at this point in the history
  • Loading branch information
dopry committed Sep 13, 2023
1 parent 014c0d8 commit 9225a27
Show file tree
Hide file tree
Showing 17 changed files with 6,001 additions and 2,958 deletions.
1 change: 1 addition & 0 deletions .mocharc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @type { import('mocha').MochaInstanceOptions } */
module.exports = {
color: true,
exit: true,
Expand Down
14 changes: 4 additions & 10 deletions docs/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,13 @@

Pecans can be easily be deployed to a state-less server or PaaS. It only uses the disk as a cache for assets.

### On Heroku:
<!-- ### With docker
Heroku is the perfect solution to host a Pecans instance.
You'll need to build your own pecans image at this time. We do not net publish one.
[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)

### With docker

Pecans can also be run as a Docker container:

```
docker run -it -p 80:80 -e GITHUB_REPO=username/repo gitbook/pecans
```
docker run -it -p 80:80 -e GITHUB_REPO=username/repo dopry/pecans
``` -->

### On your own server:

Expand Down
4 changes: 4 additions & 0 deletions env.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# for pecans
export GITHUB_OWNER="owner-nock-mocked"
export GITHUB_REPO="repo-nock-mocked"
export GITHUB_TOKEN="token-nock-mocked"
8,352 changes: 5,562 additions & 2,790 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"devDependencies": {
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@types/debug": "^4.1.8",
"@types/destroy": "^1.0.0",
"@types/expect": "^24.3.0",
"@types/express": "^4.17.13",
Expand All @@ -36,10 +37,15 @@
"@types/node": "^17.0.34",
"@types/node-fetch": "^2.6.1",
"@types/semver": "^7.3.9",
"mocha": "^10.0.0",
"@types/supertest": "^2.0.12",
"mocha": "^10.2.0",
"nanoid": "^3.3.6",
"nock": "^13.2.4",
"nodemon": "^2.0.16",
"semantic-release": "^19.0.2",
"semantic-release": "^21.1.1",
"should": "^13.2.3",
"sinon": "^14.0.0",
"supertest": "^6.2.3",
"typescript": "^4.6.4"
},
"bugs": {
Expand Down
103 changes: 92 additions & 11 deletions src/backends/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,95 @@ export type GithubReleaseAsset =
export type GithubRelease =
Endpoints["GET /repos/{owner}/{repo}/releases/latest"]["response"]["data"];

export interface GitHubBackendOpts extends BackendOpts {
export interface PecansGitHubBackendOpts extends BackendOpts {
baseUrl?: string;
proxyAssets?: boolean;
}

export class GitHubBackendSettings
export class PecansGitHubBackendSettings
extends BackendSettings
implements GitHubBackendOpts
implements PecansGitHubBackendOpts
{
baseUrl?: string;
proxyAssets = true;
}

export class GitHubBackend extends Backend {
protected opts: GitHubBackendSettings;
export interface PecansGithubBackendEnvironment {
GITHUB_OWNER: string;
GITHUB_REPO: string;
GITHUB_TOKEN?: string;
}

export class PecansGitHubBackend extends Backend {
protected opts: PecansGitHubBackendSettings;
protected octokit: Octokit;

static getEnvironment(prefix?: string): PecansGithubBackendEnvironment {
const ownerEnv = prefix ? `${prefix}_GITHUB_OWNER` : "GITHUB_OWNER";
const GITHUB_OWNER = process.env[ownerEnv];

const repoEnv = prefix ? `${prefix}_GITHUB_REPO` : "GITHUB_REPO";
const GITHUB_REPO = process.env[repoEnv];

const tokenEnv = prefix ? `${prefix}_GITHUB_TOKEN` : "GITHUB_TOKEN";
const GITHUB_TOKEN = process.env[tokenEnv];

if (!GITHUB_OWNER) {
throw new Error(`PECANS_GITHUB_OWNER environment variable is required.`);
}
if (!GITHUB_REPO) {
throw new Error(`PECANS_GITHUB_REPO environment variable is required.`);
}
if (!GITHUB_TOKEN) {
console.warn(
"Github Token not provided, if your repo is private you will need to provide a token."
);
}
const env = {
GITHUB_OWNER,
GITHUB_REPO,
GITHUB_TOKEN,
};
// console.log(
// {
// GITHUB_OWNER,
// GITHUB_REPO,
// GITHUB_TOKEN:
// GITHUB_TOKEN &&
// GITHUB_TOKEN.substring(0, 4) +
// "******" +
// GITHUB_TOKEN?.substring(GITHUB_TOKEN.length - 6),
// } || "No Github Token"
// );
return env;
}

static FromEnv(env: PecansGithubBackendEnvironment): PecansGitHubBackend {
return new PecansGitHubBackend(
env.GITHUB_OWNER,
env.GITHUB_REPO,
env.GITHUB_TOKEN
);
}

constructor(
protected token: string,
protected owner: string,
protected repo: string,
opts: GitHubBackendOpts = {}
protected token?: string,
opts: PecansGitHubBackendOpts = {}
) {
if (!token) {
throw new Error("Github Token Required");
}
if (!owner) {
throw new Error("Github Owner Required");
}
if (!repo) {
throw new Error("Github Repo Required");
}
if (!token) {
console.warn("Github Token not provided, ensure the repo is public");
}
super(opts);

this.opts = Object.assign({}, new GitHubBackendSettings(), opts);
this.opts = Object.assign({}, new PecansGitHubBackendSettings(), opts);
const { baseUrl = undefined } = opts;

const octokitOptions = {
Expand Down Expand Up @@ -92,6 +146,8 @@ export class GitHubBackend extends Backend {
async releases() {
const { owner, repo } = this;

// const reponse = await this.octokit.rest.repos.listReleases({ owner, repo });
// console.debug({ data: reponse.data });
const releases = await this.octokit.paginate(
this.octokit.rest.repos.listReleases,
{ owner, repo }
Expand All @@ -112,6 +168,7 @@ export class GitHubBackend extends Backend {
async serveAsset(asset: PecansAssetDTO, res: Response): Promise<void> {
if (!this.opts.proxyAssets) {
res.redirect(asset.raw.browser_download_url);
return;
} else {
const redirect = "manual";
const headers = { Accept: "application/octet-stream" };
Expand Down Expand Up @@ -207,3 +264,27 @@ export class GitHubBackend extends Backend {
return new PecansAsset(dto);
}
}

// @deprecated
export class GitHubBackend extends PecansGitHubBackend {
constructor(
protected token: string,
protected owner: string,
protected repo: string,
opts: PecansGitHubBackendOpts = {}
) {
console.warn(
"GitHubBackend has been deprecated in favor of the namespaced PecansGithubBackend"
);
if (!token) {
throw new Error("Github Token Required");
}
if (!owner) {
throw new Error("Github Owner Required");
}
if (!repo) {
throw new Error("Github Repo Required");
}
super(owner, repo, token, opts);
}
}
38 changes: 20 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import express, { Request, Response, NextFunction } from "express";
import { GitHubBackend } from "./backends";
import express, { NextFunction, Request, Response } from "express";
import { PecansGitHubBackend } from "./backends";
import { Pecans, PecansOptions } from "./pecans";

export * from "./backends";
export * from "./pecans";
export * from "./versions";
export * from "./utils/";
export * from "./versions";


if (require.main === module) {
if (!process.env.GITHUB_TOKEN)
throw new Error("GITHUB_TOKEN environment variables is required.");
if (!process.env.GITHUB_OWNER)
throw new Error("GITHUB_OWNER environment variable is required.");
if (!process.env.GITHUB_REPO)
throw new Error("GITHUB_REPO environment variable is required.");

const token = process.env.GITHUB_TOKEN;
const owner = process.env.GITHUB_OWNER;
const repo = process.env.GITHUB_REPO;
const backend = new GitHubBackend(token, owner, repo);
export function configure() {
const PECANS_BACKEND = "PecansGithubBackend";
const basePath = process.env.PECANS_BASE_PATH || "";

const pecansOpts: PecansOptions = {
// base path to inject between host and relative path. use for D.O. app service where
// app is proxied through / api and the original url isn't passed by the proxy.
basePath,
};

const pecans = new Pecans(backend, pecansOpts);
switch (PECANS_BACKEND) {
case "PecansGithubBackend":
const backendEnv = PecansGitHubBackend.getEnvironment();
const backend = PecansGitHubBackend.FromEnv(backendEnv);
const pecans = new Pecans(backend, pecansOpts);
return { env: backendEnv, backend, pecans };

default:
throw "Unrecognized PECANS_BACKEND. Must be one of ['PecansGithubBackend']";
}
}

if (require.main === module) {
const { pecans } = configure();

// Log download
pecans.on("beforeDownload", (download) => {
console.log(
Expand Down
Loading

0 comments on commit 9225a27

Please sign in to comment.