Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Publisher minio implementation #1502

Closed
wants to merge 5 commits into from
Closed
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@octokit/rest": "^16.43.1",
"@types/which": "^1.3.2",
"aws-sdk": "^2.472.0",
"minio": "^7.0.13",
"colors": "^1.4.0",
"commander": "^4.1.1",
"cross-spawn": "^7.0.1",
Expand Down Expand Up @@ -118,6 +119,7 @@
"@types/lodash": "^4.14.149",
"@types/mime-types": "^2.1.0",
"@types/minimist": "^1.2.0",
"@types/minio": "^7.0.5",
"@types/mocha": "^7.0.1",
"@types/node": "^13.7.1",
"@types/node-fetch": "^2.5.3",
Expand Down
24 changes: 24 additions & 0 deletions packages/publisher/minio/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@electron-forge/publisher-minio",
"version": "6.0.0-beta.49",
"description": "Minio publisher for Electron Forge",
"repository": "https://github.com/electron-userland/electron-forge",
"author": "Samuel Attard",
"license": "MIT",
"main": "dist/PublisherMinio.js",
"typings": "dist/PublisherMinio.d.ts",
"devDependencies": {
"chai": "4.2.0",
"mocha": "^7.0.1"
},
"engines": {
"node": ">= 10.0.0"
},
"dependencies": {
"@electron-forge/async-ora": "6.0.0-beta.49",
"@electron-forge/publisher-base": "6.0.0-beta.49",
"@electron-forge/shared-types": "6.0.0-beta.49",
"minio": "^7.0.13",
"debug": "^4.1.0"
}
}
52 changes: 52 additions & 0 deletions packages/publisher/minio/src/Config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// eslint-disable-next-line import/prefer-default-export
export interface PublisherMinioConfig {
/**
* Endpoint of your server. e.g. localhost
*/
endPoint: string,
/**
* Port of your server. e.g. 9000
*/
port: number,
/**
* Flag of SSL
*
* Falls back to 'false'
*/
useSSL?: boolean,
/**
* Your Minio Access Key ID
*
* Falls back to the MINIO_ACCESS_KEY environment variable if not provided
*/
accessKeyId?: string;
/**
* The secret for your Minio Access Key
*
* Falls back to the MINIO_SECRET_KEY environment variable if not
* provided
*/
secretAccessKey?: string;
/**
* The name of the MinIO/S3 bucket to upload artifacts to
*/
bucket: string;
/**
* The key prefix to upload artifacts to.
*
* E.g. `my/prefix`
*
* Default: undefined
*/
folder?: string;
/**
* Override folder configuration with appVersion
*
* Default: false
*/
useAppVersionAsFolder: boolean;
/**
* Custom function to provide the key to upload a given file to
*/
keyResolver?: (fileName: string, platform: string, arch: string) => string;
}
79 changes: 79 additions & 0 deletions packages/publisher/minio/src/PublisherMinio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import PublisherBase, { PublisherOptions } from '@electron-forge/publisher-base';
import { asyncOra } from '@electron-forge/async-ora';

import debug from 'debug';
import fs from 'fs';
import path from 'path';
import { Client } from 'minio';

import { PublisherMinioConfig } from './Config';

const d = debug('electron-forge:publish:minio');

type MinioArtifact = {
path: string;
keyPrefix: string;
platform: string;
arch: string;
};

export default class PublisherMinio extends PublisherBase<PublisherMinioConfig> {
name = 'minio';

async publish({
makeResults,
}: PublisherOptions) {
const { config } = this;
const artifacts: MinioArtifact[] = [];

for (const makeResult of makeResults) {
artifacts.push(...makeResult.artifacts.map((artifact) => ({
path: artifact,
keyPrefix: config.useAppVersionAsFolder ? makeResult.packageJSON.version : config.folder,
platform: makeResult.platform,
arch: makeResult.arch,
})));
d('artifact:', makeResult);
}

const configuration = {
endPoint: config.endPoint,
port: config.port,
useSSL: config.useSSL,
accessKey: (config.accessKeyId || process.env.MINIO_ACCESS_KEY) || '',
secretKey: (config.secretAccessKey || process.env.MINIO_SECRET_KEY) || '',
};

if (!config.endPoint || !config.port || !configuration.accessKey
|| !configuration.secretKey || !config.bucket) {
throw new Error('In order to publish to minio you must set the "minio.accessKeyId", "minio.secretAccessKey", "minio.endPoint", "minio.port" and "bucket"');
}
const minioClient = new Client(configuration);

d('creating minio client with options:', config);

let uploaded = 0;
const spinnerText = () => `Uploading Artifacts ${uploaded}/${artifacts.length}`;

await asyncOra(spinnerText(), async (uploadSpinner) => {
await Promise.all(artifacts.map(async (artifact) => {
const fileName = path.basename(artifact.path);
const stream = fs.createReadStream(artifact.path);

await minioClient.putObject(config.bucket, this.resolvePath(artifact, fileName), stream);

d('uploading:', fileName);
uploaded += 1;
uploadSpinner.text = spinnerText();
}));
});
}

resolvePath(artifact: MinioArtifact, fileName: string): string {
if (!artifact.keyPrefix) {
return fileName;
}

return artifact.keyPrefix.endsWith('/') ? artifact.keyPrefix + fileName : `${artifact.keyPrefix}/${fileName}`;
}
}
Loading