Skip to content

Commit

Permalink
feat: add gcp support
Browse files Browse the repository at this point in the history
  • Loading branch information
rams23 committed Oct 17, 2023
1 parent c2f06e8 commit acefdcd
Show file tree
Hide file tree
Showing 5 changed files with 374 additions and 8 deletions.
9 changes: 7 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
"@react-native-community/cli": "^10.2.0",
"@react-native-community/cli-config": "^10.1.1",
"@rn-buildhub/azure-storage": "workspace:^",
"@rn-buildhub/s3-storage": "workspace:^0.0.1",
"@rn-buildhub/gcp-storage": "workspace:^",
"@rn-buildhub/s3-storage": "workspace:^",
"@types/chai": "^4",
"@types/mocha": "^9.0.0",
"@types/node": "^18.18.4",
Expand All @@ -78,14 +79,18 @@
},
"peerDependencies": {
"@rn-buildhub/azure-storage": "workspace:^",
"@rn-buildhub/s3-storage": "workspace:^"
"@rn-buildhub/s3-storage": "workspace:^",
"@rn-buildhub/gcp-storage": "workspace:^"
},
"peerDependenciesMeta": {
"@rn-buildhub/azure-storage": {
"optional": true
},
"@rn-buildhub/s3-storage": {
"optional": true
},
"@rn-buildhub/gcp-storage": {
"optional": true
}
},
"oclif": {
Expand Down
21 changes: 21 additions & 0 deletions packages/storage-gcp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@rn-buildhub/gcp-storage",
"version": "0.0.1",
"description": "",
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"typings": "dist/index.d.ts",
"scripts": {
"build": "tsc"
},
"author": "",
"license": "ISC",
"dependencies": {
"@google-cloud/storage": "^7.3.0",
"@rn-buildhub/storage-interface": "workspace:^",
"@types/node": "^18.18.4",
"dotenv": "^16.3.1",
"typescript": "^4.9.5"
}
}
119 changes: 119 additions & 0 deletions packages/storage-gcp/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import {Storage, Bucket} from "@google-cloud/storage";

import process from "node:process";
import path from "node:path";
import fs from "node:fs";
import { Build, HubAdapter, ProjectBuildInfo } from "@rn-buildhub/storage-interface";

export interface GCPStorageOptions {
gcpBucket?: string;
gcpApplicationCredentials?: string;
}

export function getProjectRootDir() {
// todo improve this
return process.cwd();
}

function getOptions(options: GCPStorageOptions) {
return {
gcpBucket: process.env.RNBH_GCP_BUCKET ?? options.gcpBucket,
gcpApplicationCredentials: process.env.RNBH_GOOGLE_APPLICATION_CREDENTIALS ?? options.gcpApplicationCredentials,
};
}


// todo rename hub adapter to stare and then create a hub that extends the storage?
class GCPStorage extends HubAdapter {
private bucket: Bucket;

// todo validate config

public constructor(fileOptions?: GCPStorageOptions) {
super();
require("dotenv").config({ path: path.join(getProjectRootDir(), ".env") });
const options = getOptions(fileOptions || {});
if(!options.gcpApplicationCredentials){
throw new Error("Missing RNBH_GOOGLE_APPLICATION_CREDENTIALS env variable");
}
const jsonFileContent = fs.readFileSync(
path.join(getProjectRootDir(), options.gcpApplicationCredentials),
"utf8"
);
const credentials = JSON.parse(jsonFileContent.toString());
console.log("credentials", credentials)
console.log("options", options);
const storage = new Storage({
credentials
})
if (!options.gcpBucket) {
throw new Error("Missing RNBH_GCP_BUCKET env variable");
}

this.bucket = storage.bucket(options.gcpBucket);
}

private async uploadFileToGcp(
path: string,
buffer: Buffer,
metadata?: { [key: string]: string }
) {
await this.bucket.file(path).save(buffer, {
metadata: metadata
});
}

async upload(buildId: string, buffer: Buffer, fileName: string): Promise<string> {
const buildpath = this.getBuildPath(buildId);

await this.uploadFileToGcp(`${buildpath}/${fileName}`, buffer, {
createdAt: new Date().toISOString()
});
return `${buildpath}/${fileName}`;
}

async downloadFileFromGcp(path: string): Promise<Buffer> {
const [buffer] = await this.bucket.file(path).download();
return buffer;
}

async setLastBuild(buildId: string): Promise<void> {
const fileContent = JSON.stringify({ lastBuild: buildId });
await this.uploadFileToGcp(`config.json`, Buffer.from(fileContent, "utf-8"));
}

async getLastBuild(): Promise<string> {
const fileContent = await this.downloadFileFromGcp(`config.json`);
return JSON.parse(fileContent.toString()).lastBuild;
}

private getBuildPath(buildId: string) {
return `builds/${buildId}`;
}

async saveBuildInfo(buildId: string, info: {
androidBuilds: Build[];
iosBuilds: Build[];
}): Promise<void> {
const buildpath = this.getBuildPath(buildId);
const infoToSave: ProjectBuildInfo = {
...info,
createdAt: new Date().toISOString(),
version: 1,
id: buildId
};
await this.uploadFileToGcp(`${buildpath}/info.json`, Buffer.from(JSON.stringify(infoToSave), "utf-8"));
}

async getBuildInfo(buildId: string): Promise<ProjectBuildInfo> {
const buildpath = this.getBuildPath(buildId);
const fileContent = await this.downloadFileFromGcp(`${buildpath}/info.json`);
return JSON.parse(fileContent.toString());
}

download(path: string): Promise<Buffer> {
return this.downloadFileFromGcp(path);
}
}

export default GCPStorage;
21 changes: 21 additions & 0 deletions packages/storage-gcp/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"declaration": true,
"importHelpers": false,
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"noImplicitAny": true,
"noEmitOnError": true,
"target": "es2019",
"esModuleInterop": true,
"skipLibCheck": true,
},
"include": [
"src/**/*"
],
"ts-node": {
"esm": true
}
}
Loading

0 comments on commit acefdcd

Please sign in to comment.