chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: dolthub
|
||||
@@ -0,0 +1,5 @@
|
||||
name: 'Dolt Benchmark Runner Utility Test'
|
||||
description: "Smoke tests for Dolt's benchmark runner utility"
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: '../../../SysbenchDockerfile'
|
||||
@@ -0,0 +1,51 @@
|
||||
name: 'Build dolt'
|
||||
description: 'Builds dolt (and optionally remotesrv and noms) into $GITHUB_WORKSPACE/.ci_bin and prepends that directory to $GITHUB_PATH so the binaries are on PATH for subsequent steps. On Windows, builds run inside the msys2 shell (this action expects setup-go-toolchain to have been run first so that msys2 is installed).'
|
||||
|
||||
inputs:
|
||||
remotesrv:
|
||||
description: 'Also build remotesrv.'
|
||||
required: false
|
||||
default: 'false'
|
||||
noms:
|
||||
description: 'Also build noms.'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Add .ci_bin to PATH
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/.ci_bin"
|
||||
echo "$GITHUB_WORKSPACE/.ci_bin" >> "$GITHUB_PATH"
|
||||
- name: Build dolt
|
||||
if: runner.os != 'Windows'
|
||||
shell: bash
|
||||
working-directory: ./go
|
||||
run: go build -mod=readonly -o ../.ci_bin/dolt ./cmd/dolt/.
|
||||
- name: Build remotesrv
|
||||
if: runner.os != 'Windows' && inputs.remotesrv == 'true'
|
||||
shell: bash
|
||||
working-directory: ./go
|
||||
run: go build -mod=readonly -o ../.ci_bin/remotesrv ./utils/remotesrv/.
|
||||
- name: Build noms
|
||||
if: runner.os != 'Windows' && inputs.noms == 'true'
|
||||
shell: bash
|
||||
working-directory: ./go
|
||||
run: go build -mod=readonly -o ../.ci_bin/noms ./store/cmd/noms/.
|
||||
- name: Build dolt (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
shell: 'msys2 {0}'
|
||||
working-directory: ./go
|
||||
run: go.exe build -mod=readonly -o ../.ci_bin/dolt ./cmd/dolt/.
|
||||
- name: Build remotesrv (Windows)
|
||||
if: runner.os == 'Windows' && inputs.remotesrv == 'true'
|
||||
shell: 'msys2 {0}'
|
||||
working-directory: ./go
|
||||
run: go.exe build -mod=readonly -o ../.ci_bin/remotesrv ./utils/remotesrv/.
|
||||
- name: Build noms (Windows)
|
||||
if: runner.os == 'Windows' && inputs.noms == 'true'
|
||||
shell: 'msys2 {0}'
|
||||
working-directory: ./go
|
||||
run: go.exe build -mod=readonly -o ../.ci_bin/noms ./store/cmd/noms/.
|
||||
@@ -0,0 +1,5 @@
|
||||
name: 'Dolt loading dump file integration tests'
|
||||
description: 'Smoke tests for loading dump file into Dolt'
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: '../../../integration-tests/DataDumpLoadDockerfile'
|
||||
@@ -0,0 +1,50 @@
|
||||
name: 'SES email action'
|
||||
description: 'Send email with aws ses'
|
||||
inputs:
|
||||
region:
|
||||
description: 'aws region'
|
||||
required: true
|
||||
default: ''
|
||||
version:
|
||||
description: 'dolt version being benchmarked or ref of bats windows job'
|
||||
required: true
|
||||
default: ''
|
||||
format:
|
||||
description: 'dolt noms bin format'
|
||||
required: true
|
||||
default: '__DOLT__'
|
||||
template:
|
||||
description: 'email template'
|
||||
required: false
|
||||
default: 'PerformanceBenchmarkingReleaseTemplate'
|
||||
dataFile:
|
||||
required: false
|
||||
description: 'path to email data file'
|
||||
default: ''
|
||||
bodyPath:
|
||||
required: false
|
||||
description: 'path to email body file'
|
||||
default: ''
|
||||
subject:
|
||||
required: false
|
||||
description: 'path to email subject'
|
||||
default: ''
|
||||
toAddresses:
|
||||
description: 'json string list of to addresses'
|
||||
required: true
|
||||
default: "[]"
|
||||
ccAddresses:
|
||||
description: 'json string list of cc addresses'
|
||||
required: false
|
||||
default: "[]"
|
||||
replyToAddresses:
|
||||
description: 'json string list of reply to addresses'
|
||||
required: false
|
||||
default: "[]"
|
||||
workflowURL:
|
||||
description: 'url of the workflow run'
|
||||
default: ''
|
||||
required: false
|
||||
runs:
|
||||
using: 'node20'
|
||||
main: 'dist/index.js'
|
||||
@@ -0,0 +1,898 @@
|
||||
"use strict";
|
||||
exports.id = 136;
|
||||
exports.ids = [136];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 3723:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.STSClient = exports.__Client = void 0;
|
||||
const middleware_host_header_1 = __webpack_require__(2590);
|
||||
const middleware_logger_1 = __webpack_require__(5242);
|
||||
const middleware_recursion_detection_1 = __webpack_require__(1568);
|
||||
const middleware_user_agent_1 = __webpack_require__(2959);
|
||||
const config_resolver_1 = __webpack_require__(9316);
|
||||
const core_1 = __webpack_require__(402);
|
||||
const schema_1 = __webpack_require__(6890);
|
||||
const middleware_content_length_1 = __webpack_require__(7212);
|
||||
const middleware_endpoint_1 = __webpack_require__(99);
|
||||
const middleware_retry_1 = __webpack_require__(9618);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
Object.defineProperty(exports, "__Client", ({ enumerable: true, get: function () { return smithy_client_1.Client; } }));
|
||||
const httpAuthSchemeProvider_1 = __webpack_require__(7851);
|
||||
const EndpointParameters_1 = __webpack_require__(6811);
|
||||
const runtimeConfig_1 = __webpack_require__(6578);
|
||||
const runtimeExtensions_1 = __webpack_require__(7742);
|
||||
class STSClient extends smithy_client_1.Client {
|
||||
config;
|
||||
constructor(...[configuration]) {
|
||||
const _config_0 = (0, runtimeConfig_1.getRuntimeConfig)(configuration || {});
|
||||
super(_config_0);
|
||||
this.initConfig = _config_0;
|
||||
const _config_1 = (0, EndpointParameters_1.resolveClientEndpointParameters)(_config_0);
|
||||
const _config_2 = (0, middleware_user_agent_1.resolveUserAgentConfig)(_config_1);
|
||||
const _config_3 = (0, middleware_retry_1.resolveRetryConfig)(_config_2);
|
||||
const _config_4 = (0, config_resolver_1.resolveRegionConfig)(_config_3);
|
||||
const _config_5 = (0, middleware_host_header_1.resolveHostHeaderConfig)(_config_4);
|
||||
const _config_6 = (0, middleware_endpoint_1.resolveEndpointConfig)(_config_5);
|
||||
const _config_7 = (0, httpAuthSchemeProvider_1.resolveHttpAuthSchemeConfig)(_config_6);
|
||||
const _config_8 = (0, runtimeExtensions_1.resolveRuntimeExtensions)(_config_7, configuration?.extensions || []);
|
||||
this.config = _config_8;
|
||||
this.middlewareStack.use((0, schema_1.getSchemaSerdePlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_user_agent_1.getUserAgentPlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_retry_1.getRetryPlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_content_length_1.getContentLengthPlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_host_header_1.getHostHeaderPlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_logger_1.getLoggerPlugin)(this.config));
|
||||
this.middlewareStack.use((0, middleware_recursion_detection_1.getRecursionDetectionPlugin)(this.config));
|
||||
this.middlewareStack.use((0, core_1.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, {
|
||||
httpAuthSchemeParametersProvider: httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeParametersProvider,
|
||||
identityProviderConfigProvider: async (config) => new core_1.DefaultIdentityProviderConfig({
|
||||
"aws.auth#sigv4": config.credentials,
|
||||
}),
|
||||
}));
|
||||
this.middlewareStack.use((0, core_1.getHttpSigningPlugin)(this.config));
|
||||
}
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
exports.STSClient = STSClient;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4532:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.resolveHttpAuthRuntimeConfig = exports.getHttpAuthExtensionConfiguration = void 0;
|
||||
const getHttpAuthExtensionConfiguration = (runtimeConfig) => {
|
||||
const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
|
||||
let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
|
||||
let _credentials = runtimeConfig.credentials;
|
||||
return {
|
||||
setHttpAuthScheme(httpAuthScheme) {
|
||||
const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId);
|
||||
if (index === -1) {
|
||||
_httpAuthSchemes.push(httpAuthScheme);
|
||||
}
|
||||
else {
|
||||
_httpAuthSchemes.splice(index, 1, httpAuthScheme);
|
||||
}
|
||||
},
|
||||
httpAuthSchemes() {
|
||||
return _httpAuthSchemes;
|
||||
},
|
||||
setHttpAuthSchemeProvider(httpAuthSchemeProvider) {
|
||||
_httpAuthSchemeProvider = httpAuthSchemeProvider;
|
||||
},
|
||||
httpAuthSchemeProvider() {
|
||||
return _httpAuthSchemeProvider;
|
||||
},
|
||||
setCredentials(credentials) {
|
||||
_credentials = credentials;
|
||||
},
|
||||
credentials() {
|
||||
return _credentials;
|
||||
},
|
||||
};
|
||||
};
|
||||
exports.getHttpAuthExtensionConfiguration = getHttpAuthExtensionConfiguration;
|
||||
const resolveHttpAuthRuntimeConfig = (config) => {
|
||||
return {
|
||||
httpAuthSchemes: config.httpAuthSchemes(),
|
||||
httpAuthSchemeProvider: config.httpAuthSchemeProvider(),
|
||||
credentials: config.credentials(),
|
||||
};
|
||||
};
|
||||
exports.resolveHttpAuthRuntimeConfig = resolveHttpAuthRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 7851:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.resolveHttpAuthSchemeConfig = exports.resolveStsAuthConfig = exports.defaultSTSHttpAuthSchemeProvider = exports.defaultSTSHttpAuthSchemeParametersProvider = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_middleware_1 = __webpack_require__(6324);
|
||||
const STSClient_1 = __webpack_require__(3723);
|
||||
const defaultSTSHttpAuthSchemeParametersProvider = async (config, context, input) => {
|
||||
return {
|
||||
operation: (0, util_middleware_1.getSmithyContext)(context).operation,
|
||||
region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) ||
|
||||
(() => {
|
||||
throw new Error("expected `region` to be configured for `aws.auth#sigv4`");
|
||||
})(),
|
||||
};
|
||||
};
|
||||
exports.defaultSTSHttpAuthSchemeParametersProvider = defaultSTSHttpAuthSchemeParametersProvider;
|
||||
function createAwsAuthSigv4HttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "aws.auth#sigv4",
|
||||
signingProperties: {
|
||||
name: "sts",
|
||||
region: authParameters.region,
|
||||
},
|
||||
propertiesExtractor: (config, context) => ({
|
||||
signingProperties: {
|
||||
config,
|
||||
context,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
function createSmithyApiNoAuthHttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "smithy.api#noAuth",
|
||||
};
|
||||
}
|
||||
const defaultSTSHttpAuthSchemeProvider = (authParameters) => {
|
||||
const options = [];
|
||||
switch (authParameters.operation) {
|
||||
case "AssumeRoleWithWebIdentity": {
|
||||
options.push(createSmithyApiNoAuthHttpAuthOption(authParameters));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
options.push(createAwsAuthSigv4HttpAuthOption(authParameters));
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
exports.defaultSTSHttpAuthSchemeProvider = defaultSTSHttpAuthSchemeProvider;
|
||||
const resolveStsAuthConfig = (input) => Object.assign(input, {
|
||||
stsClientCtor: STSClient_1.STSClient,
|
||||
});
|
||||
exports.resolveStsAuthConfig = resolveStsAuthConfig;
|
||||
const resolveHttpAuthSchemeConfig = (config) => {
|
||||
const config_0 = (0, exports.resolveStsAuthConfig)(config);
|
||||
const config_1 = (0, core_1.resolveAwsSdkSigV4Config)(config_0);
|
||||
return Object.assign(config_1, {
|
||||
authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []),
|
||||
});
|
||||
};
|
||||
exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6811:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.commonParams = exports.resolveClientEndpointParameters = void 0;
|
||||
const resolveClientEndpointParameters = (options) => {
|
||||
return Object.assign(options, {
|
||||
useDualstackEndpoint: options.useDualstackEndpoint ?? false,
|
||||
useFipsEndpoint: options.useFipsEndpoint ?? false,
|
||||
useGlobalEndpoint: options.useGlobalEndpoint ?? false,
|
||||
defaultSigningName: "sts",
|
||||
});
|
||||
};
|
||||
exports.resolveClientEndpointParameters = resolveClientEndpointParameters;
|
||||
exports.commonParams = {
|
||||
UseGlobalEndpoint: { type: "builtInParams", name: "useGlobalEndpoint" },
|
||||
UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" },
|
||||
Endpoint: { type: "builtInParams", name: "endpoint" },
|
||||
Region: { type: "builtInParams", name: "region" },
|
||||
UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" },
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9765:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.defaultEndpointResolver = void 0;
|
||||
const util_endpoints_1 = __webpack_require__(3068);
|
||||
const util_endpoints_2 = __webpack_require__(9674);
|
||||
const ruleset_1 = __webpack_require__(1670);
|
||||
const cache = new util_endpoints_2.EndpointCache({
|
||||
size: 50,
|
||||
params: ["Endpoint", "Region", "UseDualStack", "UseFIPS", "UseGlobalEndpoint"],
|
||||
});
|
||||
const defaultEndpointResolver = (endpointParams, context = {}) => {
|
||||
return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, {
|
||||
endpointParams: endpointParams,
|
||||
logger: context.logger,
|
||||
}));
|
||||
};
|
||||
exports.defaultEndpointResolver = defaultEndpointResolver;
|
||||
util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1670:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.ruleSet = void 0;
|
||||
const F = "required", G = "type", H = "fn", I = "argv", J = "ref";
|
||||
const a = false, b = true, c = "booleanEquals", d = "stringEquals", e = "sigv4", f = "sts", g = "us-east-1", h = "endpoint", i = "https://sts.{Region}.{PartitionResult#dnsSuffix}", j = "tree", k = "error", l = "getAttr", m = { [F]: false, [G]: "string" }, n = { [F]: true, "default": false, [G]: "boolean" }, o = { [J]: "Endpoint" }, p = { [H]: "isSet", [I]: [{ [J]: "Region" }] }, q = { [J]: "Region" }, r = { [H]: "aws.partition", [I]: [q], "assign": "PartitionResult" }, s = { [J]: "UseFIPS" }, t = { [J]: "UseDualStack" }, u = { "url": "https://sts.amazonaws.com", "properties": { "authSchemes": [{ "name": e, "signingName": f, "signingRegion": g }] }, "headers": {} }, v = {}, w = { "conditions": [{ [H]: d, [I]: [q, "aws-global"] }], [h]: u, [G]: h }, x = { [H]: c, [I]: [s, true] }, y = { [H]: c, [I]: [t, true] }, z = { [H]: l, [I]: [{ [J]: "PartitionResult" }, "supportsFIPS"] }, A = { [J]: "PartitionResult" }, B = { [H]: c, [I]: [true, { [H]: l, [I]: [A, "supportsDualStack"] }] }, C = [{ [H]: "isSet", [I]: [o] }], D = [x], E = [y];
|
||||
const _data = { version: "1.0", parameters: { Region: m, UseDualStack: n, UseFIPS: n, Endpoint: m, UseGlobalEndpoint: n }, rules: [{ conditions: [{ [H]: c, [I]: [{ [J]: "UseGlobalEndpoint" }, b] }, { [H]: "not", [I]: C }, p, r, { [H]: c, [I]: [s, a] }, { [H]: c, [I]: [t, a] }], rules: [{ conditions: [{ [H]: d, [I]: [q, "ap-northeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-south-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-2"] }], endpoint: u, [G]: h }, w, { conditions: [{ [H]: d, [I]: [q, "ca-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-north-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-3"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "sa-east-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, g] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-east-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-2"] }], endpoint: u, [G]: h }, { endpoint: { url: i, properties: { authSchemes: [{ name: e, signingName: f, signingRegion: "{Region}" }] }, headers: v }, [G]: h }], [G]: j }, { conditions: C, rules: [{ conditions: D, error: "Invalid Configuration: FIPS and custom endpoint are not supported", [G]: k }, { conditions: E, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", [G]: k }, { endpoint: { url: o, properties: v, headers: v }, [G]: h }], [G]: j }, { conditions: [p], rules: [{ conditions: [r], rules: [{ conditions: [x, y], rules: [{ conditions: [{ [H]: c, [I]: [b, z] }, B], rules: [{ endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", [G]: k }], [G]: j }, { conditions: D, rules: [{ conditions: [{ [H]: c, [I]: [z, b] }], rules: [{ conditions: [{ [H]: d, [I]: [{ [H]: l, [I]: [A, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://sts.{Region}.amazonaws.com", properties: v, headers: v }, [G]: h }, { endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS is enabled but this partition does not support FIPS", [G]: k }], [G]: j }, { conditions: E, rules: [{ conditions: [B], rules: [{ endpoint: { url: "https://sts.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "DualStack is enabled but this partition does not support DualStack", [G]: k }], [G]: j }, w, { endpoint: { url: i, properties: v, headers: v }, [G]: h }], [G]: j }], [G]: j }, { error: "Invalid Configuration: Missing Region", [G]: k }] };
|
||||
exports.ruleSet = _data;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1136:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
|
||||
var STSClient = __webpack_require__(3723);
|
||||
var smithyClient = __webpack_require__(1411);
|
||||
var middlewareEndpoint = __webpack_require__(99);
|
||||
var EndpointParameters = __webpack_require__(6811);
|
||||
var schema = __webpack_require__(6890);
|
||||
var client = __webpack_require__(5152);
|
||||
var regionConfigResolver = __webpack_require__(6463);
|
||||
|
||||
class STSServiceException extends smithyClient.ServiceException {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
Object.setPrototypeOf(this, STSServiceException.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
class ExpiredTokenException extends STSServiceException {
|
||||
name = "ExpiredTokenException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "ExpiredTokenException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, ExpiredTokenException.prototype);
|
||||
}
|
||||
}
|
||||
class MalformedPolicyDocumentException extends STSServiceException {
|
||||
name = "MalformedPolicyDocumentException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "MalformedPolicyDocumentException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, MalformedPolicyDocumentException.prototype);
|
||||
}
|
||||
}
|
||||
class PackedPolicyTooLargeException extends STSServiceException {
|
||||
name = "PackedPolicyTooLargeException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "PackedPolicyTooLargeException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, PackedPolicyTooLargeException.prototype);
|
||||
}
|
||||
}
|
||||
class RegionDisabledException extends STSServiceException {
|
||||
name = "RegionDisabledException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "RegionDisabledException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, RegionDisabledException.prototype);
|
||||
}
|
||||
}
|
||||
class IDPRejectedClaimException extends STSServiceException {
|
||||
name = "IDPRejectedClaimException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "IDPRejectedClaimException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, IDPRejectedClaimException.prototype);
|
||||
}
|
||||
}
|
||||
class InvalidIdentityTokenException extends STSServiceException {
|
||||
name = "InvalidIdentityTokenException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InvalidIdentityTokenException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InvalidIdentityTokenException.prototype);
|
||||
}
|
||||
}
|
||||
class IDPCommunicationErrorException extends STSServiceException {
|
||||
name = "IDPCommunicationErrorException";
|
||||
$fault = "client";
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "IDPCommunicationErrorException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, IDPCommunicationErrorException.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
const _A = "Arn";
|
||||
const _AKI = "AccessKeyId";
|
||||
const _AR = "AssumeRole";
|
||||
const _ARI = "AssumedRoleId";
|
||||
const _ARR = "AssumeRoleRequest";
|
||||
const _ARRs = "AssumeRoleResponse";
|
||||
const _ARU = "AssumedRoleUser";
|
||||
const _ARWWI = "AssumeRoleWithWebIdentity";
|
||||
const _ARWWIR = "AssumeRoleWithWebIdentityRequest";
|
||||
const _ARWWIRs = "AssumeRoleWithWebIdentityResponse";
|
||||
const _Au = "Audience";
|
||||
const _C = "Credentials";
|
||||
const _CA = "ContextAssertion";
|
||||
const _DS = "DurationSeconds";
|
||||
const _E = "Expiration";
|
||||
const _EI = "ExternalId";
|
||||
const _ETE = "ExpiredTokenException";
|
||||
const _IDPCEE = "IDPCommunicationErrorException";
|
||||
const _IDPRCE = "IDPRejectedClaimException";
|
||||
const _IITE = "InvalidIdentityTokenException";
|
||||
const _K = "Key";
|
||||
const _MPDE = "MalformedPolicyDocumentException";
|
||||
const _P = "Policy";
|
||||
const _PA = "PolicyArns";
|
||||
const _PAr = "ProviderArn";
|
||||
const _PC = "ProvidedContexts";
|
||||
const _PCLT = "ProvidedContextsListType";
|
||||
const _PCr = "ProvidedContext";
|
||||
const _PDT = "PolicyDescriptorType";
|
||||
const _PI = "ProviderId";
|
||||
const _PPS = "PackedPolicySize";
|
||||
const _PPTLE = "PackedPolicyTooLargeException";
|
||||
const _Pr = "Provider";
|
||||
const _RA = "RoleArn";
|
||||
const _RDE = "RegionDisabledException";
|
||||
const _RSN = "RoleSessionName";
|
||||
const _SAK = "SecretAccessKey";
|
||||
const _SFWIT = "SubjectFromWebIdentityToken";
|
||||
const _SI = "SourceIdentity";
|
||||
const _SN = "SerialNumber";
|
||||
const _ST = "SessionToken";
|
||||
const _T = "Tags";
|
||||
const _TC = "TokenCode";
|
||||
const _TTK = "TransitiveTagKeys";
|
||||
const _Ta = "Tag";
|
||||
const _V = "Value";
|
||||
const _WIT = "WebIdentityToken";
|
||||
const _a = "arn";
|
||||
const _aKST = "accessKeySecretType";
|
||||
const _aQE = "awsQueryError";
|
||||
const _c = "client";
|
||||
const _cTT = "clientTokenType";
|
||||
const _e = "error";
|
||||
const _hE = "httpError";
|
||||
const _m = "message";
|
||||
const _pDLT = "policyDescriptorListType";
|
||||
const _s = "smithy.ts.sdk.synthetic.com.amazonaws.sts";
|
||||
const _tLT = "tagListType";
|
||||
const n0 = "com.amazonaws.sts";
|
||||
var accessKeySecretType = [0, n0, _aKST, 8, 0];
|
||||
var clientTokenType = [0, n0, _cTT, 8, 0];
|
||||
var AssumedRoleUser$ = [3, n0, _ARU, 0, [_ARI, _A], [0, 0], 2];
|
||||
var AssumeRoleRequest$ = [
|
||||
3,
|
||||
n0,
|
||||
_ARR,
|
||||
0,
|
||||
[_RA, _RSN, _PA, _P, _DS, _T, _TTK, _EI, _SN, _TC, _SI, _PC],
|
||||
[0, 0, () => policyDescriptorListType, 0, 1, () => tagListType, 64 | 0, 0, 0, 0, 0, () => ProvidedContextsListType],
|
||||
2,
|
||||
];
|
||||
var AssumeRoleResponse$ = [
|
||||
3,
|
||||
n0,
|
||||
_ARRs,
|
||||
0,
|
||||
[_C, _ARU, _PPS, _SI],
|
||||
[[() => Credentials$, 0], () => AssumedRoleUser$, 1, 0],
|
||||
];
|
||||
var AssumeRoleWithWebIdentityRequest$ = [
|
||||
3,
|
||||
n0,
|
||||
_ARWWIR,
|
||||
0,
|
||||
[_RA, _RSN, _WIT, _PI, _PA, _P, _DS],
|
||||
[0, 0, [() => clientTokenType, 0], 0, () => policyDescriptorListType, 0, 1],
|
||||
3,
|
||||
];
|
||||
var AssumeRoleWithWebIdentityResponse$ = [
|
||||
3,
|
||||
n0,
|
||||
_ARWWIRs,
|
||||
0,
|
||||
[_C, _SFWIT, _ARU, _PPS, _Pr, _Au, _SI],
|
||||
[[() => Credentials$, 0], 0, () => AssumedRoleUser$, 1, 0, 0, 0],
|
||||
];
|
||||
var Credentials$ = [
|
||||
3,
|
||||
n0,
|
||||
_C,
|
||||
0,
|
||||
[_AKI, _SAK, _ST, _E],
|
||||
[0, [() => accessKeySecretType, 0], 0, 4],
|
||||
4,
|
||||
];
|
||||
var ExpiredTokenException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_ETE,
|
||||
{ [_aQE]: [`ExpiredTokenException`, 400], [_e]: _c, [_hE]: 400 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(ExpiredTokenException$, ExpiredTokenException);
|
||||
var IDPCommunicationErrorException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_IDPCEE,
|
||||
{ [_aQE]: [`IDPCommunicationError`, 400], [_e]: _c, [_hE]: 400 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(IDPCommunicationErrorException$, IDPCommunicationErrorException);
|
||||
var IDPRejectedClaimException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_IDPRCE,
|
||||
{ [_aQE]: [`IDPRejectedClaim`, 403], [_e]: _c, [_hE]: 403 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(IDPRejectedClaimException$, IDPRejectedClaimException);
|
||||
var InvalidIdentityTokenException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_IITE,
|
||||
{ [_aQE]: [`InvalidIdentityToken`, 400], [_e]: _c, [_hE]: 400 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(InvalidIdentityTokenException$, InvalidIdentityTokenException);
|
||||
var MalformedPolicyDocumentException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_MPDE,
|
||||
{ [_aQE]: [`MalformedPolicyDocument`, 400], [_e]: _c, [_hE]: 400 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(MalformedPolicyDocumentException$, MalformedPolicyDocumentException);
|
||||
var PackedPolicyTooLargeException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_PPTLE,
|
||||
{ [_aQE]: [`PackedPolicyTooLarge`, 400], [_e]: _c, [_hE]: 400 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(PackedPolicyTooLargeException$, PackedPolicyTooLargeException);
|
||||
var PolicyDescriptorType$ = [3, n0, _PDT, 0, [_a], [0]];
|
||||
var ProvidedContext$ = [3, n0, _PCr, 0, [_PAr, _CA], [0, 0]];
|
||||
var RegionDisabledException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_RDE,
|
||||
{ [_aQE]: [`RegionDisabledException`, 403], [_e]: _c, [_hE]: 403 },
|
||||
[_m],
|
||||
[0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(RegionDisabledException$, RegionDisabledException);
|
||||
var Tag$ = [3, n0, _Ta, 0, [_K, _V], [0, 0], 2];
|
||||
var STSServiceException$ = [-3, _s, "STSServiceException", 0, [], []];
|
||||
schema.TypeRegistry.for(_s).registerError(STSServiceException$, STSServiceException);
|
||||
var policyDescriptorListType = [1, n0, _pDLT, 0, () => PolicyDescriptorType$];
|
||||
var ProvidedContextsListType = [1, n0, _PCLT, 0, () => ProvidedContext$];
|
||||
var tagListType = [1, n0, _tLT, 0, () => Tag$];
|
||||
var AssumeRole$ = [9, n0, _AR, 0, () => AssumeRoleRequest$, () => AssumeRoleResponse$];
|
||||
var AssumeRoleWithWebIdentity$ = [
|
||||
9,
|
||||
n0,
|
||||
_ARWWI,
|
||||
0,
|
||||
() => AssumeRoleWithWebIdentityRequest$,
|
||||
() => AssumeRoleWithWebIdentityResponse$,
|
||||
];
|
||||
|
||||
class AssumeRoleCommand extends smithyClient.Command
|
||||
.classBuilder()
|
||||
.ep(EndpointParameters.commonParams)
|
||||
.m(function (Command, cs, config, o) {
|
||||
return [middlewareEndpoint.getEndpointPlugin(config, Command.getEndpointParameterInstructions())];
|
||||
})
|
||||
.s("AWSSecurityTokenServiceV20110615", "AssumeRole", {})
|
||||
.n("STSClient", "AssumeRoleCommand")
|
||||
.sc(AssumeRole$)
|
||||
.build() {
|
||||
}
|
||||
|
||||
class AssumeRoleWithWebIdentityCommand extends smithyClient.Command
|
||||
.classBuilder()
|
||||
.ep(EndpointParameters.commonParams)
|
||||
.m(function (Command, cs, config, o) {
|
||||
return [middlewareEndpoint.getEndpointPlugin(config, Command.getEndpointParameterInstructions())];
|
||||
})
|
||||
.s("AWSSecurityTokenServiceV20110615", "AssumeRoleWithWebIdentity", {})
|
||||
.n("STSClient", "AssumeRoleWithWebIdentityCommand")
|
||||
.sc(AssumeRoleWithWebIdentity$)
|
||||
.build() {
|
||||
}
|
||||
|
||||
const commands = {
|
||||
AssumeRoleCommand,
|
||||
AssumeRoleWithWebIdentityCommand,
|
||||
};
|
||||
class STS extends STSClient.STSClient {
|
||||
}
|
||||
smithyClient.createAggregatedClient(commands, STS);
|
||||
|
||||
const getAccountIdFromAssumedRoleUser = (assumedRoleUser) => {
|
||||
if (typeof assumedRoleUser?.Arn === "string") {
|
||||
const arnComponents = assumedRoleUser.Arn.split(":");
|
||||
if (arnComponents.length > 4 && arnComponents[4] !== "") {
|
||||
return arnComponents[4];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
const resolveRegion = async (_region, _parentRegion, credentialProviderLogger, loaderConfig = {}) => {
|
||||
const region = typeof _region === "function" ? await _region() : _region;
|
||||
const parentRegion = typeof _parentRegion === "function" ? await _parentRegion() : _parentRegion;
|
||||
let stsDefaultRegion = "";
|
||||
const resolvedRegion = region ?? parentRegion ?? (stsDefaultRegion = await regionConfigResolver.stsRegionDefaultResolver(loaderConfig)());
|
||||
credentialProviderLogger?.debug?.("@aws-sdk/client-sts::resolveRegion", "accepting first of:", `${region} (credential provider clientConfig)`, `${parentRegion} (contextual client)`, `${stsDefaultRegion} (STS default: AWS_REGION, profile region, or us-east-1)`);
|
||||
return resolvedRegion;
|
||||
};
|
||||
const getDefaultRoleAssumer$1 = (stsOptions, STSClient) => {
|
||||
let stsClient;
|
||||
let closureSourceCreds;
|
||||
return async (sourceCreds, params) => {
|
||||
closureSourceCreds = sourceCreds;
|
||||
if (!stsClient) {
|
||||
const { logger = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId, } = stsOptions;
|
||||
const resolvedRegion = await resolveRegion(region, stsOptions?.parentClientConfig?.region, credentialProviderLogger, {
|
||||
logger,
|
||||
profile,
|
||||
});
|
||||
const isCompatibleRequestHandler = !isH2(requestHandler);
|
||||
stsClient = new STSClient({
|
||||
...stsOptions,
|
||||
userAgentAppId,
|
||||
profile,
|
||||
credentialDefaultProvider: () => async () => closureSourceCreds,
|
||||
region: resolvedRegion,
|
||||
requestHandler: isCompatibleRequestHandler ? requestHandler : undefined,
|
||||
logger: logger,
|
||||
});
|
||||
}
|
||||
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleCommand(params));
|
||||
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
|
||||
throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`);
|
||||
}
|
||||
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
|
||||
const credentials = {
|
||||
accessKeyId: Credentials.AccessKeyId,
|
||||
secretAccessKey: Credentials.SecretAccessKey,
|
||||
sessionToken: Credentials.SessionToken,
|
||||
expiration: Credentials.Expiration,
|
||||
...(Credentials.CredentialScope && { credentialScope: Credentials.CredentialScope }),
|
||||
...(accountId && { accountId }),
|
||||
};
|
||||
client.setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE", "i");
|
||||
return credentials;
|
||||
};
|
||||
};
|
||||
const getDefaultRoleAssumerWithWebIdentity$1 = (stsOptions, STSClient) => {
|
||||
let stsClient;
|
||||
return async (params) => {
|
||||
if (!stsClient) {
|
||||
const { logger = stsOptions?.parentClientConfig?.logger, profile = stsOptions?.parentClientConfig?.profile, region, requestHandler = stsOptions?.parentClientConfig?.requestHandler, credentialProviderLogger, userAgentAppId = stsOptions?.parentClientConfig?.userAgentAppId, } = stsOptions;
|
||||
const resolvedRegion = await resolveRegion(region, stsOptions?.parentClientConfig?.region, credentialProviderLogger, {
|
||||
logger,
|
||||
profile,
|
||||
});
|
||||
const isCompatibleRequestHandler = !isH2(requestHandler);
|
||||
stsClient = new STSClient({
|
||||
...stsOptions,
|
||||
userAgentAppId,
|
||||
profile,
|
||||
region: resolvedRegion,
|
||||
requestHandler: isCompatibleRequestHandler ? requestHandler : undefined,
|
||||
logger: logger,
|
||||
});
|
||||
}
|
||||
const { Credentials, AssumedRoleUser } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
|
||||
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
|
||||
throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`);
|
||||
}
|
||||
const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser);
|
||||
const credentials = {
|
||||
accessKeyId: Credentials.AccessKeyId,
|
||||
secretAccessKey: Credentials.SecretAccessKey,
|
||||
sessionToken: Credentials.SessionToken,
|
||||
expiration: Credentials.Expiration,
|
||||
...(Credentials.CredentialScope && { credentialScope: Credentials.CredentialScope }),
|
||||
...(accountId && { accountId }),
|
||||
};
|
||||
if (accountId) {
|
||||
client.setCredentialFeature(credentials, "RESOLVED_ACCOUNT_ID", "T");
|
||||
}
|
||||
client.setCredentialFeature(credentials, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k");
|
||||
return credentials;
|
||||
};
|
||||
};
|
||||
const isH2 = (requestHandler) => {
|
||||
return requestHandler?.metadata?.handlerProtocol === "h2";
|
||||
};
|
||||
|
||||
const getCustomizableStsClientCtor = (baseCtor, customizations) => {
|
||||
if (!customizations)
|
||||
return baseCtor;
|
||||
else
|
||||
return class CustomizableSTSClient extends baseCtor {
|
||||
constructor(config) {
|
||||
super(config);
|
||||
for (const customization of customizations) {
|
||||
this.middlewareStack.use(customization);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
const getDefaultRoleAssumer = (stsOptions = {}, stsPlugins) => getDefaultRoleAssumer$1(stsOptions, getCustomizableStsClientCtor(STSClient.STSClient, stsPlugins));
|
||||
const getDefaultRoleAssumerWithWebIdentity = (stsOptions = {}, stsPlugins) => getDefaultRoleAssumerWithWebIdentity$1(stsOptions, getCustomizableStsClientCtor(STSClient.STSClient, stsPlugins));
|
||||
const decorateDefaultCredentialProvider = (provider) => (input) => provider({
|
||||
roleAssumer: getDefaultRoleAssumer(input),
|
||||
roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(input),
|
||||
...input,
|
||||
});
|
||||
|
||||
Object.defineProperty(exports, "$Command", ({
|
||||
enumerable: true,
|
||||
get: function () { return smithyClient.Command; }
|
||||
}));
|
||||
exports.AssumeRole$ = AssumeRole$;
|
||||
exports.AssumeRoleCommand = AssumeRoleCommand;
|
||||
exports.AssumeRoleRequest$ = AssumeRoleRequest$;
|
||||
exports.AssumeRoleResponse$ = AssumeRoleResponse$;
|
||||
exports.AssumeRoleWithWebIdentity$ = AssumeRoleWithWebIdentity$;
|
||||
exports.AssumeRoleWithWebIdentityCommand = AssumeRoleWithWebIdentityCommand;
|
||||
exports.AssumeRoleWithWebIdentityRequest$ = AssumeRoleWithWebIdentityRequest$;
|
||||
exports.AssumeRoleWithWebIdentityResponse$ = AssumeRoleWithWebIdentityResponse$;
|
||||
exports.AssumedRoleUser$ = AssumedRoleUser$;
|
||||
exports.Credentials$ = Credentials$;
|
||||
exports.ExpiredTokenException = ExpiredTokenException;
|
||||
exports.ExpiredTokenException$ = ExpiredTokenException$;
|
||||
exports.IDPCommunicationErrorException = IDPCommunicationErrorException;
|
||||
exports.IDPCommunicationErrorException$ = IDPCommunicationErrorException$;
|
||||
exports.IDPRejectedClaimException = IDPRejectedClaimException;
|
||||
exports.IDPRejectedClaimException$ = IDPRejectedClaimException$;
|
||||
exports.InvalidIdentityTokenException = InvalidIdentityTokenException;
|
||||
exports.InvalidIdentityTokenException$ = InvalidIdentityTokenException$;
|
||||
exports.MalformedPolicyDocumentException = MalformedPolicyDocumentException;
|
||||
exports.MalformedPolicyDocumentException$ = MalformedPolicyDocumentException$;
|
||||
exports.PackedPolicyTooLargeException = PackedPolicyTooLargeException;
|
||||
exports.PackedPolicyTooLargeException$ = PackedPolicyTooLargeException$;
|
||||
exports.PolicyDescriptorType$ = PolicyDescriptorType$;
|
||||
exports.ProvidedContext$ = ProvidedContext$;
|
||||
exports.RegionDisabledException = RegionDisabledException;
|
||||
exports.RegionDisabledException$ = RegionDisabledException$;
|
||||
exports.STS = STS;
|
||||
exports.STSServiceException = STSServiceException;
|
||||
exports.STSServiceException$ = STSServiceException$;
|
||||
exports.Tag$ = Tag$;
|
||||
exports.decorateDefaultCredentialProvider = decorateDefaultCredentialProvider;
|
||||
exports.getDefaultRoleAssumer = getDefaultRoleAssumer;
|
||||
exports.getDefaultRoleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity;
|
||||
Object.keys(STSClient).forEach(function (k) {
|
||||
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
||||
enumerable: true,
|
||||
get: function () { return STSClient[k]; }
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6578:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const tslib_1 = __webpack_require__(1860);
|
||||
const package_json_1 = tslib_1.__importDefault(__webpack_require__(9955));
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_user_agent_node_1 = __webpack_require__(1656);
|
||||
const config_resolver_1 = __webpack_require__(9316);
|
||||
const core_2 = __webpack_require__(402);
|
||||
const hash_node_1 = __webpack_require__(2711);
|
||||
const middleware_retry_1 = __webpack_require__(9618);
|
||||
const node_config_provider_1 = __webpack_require__(5704);
|
||||
const node_http_handler_1 = __webpack_require__(1279);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const util_body_length_node_1 = __webpack_require__(3638);
|
||||
const util_defaults_mode_node_1 = __webpack_require__(5435);
|
||||
const util_retry_1 = __webpack_require__(5518);
|
||||
const runtimeConfig_shared_1 = __webpack_require__(4443);
|
||||
const getRuntimeConfig = (config) => {
|
||||
(0, smithy_client_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config);
|
||||
const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode);
|
||||
const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config);
|
||||
(0, core_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const loaderConfig = {
|
||||
profile: config?.profile,
|
||||
logger: clientSharedValues.logger,
|
||||
};
|
||||
return {
|
||||
...clientSharedValues,
|
||||
...config,
|
||||
runtime: "node",
|
||||
defaultsMode,
|
||||
authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
|
||||
bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength,
|
||||
defaultUserAgentProvider: config?.defaultUserAgentProvider ??
|
||||
(0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }),
|
||||
httpAuthSchemes: config?.httpAuthSchemes ?? [
|
||||
{
|
||||
schemeId: "aws.auth#sigv4",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4") ||
|
||||
(async (idProps) => await config.credentialDefaultProvider(idProps?.__config || {})()),
|
||||
signer: new core_1.AwsSdkSigV4Signer(),
|
||||
},
|
||||
{
|
||||
schemeId: "smithy.api#noAuth",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})),
|
||||
signer: new core_2.NoAuthSigner(),
|
||||
},
|
||||
],
|
||||
maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
|
||||
region: config?.region ??
|
||||
(0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
|
||||
requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
|
||||
retryMode: config?.retryMode ??
|
||||
(0, node_config_provider_1.loadConfig)({
|
||||
...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS,
|
||||
default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE,
|
||||
}, config),
|
||||
sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"),
|
||||
streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector,
|
||||
useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig),
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4443:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const protocols_1 = __webpack_require__(7288);
|
||||
const core_2 = __webpack_require__(402);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const url_parser_1 = __webpack_require__(4494);
|
||||
const util_base64_1 = __webpack_require__(8385);
|
||||
const util_utf8_1 = __webpack_require__(1577);
|
||||
const httpAuthSchemeProvider_1 = __webpack_require__(7851);
|
||||
const endpointResolver_1 = __webpack_require__(9765);
|
||||
const getRuntimeConfig = (config) => {
|
||||
return {
|
||||
apiVersion: "2011-06-15",
|
||||
base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64,
|
||||
base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64,
|
||||
disableHostPrefix: config?.disableHostPrefix ?? false,
|
||||
endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver,
|
||||
extensions: config?.extensions ?? [],
|
||||
httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeProvider,
|
||||
httpAuthSchemes: config?.httpAuthSchemes ?? [
|
||||
{
|
||||
schemeId: "aws.auth#sigv4",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"),
|
||||
signer: new core_1.AwsSdkSigV4Signer(),
|
||||
},
|
||||
{
|
||||
schemeId: "smithy.api#noAuth",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})),
|
||||
signer: new core_2.NoAuthSigner(),
|
||||
},
|
||||
],
|
||||
logger: config?.logger ?? new smithy_client_1.NoOpLogger(),
|
||||
protocol: config?.protocol ?? protocols_1.AwsQueryProtocol,
|
||||
protocolSettings: config?.protocolSettings ?? {
|
||||
defaultNamespace: "com.amazonaws.sts",
|
||||
xmlNamespace: "https://sts.amazonaws.com/doc/2011-06-15/",
|
||||
version: "2011-06-15",
|
||||
serviceTarget: "AWSSecurityTokenServiceV20110615",
|
||||
},
|
||||
serviceId: config?.serviceId ?? "STS",
|
||||
urlParser: config?.urlParser ?? url_parser_1.parseUrl,
|
||||
utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8,
|
||||
utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8,
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 7742:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.resolveRuntimeExtensions = void 0;
|
||||
const region_config_resolver_1 = __webpack_require__(6463);
|
||||
const protocol_http_1 = __webpack_require__(2356);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const httpAuthExtensionConfiguration_1 = __webpack_require__(4532);
|
||||
const resolveRuntimeExtensions = (runtimeConfig, extensions) => {
|
||||
const extensionConfiguration = Object.assign((0, region_config_resolver_1.getAwsRegionExtensionConfiguration)(runtimeConfig), (0, smithy_client_1.getDefaultExtensionConfiguration)(runtimeConfig), (0, protocol_http_1.getHttpHandlerExtensionConfiguration)(runtimeConfig), (0, httpAuthExtensionConfiguration_1.getHttpAuthExtensionConfiguration)(runtimeConfig));
|
||||
extensions.forEach((extension) => extension.configure(extensionConfiguration));
|
||||
return Object.assign(runtimeConfig, (0, region_config_resolver_1.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), (0, smithy_client_1.resolveDefaultRuntimeConfig)(extensionConfiguration), (0, protocol_http_1.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), (0, httpAuthExtensionConfiguration_1.resolveHttpAuthRuntimeConfig)(extensionConfiguration));
|
||||
};
|
||||
exports.resolveRuntimeExtensions = resolveRuntimeExtensions;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9955:
|
||||
/***/ ((module) => {
|
||||
|
||||
module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/nested-clients","version":"3.982.0","description":"Nested clients for AWS SDK packages.","main":"./dist-cjs/index.js","module":"./dist-es/index.js","types":"./dist-types/index.d.ts","scripts":{"build":"yarn lint && concurrently \'yarn:build:types\' \'yarn:build:es\' && yarn build:cjs","build:cjs":"node ../../scripts/compilation/inline nested-clients","build:es":"tsc -p tsconfig.es.json","build:include:deps":"yarn g:turbo run build -F=\\"$npm_package_name\\"","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo","lint":"node ../../scripts/validation/submodules-linter.js --pkg nested-clients","test":"yarn g:vitest run","test:watch":"yarn g:vitest watch"},"engines":{"node":">=20.0.0"},"sideEffects":false,"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"^3.973.6","@aws-sdk/middleware-host-header":"^3.972.3","@aws-sdk/middleware-logger":"^3.972.3","@aws-sdk/middleware-recursion-detection":"^3.972.3","@aws-sdk/middleware-user-agent":"^3.972.6","@aws-sdk/region-config-resolver":"^3.972.3","@aws-sdk/types":"^3.973.1","@aws-sdk/util-endpoints":"3.982.0","@aws-sdk/util-user-agent-browser":"^3.972.3","@aws-sdk/util-user-agent-node":"^3.972.4","@smithy/config-resolver":"^4.4.6","@smithy/core":"^3.22.0","@smithy/fetch-http-handler":"^5.3.9","@smithy/hash-node":"^4.2.8","@smithy/invalid-dependency":"^4.2.8","@smithy/middleware-content-length":"^4.2.8","@smithy/middleware-endpoint":"^4.4.12","@smithy/middleware-retry":"^4.4.29","@smithy/middleware-serde":"^4.2.9","@smithy/middleware-stack":"^4.2.8","@smithy/node-config-provider":"^4.3.8","@smithy/node-http-handler":"^4.4.8","@smithy/protocol-http":"^5.3.8","@smithy/smithy-client":"^4.11.1","@smithy/types":"^4.12.0","@smithy/url-parser":"^4.2.8","@smithy/util-base64":"^4.3.0","@smithy/util-body-length-browser":"^4.2.0","@smithy/util-body-length-node":"^4.2.1","@smithy/util-defaults-mode-browser":"^4.3.28","@smithy/util-defaults-mode-node":"^4.2.31","@smithy/util-endpoints":"^3.2.8","@smithy/util-middleware":"^4.2.8","@smithy/util-retry":"^4.2.8","@smithy/util-utf8":"^4.2.0","tslib":"^2.6.2"},"devDependencies":{"concurrently":"7.0.0","downlevel-dts":"0.10.1","premove":"4.0.0","typescript":"~5.8.3"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["./signin.d.ts","./signin.js","./sso-oidc.d.ts","./sso-oidc.js","./sts.d.ts","./sts.js","dist-*/**"],"browser":{"./dist-es/submodules/signin/runtimeConfig":"./dist-es/submodules/signin/runtimeConfig.browser","./dist-es/submodules/sso-oidc/runtimeConfig":"./dist-es/submodules/sso-oidc/runtimeConfig.browser","./dist-es/submodules/sts/runtimeConfig":"./dist-es/submodules/sts/runtimeConfig.browser"},"react-native":{},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/packages/nested-clients","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"packages/nested-clients"},"exports":{"./package.json":"./package.json","./sso-oidc":{"types":"./dist-types/submodules/sso-oidc/index.d.ts","module":"./dist-es/submodules/sso-oidc/index.js","node":"./dist-cjs/submodules/sso-oidc/index.js","import":"./dist-es/submodules/sso-oidc/index.js","require":"./dist-cjs/submodules/sso-oidc/index.js"},"./sts":{"types":"./dist-types/submodules/sts/index.d.ts","module":"./dist-es/submodules/sts/index.js","node":"./dist-cjs/submodules/sts/index.js","import":"./dist-es/submodules/sts/index.js","require":"./dist-cjs/submodules/sts/index.js"},"./signin":{"types":"./dist-types/submodules/signin/index.d.ts","module":"./dist-es/submodules/signin/index.js","node":"./dist-cjs/submodules/signin/index.js","import":"./dist-es/submodules/signin/index.js","require":"./dist-cjs/submodules/signin/index.js"}}}');
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
exports.id = 360;
|
||||
exports.ids = [360];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 5360:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
|
||||
var sharedIniFileLoader = __webpack_require__(4964);
|
||||
var propertyProvider = __webpack_require__(8857);
|
||||
var child_process = __webpack_require__(5317);
|
||||
var util = __webpack_require__(9023);
|
||||
var client = __webpack_require__(5152);
|
||||
|
||||
const getValidatedProcessCredentials = (profileName, data, profiles) => {
|
||||
if (data.Version !== 1) {
|
||||
throw Error(`Profile ${profileName} credential_process did not return Version 1.`);
|
||||
}
|
||||
if (data.AccessKeyId === undefined || data.SecretAccessKey === undefined) {
|
||||
throw Error(`Profile ${profileName} credential_process returned invalid credentials.`);
|
||||
}
|
||||
if (data.Expiration) {
|
||||
const currentTime = new Date();
|
||||
const expireTime = new Date(data.Expiration);
|
||||
if (expireTime < currentTime) {
|
||||
throw Error(`Profile ${profileName} credential_process returned expired credentials.`);
|
||||
}
|
||||
}
|
||||
let accountId = data.AccountId;
|
||||
if (!accountId && profiles?.[profileName]?.aws_account_id) {
|
||||
accountId = profiles[profileName].aws_account_id;
|
||||
}
|
||||
const credentials = {
|
||||
accessKeyId: data.AccessKeyId,
|
||||
secretAccessKey: data.SecretAccessKey,
|
||||
...(data.SessionToken && { sessionToken: data.SessionToken }),
|
||||
...(data.Expiration && { expiration: new Date(data.Expiration) }),
|
||||
...(data.CredentialScope && { credentialScope: data.CredentialScope }),
|
||||
...(accountId && { accountId }),
|
||||
};
|
||||
client.setCredentialFeature(credentials, "CREDENTIALS_PROCESS", "w");
|
||||
return credentials;
|
||||
};
|
||||
|
||||
const resolveProcessCredentials = async (profileName, profiles, logger) => {
|
||||
const profile = profiles[profileName];
|
||||
if (profiles[profileName]) {
|
||||
const credentialProcess = profile["credential_process"];
|
||||
if (credentialProcess !== undefined) {
|
||||
const execPromise = util.promisify(sharedIniFileLoader.externalDataInterceptor?.getTokenRecord?.().exec ?? child_process.exec);
|
||||
try {
|
||||
const { stdout } = await execPromise(credentialProcess);
|
||||
let data;
|
||||
try {
|
||||
data = JSON.parse(stdout.trim());
|
||||
}
|
||||
catch {
|
||||
throw Error(`Profile ${profileName} credential_process returned invalid JSON.`);
|
||||
}
|
||||
return getValidatedProcessCredentials(profileName, data, profiles);
|
||||
}
|
||||
catch (error) {
|
||||
throw new propertyProvider.CredentialsProviderError(error.message, { logger });
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new propertyProvider.CredentialsProviderError(`Profile ${profileName} did not contain credential_process.`, { logger });
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new propertyProvider.CredentialsProviderError(`Profile ${profileName} could not be found in shared credentials file.`, {
|
||||
logger,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const fromProcess = (init = {}) => async ({ callerClientConfig } = {}) => {
|
||||
init.logger?.debug("@aws-sdk/credential-provider-process - fromProcess");
|
||||
const profiles = await sharedIniFileLoader.parseKnownFiles(init);
|
||||
return resolveProcessCredentials(sharedIniFileLoader.getProfileName({
|
||||
profile: init.profile ?? callerClientConfig?.profile,
|
||||
}), profiles, init.logger);
|
||||
};
|
||||
|
||||
exports.fromProcess = fromProcess;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,738 @@
|
||||
"use strict";
|
||||
exports.id = 443;
|
||||
exports.ids = [443];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 8396:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.resolveHttpAuthSchemeConfig = exports.defaultSSOOIDCHttpAuthSchemeProvider = exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_middleware_1 = __webpack_require__(6324);
|
||||
const defaultSSOOIDCHttpAuthSchemeParametersProvider = async (config, context, input) => {
|
||||
return {
|
||||
operation: (0, util_middleware_1.getSmithyContext)(context).operation,
|
||||
region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) ||
|
||||
(() => {
|
||||
throw new Error("expected `region` to be configured for `aws.auth#sigv4`");
|
||||
})(),
|
||||
};
|
||||
};
|
||||
exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = defaultSSOOIDCHttpAuthSchemeParametersProvider;
|
||||
function createAwsAuthSigv4HttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "aws.auth#sigv4",
|
||||
signingProperties: {
|
||||
name: "sso-oauth",
|
||||
region: authParameters.region,
|
||||
},
|
||||
propertiesExtractor: (config, context) => ({
|
||||
signingProperties: {
|
||||
config,
|
||||
context,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
function createSmithyApiNoAuthHttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "smithy.api#noAuth",
|
||||
};
|
||||
}
|
||||
const defaultSSOOIDCHttpAuthSchemeProvider = (authParameters) => {
|
||||
const options = [];
|
||||
switch (authParameters.operation) {
|
||||
case "CreateToken": {
|
||||
options.push(createSmithyApiNoAuthHttpAuthOption(authParameters));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
options.push(createAwsAuthSigv4HttpAuthOption(authParameters));
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
exports.defaultSSOOIDCHttpAuthSchemeProvider = defaultSSOOIDCHttpAuthSchemeProvider;
|
||||
const resolveHttpAuthSchemeConfig = (config) => {
|
||||
const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config);
|
||||
return Object.assign(config_0, {
|
||||
authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []),
|
||||
});
|
||||
};
|
||||
exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 546:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.defaultEndpointResolver = void 0;
|
||||
const util_endpoints_1 = __webpack_require__(3068);
|
||||
const util_endpoints_2 = __webpack_require__(9674);
|
||||
const ruleset_1 = __webpack_require__(9947);
|
||||
const cache = new util_endpoints_2.EndpointCache({
|
||||
size: 50,
|
||||
params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"],
|
||||
});
|
||||
const defaultEndpointResolver = (endpointParams, context = {}) => {
|
||||
return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, {
|
||||
endpointParams: endpointParams,
|
||||
logger: context.logger,
|
||||
}));
|
||||
};
|
||||
exports.defaultEndpointResolver = defaultEndpointResolver;
|
||||
util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9947:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.ruleSet = void 0;
|
||||
const u = "required", v = "fn", w = "argv", x = "ref";
|
||||
const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "getAttr", i = { [u]: false, "type": "string" }, j = { [u]: true, "default": false, "type": "boolean" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] }, p = { [x]: g }, q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] }, r = [l], s = [m], t = [{ [x]: "Region" }];
|
||||
const _data = { version: "1.0", parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }, { conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, o] }, q], rules: [{ endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: r, rules: [{ conditions: [{ [v]: c, [w]: [o, a] }], rules: [{ conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://oidc.{Region}.amazonaws.com", properties: n, headers: n }, type: e }, { endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: s, rules: [{ conditions: [q], rules: [{ endpoint: { url: "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://oidc.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }] };
|
||||
exports.ruleSet = _data;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9443:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var __webpack_unused_export__;
|
||||
|
||||
|
||||
var middlewareHostHeader = __webpack_require__(2590);
|
||||
var middlewareLogger = __webpack_require__(5242);
|
||||
var middlewareRecursionDetection = __webpack_require__(1568);
|
||||
var middlewareUserAgent = __webpack_require__(2959);
|
||||
var configResolver = __webpack_require__(9316);
|
||||
var core = __webpack_require__(402);
|
||||
var schema = __webpack_require__(6890);
|
||||
var middlewareContentLength = __webpack_require__(7212);
|
||||
var middlewareEndpoint = __webpack_require__(99);
|
||||
var middlewareRetry = __webpack_require__(9618);
|
||||
var smithyClient = __webpack_require__(1411);
|
||||
var httpAuthSchemeProvider = __webpack_require__(8396);
|
||||
var runtimeConfig = __webpack_require__(6901);
|
||||
var regionConfigResolver = __webpack_require__(6463);
|
||||
var protocolHttp = __webpack_require__(2356);
|
||||
|
||||
const resolveClientEndpointParameters = (options) => {
|
||||
return Object.assign(options, {
|
||||
useDualstackEndpoint: options.useDualstackEndpoint ?? false,
|
||||
useFipsEndpoint: options.useFipsEndpoint ?? false,
|
||||
defaultSigningName: "sso-oauth",
|
||||
});
|
||||
};
|
||||
const commonParams = {
|
||||
UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" },
|
||||
Endpoint: { type: "builtInParams", name: "endpoint" },
|
||||
Region: { type: "builtInParams", name: "region" },
|
||||
UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" },
|
||||
};
|
||||
|
||||
const getHttpAuthExtensionConfiguration = (runtimeConfig) => {
|
||||
const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
|
||||
let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
|
||||
let _credentials = runtimeConfig.credentials;
|
||||
return {
|
||||
setHttpAuthScheme(httpAuthScheme) {
|
||||
const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId);
|
||||
if (index === -1) {
|
||||
_httpAuthSchemes.push(httpAuthScheme);
|
||||
}
|
||||
else {
|
||||
_httpAuthSchemes.splice(index, 1, httpAuthScheme);
|
||||
}
|
||||
},
|
||||
httpAuthSchemes() {
|
||||
return _httpAuthSchemes;
|
||||
},
|
||||
setHttpAuthSchemeProvider(httpAuthSchemeProvider) {
|
||||
_httpAuthSchemeProvider = httpAuthSchemeProvider;
|
||||
},
|
||||
httpAuthSchemeProvider() {
|
||||
return _httpAuthSchemeProvider;
|
||||
},
|
||||
setCredentials(credentials) {
|
||||
_credentials = credentials;
|
||||
},
|
||||
credentials() {
|
||||
return _credentials;
|
||||
},
|
||||
};
|
||||
};
|
||||
const resolveHttpAuthRuntimeConfig = (config) => {
|
||||
return {
|
||||
httpAuthSchemes: config.httpAuthSchemes(),
|
||||
httpAuthSchemeProvider: config.httpAuthSchemeProvider(),
|
||||
credentials: config.credentials(),
|
||||
};
|
||||
};
|
||||
|
||||
const resolveRuntimeExtensions = (runtimeConfig, extensions) => {
|
||||
const extensionConfiguration = Object.assign(regionConfigResolver.getAwsRegionExtensionConfiguration(runtimeConfig), smithyClient.getDefaultExtensionConfiguration(runtimeConfig), protocolHttp.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration(runtimeConfig));
|
||||
extensions.forEach((extension) => extension.configure(extensionConfiguration));
|
||||
return Object.assign(runtimeConfig, regionConfigResolver.resolveAwsRegionExtensionConfiguration(extensionConfiguration), smithyClient.resolveDefaultRuntimeConfig(extensionConfiguration), protocolHttp.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig(extensionConfiguration));
|
||||
};
|
||||
|
||||
class SSOOIDCClient extends smithyClient.Client {
|
||||
config;
|
||||
constructor(...[configuration]) {
|
||||
const _config_0 = runtimeConfig.getRuntimeConfig(configuration || {});
|
||||
super(_config_0);
|
||||
this.initConfig = _config_0;
|
||||
const _config_1 = resolveClientEndpointParameters(_config_0);
|
||||
const _config_2 = middlewareUserAgent.resolveUserAgentConfig(_config_1);
|
||||
const _config_3 = middlewareRetry.resolveRetryConfig(_config_2);
|
||||
const _config_4 = configResolver.resolveRegionConfig(_config_3);
|
||||
const _config_5 = middlewareHostHeader.resolveHostHeaderConfig(_config_4);
|
||||
const _config_6 = middlewareEndpoint.resolveEndpointConfig(_config_5);
|
||||
const _config_7 = httpAuthSchemeProvider.resolveHttpAuthSchemeConfig(_config_6);
|
||||
const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []);
|
||||
this.config = _config_8;
|
||||
this.middlewareStack.use(schema.getSchemaSerdePlugin(this.config));
|
||||
this.middlewareStack.use(middlewareUserAgent.getUserAgentPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareRetry.getRetryPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareContentLength.getContentLengthPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareHostHeader.getHostHeaderPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareLogger.getLoggerPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareRecursionDetection.getRecursionDetectionPlugin(this.config));
|
||||
this.middlewareStack.use(core.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
|
||||
httpAuthSchemeParametersProvider: httpAuthSchemeProvider.defaultSSOOIDCHttpAuthSchemeParametersProvider,
|
||||
identityProviderConfigProvider: async (config) => new core.DefaultIdentityProviderConfig({
|
||||
"aws.auth#sigv4": config.credentials,
|
||||
}),
|
||||
}));
|
||||
this.middlewareStack.use(core.getHttpSigningPlugin(this.config));
|
||||
}
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
class SSOOIDCServiceException extends smithyClient.ServiceException {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
Object.setPrototypeOf(this, SSOOIDCServiceException.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
class AccessDeniedException extends SSOOIDCServiceException {
|
||||
name = "AccessDeniedException";
|
||||
$fault = "client";
|
||||
error;
|
||||
reason;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "AccessDeniedException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, AccessDeniedException.prototype);
|
||||
this.error = opts.error;
|
||||
this.reason = opts.reason;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class AuthorizationPendingException extends SSOOIDCServiceException {
|
||||
name = "AuthorizationPendingException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "AuthorizationPendingException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, AuthorizationPendingException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class ExpiredTokenException extends SSOOIDCServiceException {
|
||||
name = "ExpiredTokenException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "ExpiredTokenException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, ExpiredTokenException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class InternalServerException extends SSOOIDCServiceException {
|
||||
name = "InternalServerException";
|
||||
$fault = "server";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InternalServerException",
|
||||
$fault: "server",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InternalServerException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class InvalidClientException extends SSOOIDCServiceException {
|
||||
name = "InvalidClientException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InvalidClientException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InvalidClientException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class InvalidGrantException extends SSOOIDCServiceException {
|
||||
name = "InvalidGrantException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InvalidGrantException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InvalidGrantException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class InvalidRequestException extends SSOOIDCServiceException {
|
||||
name = "InvalidRequestException";
|
||||
$fault = "client";
|
||||
error;
|
||||
reason;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InvalidRequestException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InvalidRequestException.prototype);
|
||||
this.error = opts.error;
|
||||
this.reason = opts.reason;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class InvalidScopeException extends SSOOIDCServiceException {
|
||||
name = "InvalidScopeException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InvalidScopeException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InvalidScopeException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class SlowDownException extends SSOOIDCServiceException {
|
||||
name = "SlowDownException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "SlowDownException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, SlowDownException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class UnauthorizedClientException extends SSOOIDCServiceException {
|
||||
name = "UnauthorizedClientException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "UnauthorizedClientException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, UnauthorizedClientException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
class UnsupportedGrantTypeException extends SSOOIDCServiceException {
|
||||
name = "UnsupportedGrantTypeException";
|
||||
$fault = "client";
|
||||
error;
|
||||
error_description;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "UnsupportedGrantTypeException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, UnsupportedGrantTypeException.prototype);
|
||||
this.error = opts.error;
|
||||
this.error_description = opts.error_description;
|
||||
}
|
||||
}
|
||||
|
||||
const _ADE = "AccessDeniedException";
|
||||
const _APE = "AuthorizationPendingException";
|
||||
const _AT = "AccessToken";
|
||||
const _CS = "ClientSecret";
|
||||
const _CT = "CreateToken";
|
||||
const _CTR = "CreateTokenRequest";
|
||||
const _CTRr = "CreateTokenResponse";
|
||||
const _CV = "CodeVerifier";
|
||||
const _ETE = "ExpiredTokenException";
|
||||
const _ICE = "InvalidClientException";
|
||||
const _IGE = "InvalidGrantException";
|
||||
const _IRE = "InvalidRequestException";
|
||||
const _ISE = "InternalServerException";
|
||||
const _ISEn = "InvalidScopeException";
|
||||
const _IT = "IdToken";
|
||||
const _RT = "RefreshToken";
|
||||
const _SDE = "SlowDownException";
|
||||
const _UCE = "UnauthorizedClientException";
|
||||
const _UGTE = "UnsupportedGrantTypeException";
|
||||
const _aT = "accessToken";
|
||||
const _c = "client";
|
||||
const _cI = "clientId";
|
||||
const _cS = "clientSecret";
|
||||
const _cV = "codeVerifier";
|
||||
const _co = "code";
|
||||
const _dC = "deviceCode";
|
||||
const _e = "error";
|
||||
const _eI = "expiresIn";
|
||||
const _ed = "error_description";
|
||||
const _gT = "grantType";
|
||||
const _h = "http";
|
||||
const _hE = "httpError";
|
||||
const _iT = "idToken";
|
||||
const _r = "reason";
|
||||
const _rT = "refreshToken";
|
||||
const _rU = "redirectUri";
|
||||
const _s = "scope";
|
||||
const _se = "server";
|
||||
const _sm = "smithy.ts.sdk.synthetic.com.amazonaws.ssooidc";
|
||||
const _tT = "tokenType";
|
||||
const n0 = "com.amazonaws.ssooidc";
|
||||
var AccessToken = [0, n0, _AT, 8, 0];
|
||||
var ClientSecret = [0, n0, _CS, 8, 0];
|
||||
var CodeVerifier = [0, n0, _CV, 8, 0];
|
||||
var IdToken = [0, n0, _IT, 8, 0];
|
||||
var RefreshToken = [0, n0, _RT, 8, 0];
|
||||
var AccessDeniedException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_ADE,
|
||||
{ [_e]: _c, [_hE]: 400 },
|
||||
[_e, _r, _ed],
|
||||
[0, 0, 0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(AccessDeniedException$, AccessDeniedException);
|
||||
var AuthorizationPendingException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_APE,
|
||||
{ [_e]: _c, [_hE]: 400 },
|
||||
[_e, _ed],
|
||||
[0, 0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(AuthorizationPendingException$, AuthorizationPendingException);
|
||||
var CreateTokenRequest$ = [
|
||||
3,
|
||||
n0,
|
||||
_CTR,
|
||||
0,
|
||||
[_cI, _cS, _gT, _dC, _co, _rT, _s, _rU, _cV],
|
||||
[0, [() => ClientSecret, 0], 0, 0, 0, [() => RefreshToken, 0], 64 | 0, 0, [() => CodeVerifier, 0]],
|
||||
3,
|
||||
];
|
||||
var CreateTokenResponse$ = [
|
||||
3,
|
||||
n0,
|
||||
_CTRr,
|
||||
0,
|
||||
[_aT, _tT, _eI, _rT, _iT],
|
||||
[[() => AccessToken, 0], 0, 1, [() => RefreshToken, 0], [() => IdToken, 0]],
|
||||
];
|
||||
var ExpiredTokenException$ = [-3, n0, _ETE, { [_e]: _c, [_hE]: 400 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(ExpiredTokenException$, ExpiredTokenException);
|
||||
var InternalServerException$ = [-3, n0, _ISE, { [_e]: _se, [_hE]: 500 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(InternalServerException$, InternalServerException);
|
||||
var InvalidClientException$ = [-3, n0, _ICE, { [_e]: _c, [_hE]: 401 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(InvalidClientException$, InvalidClientException);
|
||||
var InvalidGrantException$ = [-3, n0, _IGE, { [_e]: _c, [_hE]: 400 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(InvalidGrantException$, InvalidGrantException);
|
||||
var InvalidRequestException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_IRE,
|
||||
{ [_e]: _c, [_hE]: 400 },
|
||||
[_e, _r, _ed],
|
||||
[0, 0, 0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(InvalidRequestException$, InvalidRequestException);
|
||||
var InvalidScopeException$ = [-3, n0, _ISEn, { [_e]: _c, [_hE]: 400 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(InvalidScopeException$, InvalidScopeException);
|
||||
var SlowDownException$ = [-3, n0, _SDE, { [_e]: _c, [_hE]: 400 }, [_e, _ed], [0, 0]];
|
||||
schema.TypeRegistry.for(n0).registerError(SlowDownException$, SlowDownException);
|
||||
var UnauthorizedClientException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_UCE,
|
||||
{ [_e]: _c, [_hE]: 400 },
|
||||
[_e, _ed],
|
||||
[0, 0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(UnauthorizedClientException$, UnauthorizedClientException);
|
||||
var UnsupportedGrantTypeException$ = [
|
||||
-3,
|
||||
n0,
|
||||
_UGTE,
|
||||
{ [_e]: _c, [_hE]: 400 },
|
||||
[_e, _ed],
|
||||
[0, 0],
|
||||
];
|
||||
schema.TypeRegistry.for(n0).registerError(UnsupportedGrantTypeException$, UnsupportedGrantTypeException);
|
||||
var SSOOIDCServiceException$ = [-3, _sm, "SSOOIDCServiceException", 0, [], []];
|
||||
schema.TypeRegistry.for(_sm).registerError(SSOOIDCServiceException$, SSOOIDCServiceException);
|
||||
var CreateToken$ = [
|
||||
9,
|
||||
n0,
|
||||
_CT,
|
||||
{ [_h]: ["POST", "/token", 200] },
|
||||
() => CreateTokenRequest$,
|
||||
() => CreateTokenResponse$,
|
||||
];
|
||||
|
||||
class CreateTokenCommand extends smithyClient.Command
|
||||
.classBuilder()
|
||||
.ep(commonParams)
|
||||
.m(function (Command, cs, config, o) {
|
||||
return [middlewareEndpoint.getEndpointPlugin(config, Command.getEndpointParameterInstructions())];
|
||||
})
|
||||
.s("AWSSSOOIDCService", "CreateToken", {})
|
||||
.n("SSOOIDCClient", "CreateTokenCommand")
|
||||
.sc(CreateToken$)
|
||||
.build() {
|
||||
}
|
||||
|
||||
const commands = {
|
||||
CreateTokenCommand,
|
||||
};
|
||||
class SSOOIDC extends SSOOIDCClient {
|
||||
}
|
||||
smithyClient.createAggregatedClient(commands, SSOOIDC);
|
||||
|
||||
const AccessDeniedExceptionReason = {
|
||||
KMS_ACCESS_DENIED: "KMS_AccessDeniedException",
|
||||
};
|
||||
const InvalidRequestExceptionReason = {
|
||||
KMS_DISABLED_KEY: "KMS_DisabledException",
|
||||
KMS_INVALID_KEY_USAGE: "KMS_InvalidKeyUsageException",
|
||||
KMS_INVALID_STATE: "KMS_InvalidStateException",
|
||||
KMS_KEY_NOT_FOUND: "KMS_NotFoundException",
|
||||
};
|
||||
|
||||
__webpack_unused_export__ = ({
|
||||
enumerable: true,
|
||||
get: function () { return smithyClient.Command; }
|
||||
});
|
||||
__webpack_unused_export__ = ({
|
||||
enumerable: true,
|
||||
get: function () { return smithyClient.Client; }
|
||||
});
|
||||
__webpack_unused_export__ = AccessDeniedException;
|
||||
__webpack_unused_export__ = AccessDeniedException$;
|
||||
__webpack_unused_export__ = AccessDeniedExceptionReason;
|
||||
__webpack_unused_export__ = AuthorizationPendingException;
|
||||
__webpack_unused_export__ = AuthorizationPendingException$;
|
||||
__webpack_unused_export__ = CreateToken$;
|
||||
exports.CreateTokenCommand = CreateTokenCommand;
|
||||
__webpack_unused_export__ = CreateTokenRequest$;
|
||||
__webpack_unused_export__ = CreateTokenResponse$;
|
||||
__webpack_unused_export__ = ExpiredTokenException;
|
||||
__webpack_unused_export__ = ExpiredTokenException$;
|
||||
__webpack_unused_export__ = InternalServerException;
|
||||
__webpack_unused_export__ = InternalServerException$;
|
||||
__webpack_unused_export__ = InvalidClientException;
|
||||
__webpack_unused_export__ = InvalidClientException$;
|
||||
__webpack_unused_export__ = InvalidGrantException;
|
||||
__webpack_unused_export__ = InvalidGrantException$;
|
||||
__webpack_unused_export__ = InvalidRequestException;
|
||||
__webpack_unused_export__ = InvalidRequestException$;
|
||||
__webpack_unused_export__ = InvalidRequestExceptionReason;
|
||||
__webpack_unused_export__ = InvalidScopeException;
|
||||
__webpack_unused_export__ = InvalidScopeException$;
|
||||
__webpack_unused_export__ = SSOOIDC;
|
||||
exports.SSOOIDCClient = SSOOIDCClient;
|
||||
__webpack_unused_export__ = SSOOIDCServiceException;
|
||||
__webpack_unused_export__ = SSOOIDCServiceException$;
|
||||
__webpack_unused_export__ = SlowDownException;
|
||||
__webpack_unused_export__ = SlowDownException$;
|
||||
__webpack_unused_export__ = UnauthorizedClientException;
|
||||
__webpack_unused_export__ = UnauthorizedClientException$;
|
||||
__webpack_unused_export__ = UnsupportedGrantTypeException;
|
||||
__webpack_unused_export__ = UnsupportedGrantTypeException$;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6901:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const tslib_1 = __webpack_require__(1860);
|
||||
const package_json_1 = tslib_1.__importDefault(__webpack_require__(9955));
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_user_agent_node_1 = __webpack_require__(1656);
|
||||
const config_resolver_1 = __webpack_require__(9316);
|
||||
const hash_node_1 = __webpack_require__(2711);
|
||||
const middleware_retry_1 = __webpack_require__(9618);
|
||||
const node_config_provider_1 = __webpack_require__(5704);
|
||||
const node_http_handler_1 = __webpack_require__(1279);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const util_body_length_node_1 = __webpack_require__(3638);
|
||||
const util_defaults_mode_node_1 = __webpack_require__(5435);
|
||||
const util_retry_1 = __webpack_require__(5518);
|
||||
const runtimeConfig_shared_1 = __webpack_require__(1546);
|
||||
const getRuntimeConfig = (config) => {
|
||||
(0, smithy_client_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config);
|
||||
const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode);
|
||||
const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config);
|
||||
(0, core_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const loaderConfig = {
|
||||
profile: config?.profile,
|
||||
logger: clientSharedValues.logger,
|
||||
};
|
||||
return {
|
||||
...clientSharedValues,
|
||||
...config,
|
||||
runtime: "node",
|
||||
defaultsMode,
|
||||
authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
|
||||
bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength,
|
||||
defaultUserAgentProvider: config?.defaultUserAgentProvider ??
|
||||
(0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }),
|
||||
maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
|
||||
region: config?.region ??
|
||||
(0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
|
||||
requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
|
||||
retryMode: config?.retryMode ??
|
||||
(0, node_config_provider_1.loadConfig)({
|
||||
...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS,
|
||||
default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE,
|
||||
}, config),
|
||||
sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"),
|
||||
streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector,
|
||||
useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig),
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1546:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const protocols_1 = __webpack_require__(7288);
|
||||
const core_2 = __webpack_require__(402);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const url_parser_1 = __webpack_require__(4494);
|
||||
const util_base64_1 = __webpack_require__(8385);
|
||||
const util_utf8_1 = __webpack_require__(1577);
|
||||
const httpAuthSchemeProvider_1 = __webpack_require__(8396);
|
||||
const endpointResolver_1 = __webpack_require__(546);
|
||||
const getRuntimeConfig = (config) => {
|
||||
return {
|
||||
apiVersion: "2019-06-10",
|
||||
base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64,
|
||||
base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64,
|
||||
disableHostPrefix: config?.disableHostPrefix ?? false,
|
||||
endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver,
|
||||
extensions: config?.extensions ?? [],
|
||||
httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSSOOIDCHttpAuthSchemeProvider,
|
||||
httpAuthSchemes: config?.httpAuthSchemes ?? [
|
||||
{
|
||||
schemeId: "aws.auth#sigv4",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"),
|
||||
signer: new core_1.AwsSdkSigV4Signer(),
|
||||
},
|
||||
{
|
||||
schemeId: "smithy.api#noAuth",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})),
|
||||
signer: new core_2.NoAuthSigner(),
|
||||
},
|
||||
],
|
||||
logger: config?.logger ?? new smithy_client_1.NoOpLogger(),
|
||||
protocol: config?.protocol ?? protocols_1.AwsRestJsonProtocol,
|
||||
protocolSettings: config?.protocolSettings ?? {
|
||||
defaultNamespace: "com.amazonaws.ssooidc",
|
||||
version: "2019-06-10",
|
||||
serviceTarget: "AWSSSOOIDCService",
|
||||
},
|
||||
serviceId: config?.serviceId ?? "SSO OIDC",
|
||||
urlParser: config?.urlParser ?? url_parser_1.parseUrl,
|
||||
utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8,
|
||||
utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8,
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9955:
|
||||
/***/ ((module) => {
|
||||
|
||||
module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/nested-clients","version":"3.982.0","description":"Nested clients for AWS SDK packages.","main":"./dist-cjs/index.js","module":"./dist-es/index.js","types":"./dist-types/index.d.ts","scripts":{"build":"yarn lint && concurrently \'yarn:build:types\' \'yarn:build:es\' && yarn build:cjs","build:cjs":"node ../../scripts/compilation/inline nested-clients","build:es":"tsc -p tsconfig.es.json","build:include:deps":"yarn g:turbo run build -F=\\"$npm_package_name\\"","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo","lint":"node ../../scripts/validation/submodules-linter.js --pkg nested-clients","test":"yarn g:vitest run","test:watch":"yarn g:vitest watch"},"engines":{"node":">=20.0.0"},"sideEffects":false,"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"^3.973.6","@aws-sdk/middleware-host-header":"^3.972.3","@aws-sdk/middleware-logger":"^3.972.3","@aws-sdk/middleware-recursion-detection":"^3.972.3","@aws-sdk/middleware-user-agent":"^3.972.6","@aws-sdk/region-config-resolver":"^3.972.3","@aws-sdk/types":"^3.973.1","@aws-sdk/util-endpoints":"3.982.0","@aws-sdk/util-user-agent-browser":"^3.972.3","@aws-sdk/util-user-agent-node":"^3.972.4","@smithy/config-resolver":"^4.4.6","@smithy/core":"^3.22.0","@smithy/fetch-http-handler":"^5.3.9","@smithy/hash-node":"^4.2.8","@smithy/invalid-dependency":"^4.2.8","@smithy/middleware-content-length":"^4.2.8","@smithy/middleware-endpoint":"^4.4.12","@smithy/middleware-retry":"^4.4.29","@smithy/middleware-serde":"^4.2.9","@smithy/middleware-stack":"^4.2.8","@smithy/node-config-provider":"^4.3.8","@smithy/node-http-handler":"^4.4.8","@smithy/protocol-http":"^5.3.8","@smithy/smithy-client":"^4.11.1","@smithy/types":"^4.12.0","@smithy/url-parser":"^4.2.8","@smithy/util-base64":"^4.3.0","@smithy/util-body-length-browser":"^4.2.0","@smithy/util-body-length-node":"^4.2.1","@smithy/util-defaults-mode-browser":"^4.3.28","@smithy/util-defaults-mode-node":"^4.2.31","@smithy/util-endpoints":"^3.2.8","@smithy/util-middleware":"^4.2.8","@smithy/util-retry":"^4.2.8","@smithy/util-utf8":"^4.2.0","tslib":"^2.6.2"},"devDependencies":{"concurrently":"7.0.0","downlevel-dts":"0.10.1","premove":"4.0.0","typescript":"~5.8.3"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["./signin.d.ts","./signin.js","./sso-oidc.d.ts","./sso-oidc.js","./sts.d.ts","./sts.js","dist-*/**"],"browser":{"./dist-es/submodules/signin/runtimeConfig":"./dist-es/submodules/signin/runtimeConfig.browser","./dist-es/submodules/sso-oidc/runtimeConfig":"./dist-es/submodules/sso-oidc/runtimeConfig.browser","./dist-es/submodules/sts/runtimeConfig":"./dist-es/submodules/sts/runtimeConfig.browser"},"react-native":{},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/packages/nested-clients","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"packages/nested-clients"},"exports":{"./package.json":"./package.json","./sso-oidc":{"types":"./dist-types/submodules/sso-oidc/index.d.ts","module":"./dist-es/submodules/sso-oidc/index.js","node":"./dist-cjs/submodules/sso-oidc/index.js","import":"./dist-es/submodules/sso-oidc/index.js","require":"./dist-cjs/submodules/sso-oidc/index.js"},"./sts":{"types":"./dist-types/submodules/sts/index.d.ts","module":"./dist-es/submodules/sts/index.js","node":"./dist-cjs/submodules/sts/index.js","import":"./dist-es/submodules/sts/index.js","require":"./dist-cjs/submodules/sts/index.js"},"./signin":{"types":"./dist-types/submodules/signin/index.d.ts","module":"./dist-es/submodules/signin/index.js","node":"./dist-cjs/submodules/signin/index.js","import":"./dist-es/submodules/signin/index.js","require":"./dist-cjs/submodules/signin/index.js"}}}');
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,387 @@
|
||||
"use strict";
|
||||
exports.id = 566;
|
||||
exports.ids = [566];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 566:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var __webpack_unused_export__;
|
||||
|
||||
|
||||
var propertyProvider = __webpack_require__(8857);
|
||||
var url = __webpack_require__(7016);
|
||||
var buffer = __webpack_require__(181);
|
||||
var http = __webpack_require__(8611);
|
||||
var nodeConfigProvider = __webpack_require__(5704);
|
||||
var urlParser = __webpack_require__(4494);
|
||||
|
||||
function httpRequest(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = http.request({
|
||||
method: "GET",
|
||||
...options,
|
||||
hostname: options.hostname?.replace(/^\[(.+)\]$/, "$1"),
|
||||
});
|
||||
req.on("error", (err) => {
|
||||
reject(Object.assign(new propertyProvider.ProviderError("Unable to connect to instance metadata service"), err));
|
||||
req.destroy();
|
||||
});
|
||||
req.on("timeout", () => {
|
||||
reject(new propertyProvider.ProviderError("TimeoutError from instance metadata service"));
|
||||
req.destroy();
|
||||
});
|
||||
req.on("response", (res) => {
|
||||
const { statusCode = 400 } = res;
|
||||
if (statusCode < 200 || 300 <= statusCode) {
|
||||
reject(Object.assign(new propertyProvider.ProviderError("Error response received from instance metadata service"), { statusCode }));
|
||||
req.destroy();
|
||||
}
|
||||
const chunks = [];
|
||||
res.on("data", (chunk) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
res.on("end", () => {
|
||||
resolve(buffer.Buffer.concat(chunks));
|
||||
req.destroy();
|
||||
});
|
||||
});
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
const isImdsCredentials = (arg) => Boolean(arg) &&
|
||||
typeof arg === "object" &&
|
||||
typeof arg.AccessKeyId === "string" &&
|
||||
typeof arg.SecretAccessKey === "string" &&
|
||||
typeof arg.Token === "string" &&
|
||||
typeof arg.Expiration === "string";
|
||||
const fromImdsCredentials = (creds) => ({
|
||||
accessKeyId: creds.AccessKeyId,
|
||||
secretAccessKey: creds.SecretAccessKey,
|
||||
sessionToken: creds.Token,
|
||||
expiration: new Date(creds.Expiration),
|
||||
...(creds.AccountId && { accountId: creds.AccountId }),
|
||||
});
|
||||
|
||||
const DEFAULT_TIMEOUT = 1000;
|
||||
const DEFAULT_MAX_RETRIES = 0;
|
||||
const providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT, }) => ({ maxRetries, timeout });
|
||||
|
||||
const retry = (toRetry, maxRetries) => {
|
||||
let promise = toRetry();
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
promise = promise.catch(toRetry);
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
|
||||
const ENV_CMDS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
|
||||
const ENV_CMDS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
|
||||
const ENV_CMDS_AUTH_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN";
|
||||
const fromContainerMetadata = (init = {}) => {
|
||||
const { timeout, maxRetries } = providerConfigFromInit(init);
|
||||
return () => retry(async () => {
|
||||
const requestOptions = await getCmdsUri({ logger: init.logger });
|
||||
const credsResponse = JSON.parse(await requestFromEcsImds(timeout, requestOptions));
|
||||
if (!isImdsCredentials(credsResponse)) {
|
||||
throw new propertyProvider.CredentialsProviderError("Invalid response received from instance metadata service.", {
|
||||
logger: init.logger,
|
||||
});
|
||||
}
|
||||
return fromImdsCredentials(credsResponse);
|
||||
}, maxRetries);
|
||||
};
|
||||
const requestFromEcsImds = async (timeout, options) => {
|
||||
if (process.env[ENV_CMDS_AUTH_TOKEN]) {
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
Authorization: process.env[ENV_CMDS_AUTH_TOKEN],
|
||||
};
|
||||
}
|
||||
const buffer = await httpRequest({
|
||||
...options,
|
||||
timeout,
|
||||
});
|
||||
return buffer.toString();
|
||||
};
|
||||
const CMDS_IP = "169.254.170.2";
|
||||
const GREENGRASS_HOSTS = {
|
||||
localhost: true,
|
||||
"127.0.0.1": true,
|
||||
};
|
||||
const GREENGRASS_PROTOCOLS = {
|
||||
"http:": true,
|
||||
"https:": true,
|
||||
};
|
||||
const getCmdsUri = async ({ logger }) => {
|
||||
if (process.env[ENV_CMDS_RELATIVE_URI]) {
|
||||
return {
|
||||
hostname: CMDS_IP,
|
||||
path: process.env[ENV_CMDS_RELATIVE_URI],
|
||||
};
|
||||
}
|
||||
if (process.env[ENV_CMDS_FULL_URI]) {
|
||||
const parsed = url.parse(process.env[ENV_CMDS_FULL_URI]);
|
||||
if (!parsed.hostname || !(parsed.hostname in GREENGRASS_HOSTS)) {
|
||||
throw new propertyProvider.CredentialsProviderError(`${parsed.hostname} is not a valid container metadata service hostname`, {
|
||||
tryNextLink: false,
|
||||
logger,
|
||||
});
|
||||
}
|
||||
if (!parsed.protocol || !(parsed.protocol in GREENGRASS_PROTOCOLS)) {
|
||||
throw new propertyProvider.CredentialsProviderError(`${parsed.protocol} is not a valid container metadata service protocol`, {
|
||||
tryNextLink: false,
|
||||
logger,
|
||||
});
|
||||
}
|
||||
return {
|
||||
...parsed,
|
||||
port: parsed.port ? parseInt(parsed.port, 10) : undefined,
|
||||
};
|
||||
}
|
||||
throw new propertyProvider.CredentialsProviderError("The container metadata credential provider cannot be used unless" +
|
||||
` the ${ENV_CMDS_RELATIVE_URI} or ${ENV_CMDS_FULL_URI} environment` +
|
||||
" variable is set", {
|
||||
tryNextLink: false,
|
||||
logger,
|
||||
});
|
||||
};
|
||||
|
||||
class InstanceMetadataV1FallbackError extends propertyProvider.CredentialsProviderError {
|
||||
tryNextLink;
|
||||
name = "InstanceMetadataV1FallbackError";
|
||||
constructor(message, tryNextLink = true) {
|
||||
super(message, tryNextLink);
|
||||
this.tryNextLink = tryNextLink;
|
||||
Object.setPrototypeOf(this, InstanceMetadataV1FallbackError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
exports.yI = void 0;
|
||||
(function (Endpoint) {
|
||||
Endpoint["IPv4"] = "http://169.254.169.254";
|
||||
Endpoint["IPv6"] = "http://[fd00:ec2::254]";
|
||||
})(exports.yI || (exports.yI = {}));
|
||||
|
||||
const ENV_ENDPOINT_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT";
|
||||
const CONFIG_ENDPOINT_NAME = "ec2_metadata_service_endpoint";
|
||||
const ENDPOINT_CONFIG_OPTIONS = {
|
||||
environmentVariableSelector: (env) => env[ENV_ENDPOINT_NAME],
|
||||
configFileSelector: (profile) => profile[CONFIG_ENDPOINT_NAME],
|
||||
default: undefined,
|
||||
};
|
||||
|
||||
var EndpointMode;
|
||||
(function (EndpointMode) {
|
||||
EndpointMode["IPv4"] = "IPv4";
|
||||
EndpointMode["IPv6"] = "IPv6";
|
||||
})(EndpointMode || (EndpointMode = {}));
|
||||
|
||||
const ENV_ENDPOINT_MODE_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE";
|
||||
const CONFIG_ENDPOINT_MODE_NAME = "ec2_metadata_service_endpoint_mode";
|
||||
const ENDPOINT_MODE_CONFIG_OPTIONS = {
|
||||
environmentVariableSelector: (env) => env[ENV_ENDPOINT_MODE_NAME],
|
||||
configFileSelector: (profile) => profile[CONFIG_ENDPOINT_MODE_NAME],
|
||||
default: EndpointMode.IPv4,
|
||||
};
|
||||
|
||||
const getInstanceMetadataEndpoint = async () => urlParser.parseUrl((await getFromEndpointConfig()) || (await getFromEndpointModeConfig()));
|
||||
const getFromEndpointConfig = async () => nodeConfigProvider.loadConfig(ENDPOINT_CONFIG_OPTIONS)();
|
||||
const getFromEndpointModeConfig = async () => {
|
||||
const endpointMode = await nodeConfigProvider.loadConfig(ENDPOINT_MODE_CONFIG_OPTIONS)();
|
||||
switch (endpointMode) {
|
||||
case EndpointMode.IPv4:
|
||||
return exports.yI.IPv4;
|
||||
case EndpointMode.IPv6:
|
||||
return exports.yI.IPv6;
|
||||
default:
|
||||
throw new Error(`Unsupported endpoint mode: ${endpointMode}.` + ` Select from ${Object.values(EndpointMode)}`);
|
||||
}
|
||||
};
|
||||
|
||||
const STATIC_STABILITY_REFRESH_INTERVAL_SECONDS = 5 * 60;
|
||||
const STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS = 5 * 60;
|
||||
const STATIC_STABILITY_DOC_URL = "https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html";
|
||||
const getExtendedInstanceMetadataCredentials = (credentials, logger) => {
|
||||
const refreshInterval = STATIC_STABILITY_REFRESH_INTERVAL_SECONDS +
|
||||
Math.floor(Math.random() * STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS);
|
||||
const newExpiration = new Date(Date.now() + refreshInterval * 1000);
|
||||
logger.warn("Attempting credential expiration extension due to a credential service availability issue. A refresh of these " +
|
||||
`credentials will be attempted after ${new Date(newExpiration)}.\nFor more information, please visit: ` +
|
||||
STATIC_STABILITY_DOC_URL);
|
||||
const originalExpiration = credentials.originalExpiration ?? credentials.expiration;
|
||||
return {
|
||||
...credentials,
|
||||
...(originalExpiration ? { originalExpiration } : {}),
|
||||
expiration: newExpiration,
|
||||
};
|
||||
};
|
||||
|
||||
const staticStabilityProvider = (provider, options = {}) => {
|
||||
const logger = options?.logger || console;
|
||||
let pastCredentials;
|
||||
return async () => {
|
||||
let credentials;
|
||||
try {
|
||||
credentials = await provider();
|
||||
if (credentials.expiration && credentials.expiration.getTime() < Date.now()) {
|
||||
credentials = getExtendedInstanceMetadataCredentials(credentials, logger);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
if (pastCredentials) {
|
||||
logger.warn("Credential renew failed: ", e);
|
||||
credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
pastCredentials = credentials;
|
||||
return credentials;
|
||||
};
|
||||
};
|
||||
|
||||
const IMDS_PATH = "/latest/meta-data/iam/security-credentials/";
|
||||
const IMDS_TOKEN_PATH = "/latest/api/token";
|
||||
const AWS_EC2_METADATA_V1_DISABLED = "AWS_EC2_METADATA_V1_DISABLED";
|
||||
const PROFILE_AWS_EC2_METADATA_V1_DISABLED = "ec2_metadata_v1_disabled";
|
||||
const X_AWS_EC2_METADATA_TOKEN = "x-aws-ec2-metadata-token";
|
||||
const fromInstanceMetadata = (init = {}) => staticStabilityProvider(getInstanceMetadataProvider(init), { logger: init.logger });
|
||||
const getInstanceMetadataProvider = (init = {}) => {
|
||||
let disableFetchToken = false;
|
||||
const { logger, profile } = init;
|
||||
const { timeout, maxRetries } = providerConfigFromInit(init);
|
||||
const getCredentials = async (maxRetries, options) => {
|
||||
const isImdsV1Fallback = disableFetchToken || options.headers?.[X_AWS_EC2_METADATA_TOKEN] == null;
|
||||
if (isImdsV1Fallback) {
|
||||
let fallbackBlockedFromProfile = false;
|
||||
let fallbackBlockedFromProcessEnv = false;
|
||||
const configValue = await nodeConfigProvider.loadConfig({
|
||||
environmentVariableSelector: (env) => {
|
||||
const envValue = env[AWS_EC2_METADATA_V1_DISABLED];
|
||||
fallbackBlockedFromProcessEnv = !!envValue && envValue !== "false";
|
||||
if (envValue === undefined) {
|
||||
throw new propertyProvider.CredentialsProviderError(`${AWS_EC2_METADATA_V1_DISABLED} not set in env, checking config file next.`, { logger: init.logger });
|
||||
}
|
||||
return fallbackBlockedFromProcessEnv;
|
||||
},
|
||||
configFileSelector: (profile) => {
|
||||
const profileValue = profile[PROFILE_AWS_EC2_METADATA_V1_DISABLED];
|
||||
fallbackBlockedFromProfile = !!profileValue && profileValue !== "false";
|
||||
return fallbackBlockedFromProfile;
|
||||
},
|
||||
default: false,
|
||||
}, {
|
||||
profile,
|
||||
})();
|
||||
if (init.ec2MetadataV1Disabled || configValue) {
|
||||
const causes = [];
|
||||
if (init.ec2MetadataV1Disabled)
|
||||
causes.push("credential provider initialization (runtime option ec2MetadataV1Disabled)");
|
||||
if (fallbackBlockedFromProfile)
|
||||
causes.push(`config file profile (${PROFILE_AWS_EC2_METADATA_V1_DISABLED})`);
|
||||
if (fallbackBlockedFromProcessEnv)
|
||||
causes.push(`process environment variable (${AWS_EC2_METADATA_V1_DISABLED})`);
|
||||
throw new InstanceMetadataV1FallbackError(`AWS EC2 Metadata v1 fallback has been blocked by AWS SDK configuration in the following: [${causes.join(", ")}].`);
|
||||
}
|
||||
}
|
||||
const imdsProfile = (await retry(async () => {
|
||||
let profile;
|
||||
try {
|
||||
profile = await getProfile(options);
|
||||
}
|
||||
catch (err) {
|
||||
if (err.statusCode === 401) {
|
||||
disableFetchToken = false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return profile;
|
||||
}, maxRetries)).trim();
|
||||
return retry(async () => {
|
||||
let creds;
|
||||
try {
|
||||
creds = await getCredentialsFromProfile(imdsProfile, options, init);
|
||||
}
|
||||
catch (err) {
|
||||
if (err.statusCode === 401) {
|
||||
disableFetchToken = false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
return creds;
|
||||
}, maxRetries);
|
||||
};
|
||||
return async () => {
|
||||
const endpoint = await getInstanceMetadataEndpoint();
|
||||
if (disableFetchToken) {
|
||||
logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (no token fetch)");
|
||||
return getCredentials(maxRetries, { ...endpoint, timeout });
|
||||
}
|
||||
else {
|
||||
let token;
|
||||
try {
|
||||
token = (await getMetadataToken({ ...endpoint, timeout })).toString();
|
||||
}
|
||||
catch (error) {
|
||||
if (error?.statusCode === 400) {
|
||||
throw Object.assign(error, {
|
||||
message: "EC2 Metadata token request returned error",
|
||||
});
|
||||
}
|
||||
else if (error.message === "TimeoutError" || [403, 404, 405].includes(error.statusCode)) {
|
||||
disableFetchToken = true;
|
||||
}
|
||||
logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (initial)");
|
||||
return getCredentials(maxRetries, { ...endpoint, timeout });
|
||||
}
|
||||
return getCredentials(maxRetries, {
|
||||
...endpoint,
|
||||
headers: {
|
||||
[X_AWS_EC2_METADATA_TOKEN]: token,
|
||||
},
|
||||
timeout,
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
const getMetadataToken = async (options) => httpRequest({
|
||||
...options,
|
||||
path: IMDS_TOKEN_PATH,
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"x-aws-ec2-metadata-token-ttl-seconds": "21600",
|
||||
},
|
||||
});
|
||||
const getProfile = async (options) => (await httpRequest({ ...options, path: IMDS_PATH })).toString();
|
||||
const getCredentialsFromProfile = async (profile, options, init) => {
|
||||
const credentialsResponse = JSON.parse((await httpRequest({
|
||||
...options,
|
||||
path: IMDS_PATH + profile,
|
||||
})).toString());
|
||||
if (!isImdsCredentials(credentialsResponse)) {
|
||||
throw new propertyProvider.CredentialsProviderError("Invalid response received from instance metadata service.", {
|
||||
logger: init.logger,
|
||||
});
|
||||
}
|
||||
return fromImdsCredentials(credentialsResponse);
|
||||
};
|
||||
|
||||
__webpack_unused_export__ = DEFAULT_MAX_RETRIES;
|
||||
__webpack_unused_export__ = DEFAULT_TIMEOUT;
|
||||
__webpack_unused_export__ = ENV_CMDS_AUTH_TOKEN;
|
||||
exports.ENV_CMDS_FULL_URI = ENV_CMDS_FULL_URI;
|
||||
exports.ENV_CMDS_RELATIVE_URI = ENV_CMDS_RELATIVE_URI;
|
||||
exports.fromContainerMetadata = fromContainerMetadata;
|
||||
exports.fromInstanceMetadata = fromInstanceMetadata;
|
||||
exports.getInstanceMetadataEndpoint = getInstanceMetadataEndpoint;
|
||||
exports.httpRequest = httpRequest;
|
||||
__webpack_unused_export__ = providerConfigFromInit;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,270 @@
|
||||
"use strict";
|
||||
exports.id = 579;
|
||||
exports.ids = [579];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 6579:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
|
||||
var utilUtf8 = __webpack_require__(1577);
|
||||
|
||||
class EventStreamSerde {
|
||||
marshaller;
|
||||
serializer;
|
||||
deserializer;
|
||||
serdeContext;
|
||||
defaultContentType;
|
||||
constructor({ marshaller, serializer, deserializer, serdeContext, defaultContentType, }) {
|
||||
this.marshaller = marshaller;
|
||||
this.serializer = serializer;
|
||||
this.deserializer = deserializer;
|
||||
this.serdeContext = serdeContext;
|
||||
this.defaultContentType = defaultContentType;
|
||||
}
|
||||
async serializeEventStream({ eventStream, requestSchema, initialRequest, }) {
|
||||
const marshaller = this.marshaller;
|
||||
const eventStreamMember = requestSchema.getEventStreamMember();
|
||||
const unionSchema = requestSchema.getMemberSchema(eventStreamMember);
|
||||
const serializer = this.serializer;
|
||||
const defaultContentType = this.defaultContentType;
|
||||
const initialRequestMarker = Symbol("initialRequestMarker");
|
||||
const eventStreamIterable = {
|
||||
async *[Symbol.asyncIterator]() {
|
||||
if (initialRequest) {
|
||||
const headers = {
|
||||
":event-type": { type: "string", value: "initial-request" },
|
||||
":message-type": { type: "string", value: "event" },
|
||||
":content-type": { type: "string", value: defaultContentType },
|
||||
};
|
||||
serializer.write(requestSchema, initialRequest);
|
||||
const body = serializer.flush();
|
||||
yield {
|
||||
[initialRequestMarker]: true,
|
||||
headers,
|
||||
body,
|
||||
};
|
||||
}
|
||||
for await (const page of eventStream) {
|
||||
yield page;
|
||||
}
|
||||
},
|
||||
};
|
||||
return marshaller.serialize(eventStreamIterable, (event) => {
|
||||
if (event[initialRequestMarker]) {
|
||||
return {
|
||||
headers: event.headers,
|
||||
body: event.body,
|
||||
};
|
||||
}
|
||||
const unionMember = Object.keys(event).find((key) => {
|
||||
return key !== "__type";
|
||||
}) ?? "";
|
||||
const { additionalHeaders, body, eventType, explicitPayloadContentType } = this.writeEventBody(unionMember, unionSchema, event);
|
||||
const headers = {
|
||||
":event-type": { type: "string", value: eventType },
|
||||
":message-type": { type: "string", value: "event" },
|
||||
":content-type": { type: "string", value: explicitPayloadContentType ?? defaultContentType },
|
||||
...additionalHeaders,
|
||||
};
|
||||
return {
|
||||
headers,
|
||||
body,
|
||||
};
|
||||
});
|
||||
}
|
||||
async deserializeEventStream({ response, responseSchema, initialResponseContainer, }) {
|
||||
const marshaller = this.marshaller;
|
||||
const eventStreamMember = responseSchema.getEventStreamMember();
|
||||
const unionSchema = responseSchema.getMemberSchema(eventStreamMember);
|
||||
const memberSchemas = unionSchema.getMemberSchemas();
|
||||
const initialResponseMarker = Symbol("initialResponseMarker");
|
||||
const asyncIterable = marshaller.deserialize(response.body, async (event) => {
|
||||
const unionMember = Object.keys(event).find((key) => {
|
||||
return key !== "__type";
|
||||
}) ?? "";
|
||||
const body = event[unionMember].body;
|
||||
if (unionMember === "initial-response") {
|
||||
const dataObject = await this.deserializer.read(responseSchema, body);
|
||||
delete dataObject[eventStreamMember];
|
||||
return {
|
||||
[initialResponseMarker]: true,
|
||||
...dataObject,
|
||||
};
|
||||
}
|
||||
else if (unionMember in memberSchemas) {
|
||||
const eventStreamSchema = memberSchemas[unionMember];
|
||||
if (eventStreamSchema.isStructSchema()) {
|
||||
const out = {};
|
||||
let hasBindings = false;
|
||||
for (const [name, member] of eventStreamSchema.structIterator()) {
|
||||
const { eventHeader, eventPayload } = member.getMergedTraits();
|
||||
hasBindings = hasBindings || Boolean(eventHeader || eventPayload);
|
||||
if (eventPayload) {
|
||||
if (member.isBlobSchema()) {
|
||||
out[name] = body;
|
||||
}
|
||||
else if (member.isStringSchema()) {
|
||||
out[name] = (this.serdeContext?.utf8Encoder ?? utilUtf8.toUtf8)(body);
|
||||
}
|
||||
else if (member.isStructSchema()) {
|
||||
out[name] = await this.deserializer.read(member, body);
|
||||
}
|
||||
}
|
||||
else if (eventHeader) {
|
||||
const value = event[unionMember].headers[name]?.value;
|
||||
if (value != null) {
|
||||
if (member.isNumericSchema()) {
|
||||
if (value && typeof value === "object" && "bytes" in value) {
|
||||
out[name] = BigInt(value.toString());
|
||||
}
|
||||
else {
|
||||
out[name] = Number(value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
out[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasBindings) {
|
||||
return {
|
||||
[unionMember]: out,
|
||||
};
|
||||
}
|
||||
if (body.byteLength === 0) {
|
||||
return {
|
||||
[unionMember]: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
[unionMember]: await this.deserializer.read(eventStreamSchema, body),
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
$unknown: event,
|
||||
};
|
||||
}
|
||||
});
|
||||
const asyncIterator = asyncIterable[Symbol.asyncIterator]();
|
||||
const firstEvent = await asyncIterator.next();
|
||||
if (firstEvent.done) {
|
||||
return asyncIterable;
|
||||
}
|
||||
if (firstEvent.value?.[initialResponseMarker]) {
|
||||
if (!responseSchema) {
|
||||
throw new Error("@smithy::core/protocols - initial-response event encountered in event stream but no response schema given.");
|
||||
}
|
||||
for (const [key, value] of Object.entries(firstEvent.value)) {
|
||||
initialResponseContainer[key] = value;
|
||||
}
|
||||
}
|
||||
return {
|
||||
async *[Symbol.asyncIterator]() {
|
||||
if (!firstEvent?.value?.[initialResponseMarker]) {
|
||||
yield firstEvent.value;
|
||||
}
|
||||
while (true) {
|
||||
const { done, value } = await asyncIterator.next();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
yield value;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
writeEventBody(unionMember, unionSchema, event) {
|
||||
const serializer = this.serializer;
|
||||
let eventType = unionMember;
|
||||
let explicitPayloadMember = null;
|
||||
let explicitPayloadContentType;
|
||||
const isKnownSchema = (() => {
|
||||
const struct = unionSchema.getSchema();
|
||||
return struct[4].includes(unionMember);
|
||||
})();
|
||||
const additionalHeaders = {};
|
||||
if (!isKnownSchema) {
|
||||
const [type, value] = event[unionMember];
|
||||
eventType = type;
|
||||
serializer.write(15, value);
|
||||
}
|
||||
else {
|
||||
const eventSchema = unionSchema.getMemberSchema(unionMember);
|
||||
if (eventSchema.isStructSchema()) {
|
||||
for (const [memberName, memberSchema] of eventSchema.structIterator()) {
|
||||
const { eventHeader, eventPayload } = memberSchema.getMergedTraits();
|
||||
if (eventPayload) {
|
||||
explicitPayloadMember = memberName;
|
||||
}
|
||||
else if (eventHeader) {
|
||||
const value = event[unionMember][memberName];
|
||||
let type = "binary";
|
||||
if (memberSchema.isNumericSchema()) {
|
||||
if ((-2) ** 31 <= value && value <= 2 ** 31 - 1) {
|
||||
type = "integer";
|
||||
}
|
||||
else {
|
||||
type = "long";
|
||||
}
|
||||
}
|
||||
else if (memberSchema.isTimestampSchema()) {
|
||||
type = "timestamp";
|
||||
}
|
||||
else if (memberSchema.isStringSchema()) {
|
||||
type = "string";
|
||||
}
|
||||
else if (memberSchema.isBooleanSchema()) {
|
||||
type = "boolean";
|
||||
}
|
||||
if (value != null) {
|
||||
additionalHeaders[memberName] = {
|
||||
type,
|
||||
value,
|
||||
};
|
||||
delete event[unionMember][memberName];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (explicitPayloadMember !== null) {
|
||||
const payloadSchema = eventSchema.getMemberSchema(explicitPayloadMember);
|
||||
if (payloadSchema.isBlobSchema()) {
|
||||
explicitPayloadContentType = "application/octet-stream";
|
||||
}
|
||||
else if (payloadSchema.isStringSchema()) {
|
||||
explicitPayloadContentType = "text/plain";
|
||||
}
|
||||
serializer.write(payloadSchema, event[unionMember][explicitPayloadMember]);
|
||||
}
|
||||
else {
|
||||
serializer.write(eventSchema, event[unionMember]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("@smithy/core/event-streams - non-struct member not supported in event stream union.");
|
||||
}
|
||||
}
|
||||
const messageSerialization = serializer.flush();
|
||||
const body = typeof messageSerialization === "string"
|
||||
? (this.serdeContext?.utf8Decoder ?? utilUtf8.fromUtf8)(messageSerialization)
|
||||
: messageSerialization;
|
||||
return {
|
||||
body,
|
||||
eventType,
|
||||
explicitPayloadContentType,
|
||||
additionalHeaders,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
exports.EventStreamSerde = EventStreamSerde;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,234 @@
|
||||
"use strict";
|
||||
exports.id = 605;
|
||||
exports.ids = [605];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 1509:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.checkUrl = void 0;
|
||||
const property_provider_1 = __webpack_require__(8857);
|
||||
const LOOPBACK_CIDR_IPv4 = "127.0.0.0/8";
|
||||
const LOOPBACK_CIDR_IPv6 = "::1/128";
|
||||
const ECS_CONTAINER_HOST = "169.254.170.2";
|
||||
const EKS_CONTAINER_HOST_IPv4 = "169.254.170.23";
|
||||
const EKS_CONTAINER_HOST_IPv6 = "[fd00:ec2::23]";
|
||||
const checkUrl = (url, logger) => {
|
||||
if (url.protocol === "https:") {
|
||||
return;
|
||||
}
|
||||
if (url.hostname === ECS_CONTAINER_HOST ||
|
||||
url.hostname === EKS_CONTAINER_HOST_IPv4 ||
|
||||
url.hostname === EKS_CONTAINER_HOST_IPv6) {
|
||||
return;
|
||||
}
|
||||
if (url.hostname.includes("[")) {
|
||||
if (url.hostname === "[::1]" || url.hostname === "[0000:0000:0000:0000:0000:0000:0000:0001]") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (url.hostname === "localhost") {
|
||||
return;
|
||||
}
|
||||
const ipComponents = url.hostname.split(".");
|
||||
const inRange = (component) => {
|
||||
const num = parseInt(component, 10);
|
||||
return 0 <= num && num <= 255;
|
||||
};
|
||||
if (ipComponents[0] === "127" &&
|
||||
inRange(ipComponents[1]) &&
|
||||
inRange(ipComponents[2]) &&
|
||||
inRange(ipComponents[3]) &&
|
||||
ipComponents.length === 4) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new property_provider_1.CredentialsProviderError(`URL not accepted. It must either be HTTPS or match one of the following:
|
||||
- loopback CIDR 127.0.0.0/8 or [::1/128]
|
||||
- ECS container host 169.254.170.2
|
||||
- EKS container host 169.254.170.23 or [fd00:ec2::23]`, { logger });
|
||||
};
|
||||
exports.checkUrl = checkUrl;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8712:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.fromHttp = void 0;
|
||||
const tslib_1 = __webpack_require__(1860);
|
||||
const client_1 = __webpack_require__(5152);
|
||||
const node_http_handler_1 = __webpack_require__(1279);
|
||||
const property_provider_1 = __webpack_require__(8857);
|
||||
const promises_1 = tslib_1.__importDefault(__webpack_require__(1943));
|
||||
const checkUrl_1 = __webpack_require__(1509);
|
||||
const requestHelpers_1 = __webpack_require__(8914);
|
||||
const retry_wrapper_1 = __webpack_require__(1122);
|
||||
const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI";
|
||||
const DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2";
|
||||
const AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI";
|
||||
const AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE";
|
||||
const AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN";
|
||||
const fromHttp = (options = {}) => {
|
||||
options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp");
|
||||
let host;
|
||||
const relative = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI];
|
||||
const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI];
|
||||
const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN];
|
||||
const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE];
|
||||
const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger?.warn
|
||||
? console.warn
|
||||
: options.logger.warn.bind(options.logger);
|
||||
if (relative && full) {
|
||||
warn("@aws-sdk/credential-provider-http: " +
|
||||
"you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri.");
|
||||
warn("awsContainerCredentialsFullUri will take precedence.");
|
||||
}
|
||||
if (token && tokenFile) {
|
||||
warn("@aws-sdk/credential-provider-http: " +
|
||||
"you have set both awsContainerAuthorizationToken and awsContainerAuthorizationTokenFile.");
|
||||
warn("awsContainerAuthorizationToken will take precedence.");
|
||||
}
|
||||
if (full) {
|
||||
host = full;
|
||||
}
|
||||
else if (relative) {
|
||||
host = `${DEFAULT_LINK_LOCAL_HOST}${relative}`;
|
||||
}
|
||||
else {
|
||||
throw new property_provider_1.CredentialsProviderError(`No HTTP credential provider host provided.
|
||||
Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.`, { logger: options.logger });
|
||||
}
|
||||
const url = new URL(host);
|
||||
(0, checkUrl_1.checkUrl)(url, options.logger);
|
||||
const requestHandler = node_http_handler_1.NodeHttpHandler.create({
|
||||
requestTimeout: options.timeout ?? 1000,
|
||||
connectionTimeout: options.timeout ?? 1000,
|
||||
});
|
||||
return (0, retry_wrapper_1.retryWrapper)(async () => {
|
||||
const request = (0, requestHelpers_1.createGetRequest)(url);
|
||||
if (token) {
|
||||
request.headers.Authorization = token;
|
||||
}
|
||||
else if (tokenFile) {
|
||||
request.headers.Authorization = (await promises_1.default.readFile(tokenFile)).toString();
|
||||
}
|
||||
try {
|
||||
const result = await requestHandler.handle(request);
|
||||
return (0, requestHelpers_1.getCredentials)(result.response).then((creds) => (0, client_1.setCredentialFeature)(creds, "CREDENTIALS_HTTP", "z"));
|
||||
}
|
||||
catch (e) {
|
||||
throw new property_provider_1.CredentialsProviderError(String(e), { logger: options.logger });
|
||||
}
|
||||
}, options.maxRetries ?? 3, options.timeout ?? 1000);
|
||||
};
|
||||
exports.fromHttp = fromHttp;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8914:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.createGetRequest = createGetRequest;
|
||||
exports.getCredentials = getCredentials;
|
||||
const property_provider_1 = __webpack_require__(8857);
|
||||
const protocol_http_1 = __webpack_require__(2356);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const util_stream_1 = __webpack_require__(4252);
|
||||
function createGetRequest(url) {
|
||||
return new protocol_http_1.HttpRequest({
|
||||
protocol: url.protocol,
|
||||
hostname: url.hostname,
|
||||
port: Number(url.port),
|
||||
path: url.pathname,
|
||||
query: Array.from(url.searchParams.entries()).reduce((acc, [k, v]) => {
|
||||
acc[k] = v;
|
||||
return acc;
|
||||
}, {}),
|
||||
fragment: url.hash,
|
||||
});
|
||||
}
|
||||
async function getCredentials(response, logger) {
|
||||
const stream = (0, util_stream_1.sdkStreamMixin)(response.body);
|
||||
const str = await stream.transformToString();
|
||||
if (response.statusCode === 200) {
|
||||
const parsed = JSON.parse(str);
|
||||
if (typeof parsed.AccessKeyId !== "string" ||
|
||||
typeof parsed.SecretAccessKey !== "string" ||
|
||||
typeof parsed.Token !== "string" ||
|
||||
typeof parsed.Expiration !== "string") {
|
||||
throw new property_provider_1.CredentialsProviderError("HTTP credential provider response not of the required format, an object matching: " +
|
||||
"{ AccessKeyId: string, SecretAccessKey: string, Token: string, Expiration: string(rfc3339) }", { logger });
|
||||
}
|
||||
return {
|
||||
accessKeyId: parsed.AccessKeyId,
|
||||
secretAccessKey: parsed.SecretAccessKey,
|
||||
sessionToken: parsed.Token,
|
||||
expiration: (0, smithy_client_1.parseRfc3339DateTime)(parsed.Expiration),
|
||||
};
|
||||
}
|
||||
if (response.statusCode >= 400 && response.statusCode < 500) {
|
||||
let parsedBody = {};
|
||||
try {
|
||||
parsedBody = JSON.parse(str);
|
||||
}
|
||||
catch (e) { }
|
||||
throw Object.assign(new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger }), {
|
||||
Code: parsedBody.Code,
|
||||
Message: parsedBody.Message,
|
||||
});
|
||||
}
|
||||
throw new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger });
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1122:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.retryWrapper = void 0;
|
||||
const retryWrapper = (toRetry, maxRetries, delayMs) => {
|
||||
return async () => {
|
||||
for (let i = 0; i < maxRetries; ++i) {
|
||||
try {
|
||||
return await toRetry();
|
||||
}
|
||||
catch (e) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
||||
}
|
||||
}
|
||||
return await toRetry();
|
||||
};
|
||||
};
|
||||
exports.retryWrapper = retryWrapper;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8605:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var __webpack_unused_export__;
|
||||
|
||||
__webpack_unused_export__ = ({ value: true });
|
||||
exports.fromHttp = void 0;
|
||||
var fromHttp_1 = __webpack_require__(8712);
|
||||
Object.defineProperty(exports, "fromHttp", ({ enumerable: true, get: function () { return fromHttp_1.fromHttp; } }));
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,587 @@
|
||||
"use strict";
|
||||
exports.id = 762;
|
||||
exports.ids = [762];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 7709:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.resolveHttpAuthSchemeConfig = exports.defaultSigninHttpAuthSchemeProvider = exports.defaultSigninHttpAuthSchemeParametersProvider = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_middleware_1 = __webpack_require__(6324);
|
||||
const defaultSigninHttpAuthSchemeParametersProvider = async (config, context, input) => {
|
||||
return {
|
||||
operation: (0, util_middleware_1.getSmithyContext)(context).operation,
|
||||
region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) ||
|
||||
(() => {
|
||||
throw new Error("expected `region` to be configured for `aws.auth#sigv4`");
|
||||
})(),
|
||||
};
|
||||
};
|
||||
exports.defaultSigninHttpAuthSchemeParametersProvider = defaultSigninHttpAuthSchemeParametersProvider;
|
||||
function createAwsAuthSigv4HttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "aws.auth#sigv4",
|
||||
signingProperties: {
|
||||
name: "signin",
|
||||
region: authParameters.region,
|
||||
},
|
||||
propertiesExtractor: (config, context) => ({
|
||||
signingProperties: {
|
||||
config,
|
||||
context,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
||||
function createSmithyApiNoAuthHttpAuthOption(authParameters) {
|
||||
return {
|
||||
schemeId: "smithy.api#noAuth",
|
||||
};
|
||||
}
|
||||
const defaultSigninHttpAuthSchemeProvider = (authParameters) => {
|
||||
const options = [];
|
||||
switch (authParameters.operation) {
|
||||
case "CreateOAuth2Token": {
|
||||
options.push(createSmithyApiNoAuthHttpAuthOption(authParameters));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
options.push(createAwsAuthSigv4HttpAuthOption(authParameters));
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
exports.defaultSigninHttpAuthSchemeProvider = defaultSigninHttpAuthSchemeProvider;
|
||||
const resolveHttpAuthSchemeConfig = (config) => {
|
||||
const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config);
|
||||
return Object.assign(config_0, {
|
||||
authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []),
|
||||
});
|
||||
};
|
||||
exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2547:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.defaultEndpointResolver = void 0;
|
||||
const util_endpoints_1 = __webpack_require__(3068);
|
||||
const util_endpoints_2 = __webpack_require__(9674);
|
||||
const ruleset_1 = __webpack_require__(6904);
|
||||
const cache = new util_endpoints_2.EndpointCache({
|
||||
size: 50,
|
||||
params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"],
|
||||
});
|
||||
const defaultEndpointResolver = (endpointParams, context = {}) => {
|
||||
return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, {
|
||||
endpointParams: endpointParams,
|
||||
logger: context.logger,
|
||||
}));
|
||||
};
|
||||
exports.defaultEndpointResolver = defaultEndpointResolver;
|
||||
util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6904:
|
||||
/***/ ((__unused_webpack_module, exports) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.ruleSet = void 0;
|
||||
const u = "required", v = "fn", w = "argv", x = "ref";
|
||||
const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "stringEquals", i = { [u]: true, "default": false, "type": "boolean" }, j = { [u]: false, "type": "string" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: "getAttr", [w]: [{ [x]: g }, "name"] }, p = { [v]: c, [w]: [{ [x]: "UseFIPS" }, false] }, q = { [v]: c, [w]: [{ [x]: "UseDualStack" }, false] }, r = { [v]: "getAttr", [w]: [{ [x]: g }, "supportsFIPS"] }, s = { [v]: c, [w]: [true, { [v]: "getAttr", [w]: [{ [x]: g }, "supportsDualStack"] }] }, t = [{ [x]: "Region" }];
|
||||
const _data = { version: "1.0", parameters: { UseDualStack: i, UseFIPS: i, Endpoint: j, Region: j }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: [l], error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { rules: [{ conditions: [m], error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }], type: f }, { rules: [{ conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [{ [v]: h, [w]: [o, "aws"] }, p, q], endpoint: { url: "https://{Region}.signin.aws.amazon.com", properties: n, headers: n }, type: e }, { conditions: [{ [v]: h, [w]: [o, "aws-cn"] }, p, q], endpoint: { url: "https://{Region}.signin.amazonaws.cn", properties: n, headers: n }, type: e }, { conditions: [{ [v]: h, [w]: [o, "aws-us-gov"] }, p, q], endpoint: { url: "https://{Region}.signin.amazonaws-us-gov.com", properties: n, headers: n }, type: e }, { conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, r] }, s], rules: [{ endpoint: { url: "https://signin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: [l, q], rules: [{ conditions: [{ [v]: c, [w]: [r, a] }], rules: [{ endpoint: { url: "https://signin-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: [p, m], rules: [{ conditions: [s], rules: [{ endpoint: { url: "https://signin.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://signin.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }], type: f }] };
|
||||
exports.ruleSet = _data;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9762:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
var __webpack_unused_export__;
|
||||
|
||||
|
||||
var middlewareHostHeader = __webpack_require__(2590);
|
||||
var middlewareLogger = __webpack_require__(5242);
|
||||
var middlewareRecursionDetection = __webpack_require__(1568);
|
||||
var middlewareUserAgent = __webpack_require__(2959);
|
||||
var configResolver = __webpack_require__(9316);
|
||||
var core = __webpack_require__(402);
|
||||
var schema = __webpack_require__(6890);
|
||||
var middlewareContentLength = __webpack_require__(7212);
|
||||
var middlewareEndpoint = __webpack_require__(99);
|
||||
var middlewareRetry = __webpack_require__(9618);
|
||||
var smithyClient = __webpack_require__(1411);
|
||||
var httpAuthSchemeProvider = __webpack_require__(7709);
|
||||
var runtimeConfig = __webpack_require__(2836);
|
||||
var regionConfigResolver = __webpack_require__(6463);
|
||||
var protocolHttp = __webpack_require__(2356);
|
||||
|
||||
const resolveClientEndpointParameters = (options) => {
|
||||
return Object.assign(options, {
|
||||
useDualstackEndpoint: options.useDualstackEndpoint ?? false,
|
||||
useFipsEndpoint: options.useFipsEndpoint ?? false,
|
||||
defaultSigningName: "signin",
|
||||
});
|
||||
};
|
||||
const commonParams = {
|
||||
UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" },
|
||||
Endpoint: { type: "builtInParams", name: "endpoint" },
|
||||
Region: { type: "builtInParams", name: "region" },
|
||||
UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" },
|
||||
};
|
||||
|
||||
const getHttpAuthExtensionConfiguration = (runtimeConfig) => {
|
||||
const _httpAuthSchemes = runtimeConfig.httpAuthSchemes;
|
||||
let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider;
|
||||
let _credentials = runtimeConfig.credentials;
|
||||
return {
|
||||
setHttpAuthScheme(httpAuthScheme) {
|
||||
const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId);
|
||||
if (index === -1) {
|
||||
_httpAuthSchemes.push(httpAuthScheme);
|
||||
}
|
||||
else {
|
||||
_httpAuthSchemes.splice(index, 1, httpAuthScheme);
|
||||
}
|
||||
},
|
||||
httpAuthSchemes() {
|
||||
return _httpAuthSchemes;
|
||||
},
|
||||
setHttpAuthSchemeProvider(httpAuthSchemeProvider) {
|
||||
_httpAuthSchemeProvider = httpAuthSchemeProvider;
|
||||
},
|
||||
httpAuthSchemeProvider() {
|
||||
return _httpAuthSchemeProvider;
|
||||
},
|
||||
setCredentials(credentials) {
|
||||
_credentials = credentials;
|
||||
},
|
||||
credentials() {
|
||||
return _credentials;
|
||||
},
|
||||
};
|
||||
};
|
||||
const resolveHttpAuthRuntimeConfig = (config) => {
|
||||
return {
|
||||
httpAuthSchemes: config.httpAuthSchemes(),
|
||||
httpAuthSchemeProvider: config.httpAuthSchemeProvider(),
|
||||
credentials: config.credentials(),
|
||||
};
|
||||
};
|
||||
|
||||
const resolveRuntimeExtensions = (runtimeConfig, extensions) => {
|
||||
const extensionConfiguration = Object.assign(regionConfigResolver.getAwsRegionExtensionConfiguration(runtimeConfig), smithyClient.getDefaultExtensionConfiguration(runtimeConfig), protocolHttp.getHttpHandlerExtensionConfiguration(runtimeConfig), getHttpAuthExtensionConfiguration(runtimeConfig));
|
||||
extensions.forEach((extension) => extension.configure(extensionConfiguration));
|
||||
return Object.assign(runtimeConfig, regionConfigResolver.resolveAwsRegionExtensionConfiguration(extensionConfiguration), smithyClient.resolveDefaultRuntimeConfig(extensionConfiguration), protocolHttp.resolveHttpHandlerRuntimeConfig(extensionConfiguration), resolveHttpAuthRuntimeConfig(extensionConfiguration));
|
||||
};
|
||||
|
||||
class SigninClient extends smithyClient.Client {
|
||||
config;
|
||||
constructor(...[configuration]) {
|
||||
const _config_0 = runtimeConfig.getRuntimeConfig(configuration || {});
|
||||
super(_config_0);
|
||||
this.initConfig = _config_0;
|
||||
const _config_1 = resolveClientEndpointParameters(_config_0);
|
||||
const _config_2 = middlewareUserAgent.resolveUserAgentConfig(_config_1);
|
||||
const _config_3 = middlewareRetry.resolveRetryConfig(_config_2);
|
||||
const _config_4 = configResolver.resolveRegionConfig(_config_3);
|
||||
const _config_5 = middlewareHostHeader.resolveHostHeaderConfig(_config_4);
|
||||
const _config_6 = middlewareEndpoint.resolveEndpointConfig(_config_5);
|
||||
const _config_7 = httpAuthSchemeProvider.resolveHttpAuthSchemeConfig(_config_6);
|
||||
const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []);
|
||||
this.config = _config_8;
|
||||
this.middlewareStack.use(schema.getSchemaSerdePlugin(this.config));
|
||||
this.middlewareStack.use(middlewareUserAgent.getUserAgentPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareRetry.getRetryPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareContentLength.getContentLengthPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareHostHeader.getHostHeaderPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareLogger.getLoggerPlugin(this.config));
|
||||
this.middlewareStack.use(middlewareRecursionDetection.getRecursionDetectionPlugin(this.config));
|
||||
this.middlewareStack.use(core.getHttpAuthSchemeEndpointRuleSetPlugin(this.config, {
|
||||
httpAuthSchemeParametersProvider: httpAuthSchemeProvider.defaultSigninHttpAuthSchemeParametersProvider,
|
||||
identityProviderConfigProvider: async (config) => new core.DefaultIdentityProviderConfig({
|
||||
"aws.auth#sigv4": config.credentials,
|
||||
}),
|
||||
}));
|
||||
this.middlewareStack.use(core.getHttpSigningPlugin(this.config));
|
||||
}
|
||||
destroy() {
|
||||
super.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
class SigninServiceException extends smithyClient.ServiceException {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
Object.setPrototypeOf(this, SigninServiceException.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
class AccessDeniedException extends SigninServiceException {
|
||||
name = "AccessDeniedException";
|
||||
$fault = "client";
|
||||
error;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "AccessDeniedException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, AccessDeniedException.prototype);
|
||||
this.error = opts.error;
|
||||
}
|
||||
}
|
||||
class InternalServerException extends SigninServiceException {
|
||||
name = "InternalServerException";
|
||||
$fault = "server";
|
||||
error;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "InternalServerException",
|
||||
$fault: "server",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, InternalServerException.prototype);
|
||||
this.error = opts.error;
|
||||
}
|
||||
}
|
||||
class TooManyRequestsError extends SigninServiceException {
|
||||
name = "TooManyRequestsError";
|
||||
$fault = "client";
|
||||
error;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "TooManyRequestsError",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, TooManyRequestsError.prototype);
|
||||
this.error = opts.error;
|
||||
}
|
||||
}
|
||||
class ValidationException extends SigninServiceException {
|
||||
name = "ValidationException";
|
||||
$fault = "client";
|
||||
error;
|
||||
constructor(opts) {
|
||||
super({
|
||||
name: "ValidationException",
|
||||
$fault: "client",
|
||||
...opts,
|
||||
});
|
||||
Object.setPrototypeOf(this, ValidationException.prototype);
|
||||
this.error = opts.error;
|
||||
}
|
||||
}
|
||||
|
||||
const _ADE = "AccessDeniedException";
|
||||
const _AT = "AccessToken";
|
||||
const _COAT = "CreateOAuth2Token";
|
||||
const _COATR = "CreateOAuth2TokenRequest";
|
||||
const _COATRB = "CreateOAuth2TokenRequestBody";
|
||||
const _COATRBr = "CreateOAuth2TokenResponseBody";
|
||||
const _COATRr = "CreateOAuth2TokenResponse";
|
||||
const _ISE = "InternalServerException";
|
||||
const _RT = "RefreshToken";
|
||||
const _TMRE = "TooManyRequestsError";
|
||||
const _VE = "ValidationException";
|
||||
const _aKI = "accessKeyId";
|
||||
const _aT = "accessToken";
|
||||
const _c = "client";
|
||||
const _cI = "clientId";
|
||||
const _cV = "codeVerifier";
|
||||
const _co = "code";
|
||||
const _e = "error";
|
||||
const _eI = "expiresIn";
|
||||
const _gT = "grantType";
|
||||
const _h = "http";
|
||||
const _hE = "httpError";
|
||||
const _iT = "idToken";
|
||||
const _jN = "jsonName";
|
||||
const _m = "message";
|
||||
const _rT = "refreshToken";
|
||||
const _rU = "redirectUri";
|
||||
const _s = "server";
|
||||
const _sAK = "secretAccessKey";
|
||||
const _sT = "sessionToken";
|
||||
const _sm = "smithy.ts.sdk.synthetic.com.amazonaws.signin";
|
||||
const _tI = "tokenInput";
|
||||
const _tO = "tokenOutput";
|
||||
const _tT = "tokenType";
|
||||
const n0 = "com.amazonaws.signin";
|
||||
var RefreshToken = [0, n0, _RT, 8, 0];
|
||||
var AccessDeniedException$ = [-3, n0, _ADE, { [_e]: _c }, [_e, _m], [0, 0], 2];
|
||||
schema.TypeRegistry.for(n0).registerError(AccessDeniedException$, AccessDeniedException);
|
||||
var AccessToken$ = [
|
||||
3,
|
||||
n0,
|
||||
_AT,
|
||||
8,
|
||||
[_aKI, _sAK, _sT],
|
||||
[
|
||||
[0, { [_jN]: _aKI }],
|
||||
[0, { [_jN]: _sAK }],
|
||||
[0, { [_jN]: _sT }],
|
||||
],
|
||||
3,
|
||||
];
|
||||
var CreateOAuth2TokenRequest$ = [
|
||||
3,
|
||||
n0,
|
||||
_COATR,
|
||||
0,
|
||||
[_tI],
|
||||
[[() => CreateOAuth2TokenRequestBody$, 16]],
|
||||
1,
|
||||
];
|
||||
var CreateOAuth2TokenRequestBody$ = [
|
||||
3,
|
||||
n0,
|
||||
_COATRB,
|
||||
0,
|
||||
[_cI, _gT, _co, _rU, _cV, _rT],
|
||||
[
|
||||
[0, { [_jN]: _cI }],
|
||||
[0, { [_jN]: _gT }],
|
||||
0,
|
||||
[0, { [_jN]: _rU }],
|
||||
[0, { [_jN]: _cV }],
|
||||
[() => RefreshToken, { [_jN]: _rT }],
|
||||
],
|
||||
2,
|
||||
];
|
||||
var CreateOAuth2TokenResponse$ = [
|
||||
3,
|
||||
n0,
|
||||
_COATRr,
|
||||
0,
|
||||
[_tO],
|
||||
[[() => CreateOAuth2TokenResponseBody$, 16]],
|
||||
1,
|
||||
];
|
||||
var CreateOAuth2TokenResponseBody$ = [
|
||||
3,
|
||||
n0,
|
||||
_COATRBr,
|
||||
0,
|
||||
[_aT, _tT, _eI, _rT, _iT],
|
||||
[
|
||||
[() => AccessToken$, { [_jN]: _aT }],
|
||||
[0, { [_jN]: _tT }],
|
||||
[1, { [_jN]: _eI }],
|
||||
[() => RefreshToken, { [_jN]: _rT }],
|
||||
[0, { [_jN]: _iT }],
|
||||
],
|
||||
4,
|
||||
];
|
||||
var InternalServerException$ = [-3, n0, _ISE, { [_e]: _s, [_hE]: 500 }, [_e, _m], [0, 0], 2];
|
||||
schema.TypeRegistry.for(n0).registerError(InternalServerException$, InternalServerException);
|
||||
var TooManyRequestsError$ = [-3, n0, _TMRE, { [_e]: _c, [_hE]: 429 }, [_e, _m], [0, 0], 2];
|
||||
schema.TypeRegistry.for(n0).registerError(TooManyRequestsError$, TooManyRequestsError);
|
||||
var ValidationException$ = [-3, n0, _VE, { [_e]: _c, [_hE]: 400 }, [_e, _m], [0, 0], 2];
|
||||
schema.TypeRegistry.for(n0).registerError(ValidationException$, ValidationException);
|
||||
var SigninServiceException$ = [-3, _sm, "SigninServiceException", 0, [], []];
|
||||
schema.TypeRegistry.for(_sm).registerError(SigninServiceException$, SigninServiceException);
|
||||
var CreateOAuth2Token$ = [
|
||||
9,
|
||||
n0,
|
||||
_COAT,
|
||||
{ [_h]: ["POST", "/v1/token", 200] },
|
||||
() => CreateOAuth2TokenRequest$,
|
||||
() => CreateOAuth2TokenResponse$,
|
||||
];
|
||||
|
||||
class CreateOAuth2TokenCommand extends smithyClient.Command
|
||||
.classBuilder()
|
||||
.ep(commonParams)
|
||||
.m(function (Command, cs, config, o) {
|
||||
return [middlewareEndpoint.getEndpointPlugin(config, Command.getEndpointParameterInstructions())];
|
||||
})
|
||||
.s("Signin", "CreateOAuth2Token", {})
|
||||
.n("SigninClient", "CreateOAuth2TokenCommand")
|
||||
.sc(CreateOAuth2Token$)
|
||||
.build() {
|
||||
}
|
||||
|
||||
const commands = {
|
||||
CreateOAuth2TokenCommand,
|
||||
};
|
||||
class Signin extends SigninClient {
|
||||
}
|
||||
smithyClient.createAggregatedClient(commands, Signin);
|
||||
|
||||
const OAuth2ErrorCode = {
|
||||
AUTHCODE_EXPIRED: "AUTHCODE_EXPIRED",
|
||||
INSUFFICIENT_PERMISSIONS: "INSUFFICIENT_PERMISSIONS",
|
||||
INVALID_REQUEST: "INVALID_REQUEST",
|
||||
SERVER_ERROR: "server_error",
|
||||
TOKEN_EXPIRED: "TOKEN_EXPIRED",
|
||||
USER_CREDENTIALS_CHANGED: "USER_CREDENTIALS_CHANGED",
|
||||
};
|
||||
|
||||
__webpack_unused_export__ = ({
|
||||
enumerable: true,
|
||||
get: function () { return smithyClient.Command; }
|
||||
});
|
||||
__webpack_unused_export__ = ({
|
||||
enumerable: true,
|
||||
get: function () { return smithyClient.Client; }
|
||||
});
|
||||
__webpack_unused_export__ = AccessDeniedException;
|
||||
__webpack_unused_export__ = AccessDeniedException$;
|
||||
__webpack_unused_export__ = AccessToken$;
|
||||
__webpack_unused_export__ = CreateOAuth2Token$;
|
||||
exports.CreateOAuth2TokenCommand = CreateOAuth2TokenCommand;
|
||||
__webpack_unused_export__ = CreateOAuth2TokenRequest$;
|
||||
__webpack_unused_export__ = CreateOAuth2TokenRequestBody$;
|
||||
__webpack_unused_export__ = CreateOAuth2TokenResponse$;
|
||||
__webpack_unused_export__ = CreateOAuth2TokenResponseBody$;
|
||||
__webpack_unused_export__ = InternalServerException;
|
||||
__webpack_unused_export__ = InternalServerException$;
|
||||
__webpack_unused_export__ = OAuth2ErrorCode;
|
||||
__webpack_unused_export__ = Signin;
|
||||
exports.SigninClient = SigninClient;
|
||||
__webpack_unused_export__ = SigninServiceException;
|
||||
__webpack_unused_export__ = SigninServiceException$;
|
||||
__webpack_unused_export__ = TooManyRequestsError;
|
||||
__webpack_unused_export__ = TooManyRequestsError$;
|
||||
__webpack_unused_export__ = ValidationException;
|
||||
__webpack_unused_export__ = ValidationException$;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 2836:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const tslib_1 = __webpack_require__(1860);
|
||||
const package_json_1 = tslib_1.__importDefault(__webpack_require__(9955));
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const util_user_agent_node_1 = __webpack_require__(1656);
|
||||
const config_resolver_1 = __webpack_require__(9316);
|
||||
const hash_node_1 = __webpack_require__(2711);
|
||||
const middleware_retry_1 = __webpack_require__(9618);
|
||||
const node_config_provider_1 = __webpack_require__(5704);
|
||||
const node_http_handler_1 = __webpack_require__(1279);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const util_body_length_node_1 = __webpack_require__(3638);
|
||||
const util_defaults_mode_node_1 = __webpack_require__(5435);
|
||||
const util_retry_1 = __webpack_require__(5518);
|
||||
const runtimeConfig_shared_1 = __webpack_require__(357);
|
||||
const getRuntimeConfig = (config) => {
|
||||
(0, smithy_client_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config);
|
||||
const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode);
|
||||
const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config);
|
||||
(0, core_1.emitWarningIfUnsupportedVersion)(process.version);
|
||||
const loaderConfig = {
|
||||
profile: config?.profile,
|
||||
logger: clientSharedValues.logger,
|
||||
};
|
||||
return {
|
||||
...clientSharedValues,
|
||||
...config,
|
||||
runtime: "node",
|
||||
defaultsMode,
|
||||
authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig),
|
||||
bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength,
|
||||
defaultUserAgentProvider: config?.defaultUserAgentProvider ??
|
||||
(0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }),
|
||||
maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config),
|
||||
region: config?.region ??
|
||||
(0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }),
|
||||
requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider),
|
||||
retryMode: config?.retryMode ??
|
||||
(0, node_config_provider_1.loadConfig)({
|
||||
...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS,
|
||||
default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE,
|
||||
}, config),
|
||||
sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"),
|
||||
streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector,
|
||||
useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig),
|
||||
userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig),
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 357:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuntimeConfig = void 0;
|
||||
const core_1 = __webpack_require__(8704);
|
||||
const protocols_1 = __webpack_require__(7288);
|
||||
const core_2 = __webpack_require__(402);
|
||||
const smithy_client_1 = __webpack_require__(1411);
|
||||
const url_parser_1 = __webpack_require__(4494);
|
||||
const util_base64_1 = __webpack_require__(8385);
|
||||
const util_utf8_1 = __webpack_require__(1577);
|
||||
const httpAuthSchemeProvider_1 = __webpack_require__(7709);
|
||||
const endpointResolver_1 = __webpack_require__(2547);
|
||||
const getRuntimeConfig = (config) => {
|
||||
return {
|
||||
apiVersion: "2023-01-01",
|
||||
base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64,
|
||||
base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64,
|
||||
disableHostPrefix: config?.disableHostPrefix ?? false,
|
||||
endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver,
|
||||
extensions: config?.extensions ?? [],
|
||||
httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSigninHttpAuthSchemeProvider,
|
||||
httpAuthSchemes: config?.httpAuthSchemes ?? [
|
||||
{
|
||||
schemeId: "aws.auth#sigv4",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"),
|
||||
signer: new core_1.AwsSdkSigV4Signer(),
|
||||
},
|
||||
{
|
||||
schemeId: "smithy.api#noAuth",
|
||||
identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})),
|
||||
signer: new core_2.NoAuthSigner(),
|
||||
},
|
||||
],
|
||||
logger: config?.logger ?? new smithy_client_1.NoOpLogger(),
|
||||
protocol: config?.protocol ?? protocols_1.AwsRestJsonProtocol,
|
||||
protocolSettings: config?.protocolSettings ?? {
|
||||
defaultNamespace: "com.amazonaws.signin",
|
||||
version: "2023-01-01",
|
||||
serviceTarget: "Signin",
|
||||
},
|
||||
serviceId: config?.serviceId ?? "Signin",
|
||||
urlParser: config?.urlParser ?? url_parser_1.parseUrl,
|
||||
utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8,
|
||||
utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8,
|
||||
};
|
||||
};
|
||||
exports.getRuntimeConfig = getRuntimeConfig;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 9955:
|
||||
/***/ ((module) => {
|
||||
|
||||
module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/nested-clients","version":"3.982.0","description":"Nested clients for AWS SDK packages.","main":"./dist-cjs/index.js","module":"./dist-es/index.js","types":"./dist-types/index.d.ts","scripts":{"build":"yarn lint && concurrently \'yarn:build:types\' \'yarn:build:es\' && yarn build:cjs","build:cjs":"node ../../scripts/compilation/inline nested-clients","build:es":"tsc -p tsconfig.es.json","build:include:deps":"yarn g:turbo run build -F=\\"$npm_package_name\\"","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"premove dist-cjs dist-es dist-types tsconfig.cjs.tsbuildinfo tsconfig.es.tsbuildinfo tsconfig.types.tsbuildinfo","lint":"node ../../scripts/validation/submodules-linter.js --pkg nested-clients","test":"yarn g:vitest run","test:watch":"yarn g:vitest watch"},"engines":{"node":">=20.0.0"},"sideEffects":false,"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"^3.973.6","@aws-sdk/middleware-host-header":"^3.972.3","@aws-sdk/middleware-logger":"^3.972.3","@aws-sdk/middleware-recursion-detection":"^3.972.3","@aws-sdk/middleware-user-agent":"^3.972.6","@aws-sdk/region-config-resolver":"^3.972.3","@aws-sdk/types":"^3.973.1","@aws-sdk/util-endpoints":"3.982.0","@aws-sdk/util-user-agent-browser":"^3.972.3","@aws-sdk/util-user-agent-node":"^3.972.4","@smithy/config-resolver":"^4.4.6","@smithy/core":"^3.22.0","@smithy/fetch-http-handler":"^5.3.9","@smithy/hash-node":"^4.2.8","@smithy/invalid-dependency":"^4.2.8","@smithy/middleware-content-length":"^4.2.8","@smithy/middleware-endpoint":"^4.4.12","@smithy/middleware-retry":"^4.4.29","@smithy/middleware-serde":"^4.2.9","@smithy/middleware-stack":"^4.2.8","@smithy/node-config-provider":"^4.3.8","@smithy/node-http-handler":"^4.4.8","@smithy/protocol-http":"^5.3.8","@smithy/smithy-client":"^4.11.1","@smithy/types":"^4.12.0","@smithy/url-parser":"^4.2.8","@smithy/util-base64":"^4.3.0","@smithy/util-body-length-browser":"^4.2.0","@smithy/util-body-length-node":"^4.2.1","@smithy/util-defaults-mode-browser":"^4.3.28","@smithy/util-defaults-mode-node":"^4.2.31","@smithy/util-endpoints":"^3.2.8","@smithy/util-middleware":"^4.2.8","@smithy/util-retry":"^4.2.8","@smithy/util-utf8":"^4.2.0","tslib":"^2.6.2"},"devDependencies":{"concurrently":"7.0.0","downlevel-dts":"0.10.1","premove":"4.0.0","typescript":"~5.8.3"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["./signin.d.ts","./signin.js","./sso-oidc.d.ts","./sso-oidc.js","./sts.d.ts","./sts.js","dist-*/**"],"browser":{"./dist-es/submodules/signin/runtimeConfig":"./dist-es/submodules/signin/runtimeConfig.browser","./dist-es/submodules/sso-oidc/runtimeConfig":"./dist-es/submodules/sso-oidc/runtimeConfig.browser","./dist-es/submodules/sts/runtimeConfig":"./dist-es/submodules/sts/runtimeConfig.browser"},"react-native":{},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/packages/nested-clients","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"packages/nested-clients"},"exports":{"./package.json":"./package.json","./sso-oidc":{"types":"./dist-types/submodules/sso-oidc/index.d.ts","module":"./dist-es/submodules/sso-oidc/index.js","node":"./dist-cjs/submodules/sso-oidc/index.js","import":"./dist-es/submodules/sso-oidc/index.js","require":"./dist-cjs/submodules/sso-oidc/index.js"},"./sts":{"types":"./dist-types/submodules/sts/index.d.ts","module":"./dist-es/submodules/sts/index.js","node":"./dist-cjs/submodules/sts/index.js","import":"./dist-es/submodules/sts/index.js","require":"./dist-cjs/submodules/sts/index.js"},"./signin":{"types":"./dist-types/submodules/signin/index.d.ts","module":"./dist-es/submodules/signin/index.js","node":"./dist-cjs/submodules/signin/index.js","import":"./dist-es/submodules/signin/index.js","require":"./dist-cjs/submodules/signin/index.js"}}}');
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
@@ -0,0 +1,531 @@
|
||||
"use strict";
|
||||
exports.id = 869;
|
||||
exports.ids = [869];
|
||||
exports.modules = {
|
||||
|
||||
/***/ 5869:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
|
||||
var sharedIniFileLoader = __webpack_require__(4964);
|
||||
var propertyProvider = __webpack_require__(8857);
|
||||
var client = __webpack_require__(5152);
|
||||
var credentialProviderLogin = __webpack_require__(4072);
|
||||
|
||||
const resolveCredentialSource = (credentialSource, profileName, logger) => {
|
||||
const sourceProvidersMap = {
|
||||
EcsContainer: async (options) => {
|
||||
const { fromHttp } = await __webpack_require__.e(/* import() */ 605).then(__webpack_require__.bind(__webpack_require__, 8605));
|
||||
const { fromContainerMetadata } = await __webpack_require__.e(/* import() */ 566).then(__webpack_require__.t.bind(__webpack_require__, 566, 19));
|
||||
logger?.debug("@aws-sdk/credential-provider-ini - credential_source is EcsContainer");
|
||||
return async () => propertyProvider.chain(fromHttp(options ?? {}), fromContainerMetadata(options))().then(setNamedProvider);
|
||||
},
|
||||
Ec2InstanceMetadata: async (options) => {
|
||||
logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Ec2InstanceMetadata");
|
||||
const { fromInstanceMetadata } = await __webpack_require__.e(/* import() */ 566).then(__webpack_require__.t.bind(__webpack_require__, 566, 19));
|
||||
return async () => fromInstanceMetadata(options)().then(setNamedProvider);
|
||||
},
|
||||
Environment: async (options) => {
|
||||
logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Environment");
|
||||
const { fromEnv } = await Promise.resolve(/* import() */).then(__webpack_require__.t.bind(__webpack_require__, 5606, 19));
|
||||
return async () => fromEnv(options)().then(setNamedProvider);
|
||||
},
|
||||
};
|
||||
if (credentialSource in sourceProvidersMap) {
|
||||
return sourceProvidersMap[credentialSource];
|
||||
}
|
||||
else {
|
||||
throw new propertyProvider.CredentialsProviderError(`Unsupported credential source in profile ${profileName}. Got ${credentialSource}, ` +
|
||||
`expected EcsContainer or Ec2InstanceMetadata or Environment.`, { logger });
|
||||
}
|
||||
};
|
||||
const setNamedProvider = (creds) => client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p");
|
||||
|
||||
const isAssumeRoleProfile = (arg, { profile = "default", logger } = {}) => {
|
||||
return (Boolean(arg) &&
|
||||
typeof arg === "object" &&
|
||||
typeof arg.role_arn === "string" &&
|
||||
["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 &&
|
||||
["undefined", "string"].indexOf(typeof arg.external_id) > -1 &&
|
||||
["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 &&
|
||||
(isAssumeRoleWithSourceProfile(arg, { profile, logger }) || isCredentialSourceProfile(arg, { profile, logger })));
|
||||
};
|
||||
const isAssumeRoleWithSourceProfile = (arg, { profile, logger }) => {
|
||||
const withSourceProfile = typeof arg.source_profile === "string" && typeof arg.credential_source === "undefined";
|
||||
if (withSourceProfile) {
|
||||
logger?.debug?.(` ${profile} isAssumeRoleWithSourceProfile source_profile=${arg.source_profile}`);
|
||||
}
|
||||
return withSourceProfile;
|
||||
};
|
||||
const isCredentialSourceProfile = (arg, { profile, logger }) => {
|
||||
const withProviderProfile = typeof arg.credential_source === "string" && typeof arg.source_profile === "undefined";
|
||||
if (withProviderProfile) {
|
||||
logger?.debug?.(` ${profile} isCredentialSourceProfile credential_source=${arg.credential_source}`);
|
||||
}
|
||||
return withProviderProfile;
|
||||
};
|
||||
const resolveAssumeRoleCredentials = async (profileName, profiles, options, callerClientConfig, visitedProfiles = {}, resolveProfileData) => {
|
||||
options.logger?.debug("@aws-sdk/credential-provider-ini - resolveAssumeRoleCredentials (STS)");
|
||||
const profileData = profiles[profileName];
|
||||
const { source_profile, region } = profileData;
|
||||
if (!options.roleAssumer) {
|
||||
const { getDefaultRoleAssumer } = await __webpack_require__.e(/* import() */ 136).then(__webpack_require__.t.bind(__webpack_require__, 1136, 23));
|
||||
options.roleAssumer = getDefaultRoleAssumer({
|
||||
...options.clientConfig,
|
||||
credentialProviderLogger: options.logger,
|
||||
parentClientConfig: {
|
||||
...callerClientConfig,
|
||||
...options?.parentClientConfig,
|
||||
region: region ?? options?.parentClientConfig?.region ?? callerClientConfig?.region,
|
||||
},
|
||||
}, options.clientPlugins);
|
||||
}
|
||||
if (source_profile && source_profile in visitedProfiles) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Detected a cycle attempting to resolve credentials for profile` +
|
||||
` ${sharedIniFileLoader.getProfileName(options)}. Profiles visited: ` +
|
||||
Object.keys(visitedProfiles).join(", "), { logger: options.logger });
|
||||
}
|
||||
options.logger?.debug(`@aws-sdk/credential-provider-ini - finding credential resolver using ${source_profile ? `source_profile=[${source_profile}]` : `profile=[${profileName}]`}`);
|
||||
const sourceCredsProvider = source_profile
|
||||
? resolveProfileData(source_profile, profiles, options, callerClientConfig, {
|
||||
...visitedProfiles,
|
||||
[source_profile]: true,
|
||||
}, isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {}))
|
||||
: (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))();
|
||||
if (isCredentialSourceWithoutRoleArn(profileData)) {
|
||||
return sourceCredsProvider.then((creds) => client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
||||
}
|
||||
else {
|
||||
const params = {
|
||||
RoleArn: profileData.role_arn,
|
||||
RoleSessionName: profileData.role_session_name || `aws-sdk-js-${Date.now()}`,
|
||||
ExternalId: profileData.external_id,
|
||||
DurationSeconds: parseInt(profileData.duration_seconds || "3600", 10),
|
||||
};
|
||||
const { mfa_serial } = profileData;
|
||||
if (mfa_serial) {
|
||||
if (!options.mfaCodeProvider) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Profile ${profileName} requires multi-factor authentication, but no MFA code callback was provided.`, { logger: options.logger, tryNextLink: false });
|
||||
}
|
||||
params.SerialNumber = mfa_serial;
|
||||
params.TokenCode = await options.mfaCodeProvider(mfa_serial);
|
||||
}
|
||||
const sourceCreds = await sourceCredsProvider;
|
||||
return options.roleAssumer(sourceCreds, params).then((creds) => client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o"));
|
||||
}
|
||||
};
|
||||
const isCredentialSourceWithoutRoleArn = (section) => {
|
||||
return !section.role_arn && !!section.credential_source;
|
||||
};
|
||||
|
||||
const isLoginProfile = (data) => {
|
||||
return Boolean(data && data.login_session);
|
||||
};
|
||||
const resolveLoginCredentials = async (profileName, options, callerClientConfig) => {
|
||||
const credentials = await credentialProviderLogin.fromLoginCredentials({
|
||||
...options,
|
||||
profile: profileName,
|
||||
})({ callerClientConfig });
|
||||
return client.setCredentialFeature(credentials, "CREDENTIALS_PROFILE_LOGIN", "AC");
|
||||
};
|
||||
|
||||
const isProcessProfile = (arg) => Boolean(arg) && typeof arg === "object" && typeof arg.credential_process === "string";
|
||||
const resolveProcessCredentials = async (options, profile) => __webpack_require__.e(/* import() */ 360).then(__webpack_require__.t.bind(__webpack_require__, 5360, 19)).then(({ fromProcess }) => fromProcess({
|
||||
...options,
|
||||
profile,
|
||||
})().then((creds) => client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_PROCESS", "v")));
|
||||
|
||||
const resolveSsoCredentials = async (profile, profileData, options = {}, callerClientConfig) => {
|
||||
const { fromSSO } = await __webpack_require__.e(/* import() */ 998).then(__webpack_require__.t.bind(__webpack_require__, 998, 19));
|
||||
return fromSSO({
|
||||
profile,
|
||||
logger: options.logger,
|
||||
parentClientConfig: options.parentClientConfig,
|
||||
clientConfig: options.clientConfig,
|
||||
})({
|
||||
callerClientConfig,
|
||||
}).then((creds) => {
|
||||
if (profileData.sso_session) {
|
||||
return client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SSO", "r");
|
||||
}
|
||||
else {
|
||||
return client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t");
|
||||
}
|
||||
});
|
||||
};
|
||||
const isSsoProfile = (arg) => arg &&
|
||||
(typeof arg.sso_start_url === "string" ||
|
||||
typeof arg.sso_account_id === "string" ||
|
||||
typeof arg.sso_session === "string" ||
|
||||
typeof arg.sso_region === "string" ||
|
||||
typeof arg.sso_role_name === "string");
|
||||
|
||||
const isStaticCredsProfile = (arg) => Boolean(arg) &&
|
||||
typeof arg === "object" &&
|
||||
typeof arg.aws_access_key_id === "string" &&
|
||||
typeof arg.aws_secret_access_key === "string" &&
|
||||
["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1 &&
|
||||
["undefined", "string"].indexOf(typeof arg.aws_account_id) > -1;
|
||||
const resolveStaticCredentials = async (profile, options) => {
|
||||
options?.logger?.debug("@aws-sdk/credential-provider-ini - resolveStaticCredentials");
|
||||
const credentials = {
|
||||
accessKeyId: profile.aws_access_key_id,
|
||||
secretAccessKey: profile.aws_secret_access_key,
|
||||
sessionToken: profile.aws_session_token,
|
||||
...(profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope }),
|
||||
...(profile.aws_account_id && { accountId: profile.aws_account_id }),
|
||||
};
|
||||
return client.setCredentialFeature(credentials, "CREDENTIALS_PROFILE", "n");
|
||||
};
|
||||
|
||||
const isWebIdentityProfile = (arg) => Boolean(arg) &&
|
||||
typeof arg === "object" &&
|
||||
typeof arg.web_identity_token_file === "string" &&
|
||||
typeof arg.role_arn === "string" &&
|
||||
["undefined", "string"].indexOf(typeof arg.role_session_name) > -1;
|
||||
const resolveWebIdentityCredentials = async (profile, options, callerClientConfig) => __webpack_require__.e(/* import() */ 956).then(__webpack_require__.t.bind(__webpack_require__, 9956, 23)).then(({ fromTokenFile }) => fromTokenFile({
|
||||
webIdentityTokenFile: profile.web_identity_token_file,
|
||||
roleArn: profile.role_arn,
|
||||
roleSessionName: profile.role_session_name,
|
||||
roleAssumerWithWebIdentity: options.roleAssumerWithWebIdentity,
|
||||
logger: options.logger,
|
||||
parentClientConfig: options.parentClientConfig,
|
||||
})({
|
||||
callerClientConfig,
|
||||
}).then((creds) => client.setCredentialFeature(creds, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q")));
|
||||
|
||||
const resolveProfileData = async (profileName, profiles, options, callerClientConfig, visitedProfiles = {}, isAssumeRoleRecursiveCall = false) => {
|
||||
const data = profiles[profileName];
|
||||
if (Object.keys(visitedProfiles).length > 0 && isStaticCredsProfile(data)) {
|
||||
return resolveStaticCredentials(data, options);
|
||||
}
|
||||
if (isAssumeRoleRecursiveCall || isAssumeRoleProfile(data, { profile: profileName, logger: options.logger })) {
|
||||
return resolveAssumeRoleCredentials(profileName, profiles, options, callerClientConfig, visitedProfiles, resolveProfileData);
|
||||
}
|
||||
if (isStaticCredsProfile(data)) {
|
||||
return resolveStaticCredentials(data, options);
|
||||
}
|
||||
if (isWebIdentityProfile(data)) {
|
||||
return resolveWebIdentityCredentials(data, options, callerClientConfig);
|
||||
}
|
||||
if (isProcessProfile(data)) {
|
||||
return resolveProcessCredentials(options, profileName);
|
||||
}
|
||||
if (isSsoProfile(data)) {
|
||||
return await resolveSsoCredentials(profileName, data, options, callerClientConfig);
|
||||
}
|
||||
if (isLoginProfile(data)) {
|
||||
return resolveLoginCredentials(profileName, options, callerClientConfig);
|
||||
}
|
||||
throw new propertyProvider.CredentialsProviderError(`Could not resolve credentials using profile: [${profileName}] in configuration/credentials file(s).`, { logger: options.logger });
|
||||
};
|
||||
|
||||
const fromIni = (init = {}) => async ({ callerClientConfig } = {}) => {
|
||||
init.logger?.debug("@aws-sdk/credential-provider-ini - fromIni");
|
||||
const profiles = await sharedIniFileLoader.parseKnownFiles(init);
|
||||
return resolveProfileData(sharedIniFileLoader.getProfileName({
|
||||
profile: init.profile ?? callerClientConfig?.profile,
|
||||
}), profiles, init, callerClientConfig);
|
||||
};
|
||||
|
||||
exports.fromIni = fromIni;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4072:
|
||||
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||
|
||||
|
||||
|
||||
var client = __webpack_require__(5152);
|
||||
var propertyProvider = __webpack_require__(8857);
|
||||
var sharedIniFileLoader = __webpack_require__(4964);
|
||||
var protocolHttp = __webpack_require__(2356);
|
||||
var node_crypto = __webpack_require__(7598);
|
||||
var node_fs = __webpack_require__(3024);
|
||||
var node_os = __webpack_require__(8161);
|
||||
var node_path = __webpack_require__(6760);
|
||||
|
||||
class LoginCredentialsFetcher {
|
||||
profileData;
|
||||
init;
|
||||
callerClientConfig;
|
||||
static REFRESH_THRESHOLD = 5 * 60 * 1000;
|
||||
constructor(profileData, init, callerClientConfig) {
|
||||
this.profileData = profileData;
|
||||
this.init = init;
|
||||
this.callerClientConfig = callerClientConfig;
|
||||
}
|
||||
async loadCredentials() {
|
||||
const token = await this.loadToken();
|
||||
if (!token) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Failed to load a token for session ${this.loginSession}, please re-authenticate using aws login`, { tryNextLink: false, logger: this.logger });
|
||||
}
|
||||
const accessToken = token.accessToken;
|
||||
const now = Date.now();
|
||||
const expiryTime = new Date(accessToken.expiresAt).getTime();
|
||||
const timeUntilExpiry = expiryTime - now;
|
||||
if (timeUntilExpiry <= LoginCredentialsFetcher.REFRESH_THRESHOLD) {
|
||||
return this.refresh(token);
|
||||
}
|
||||
return {
|
||||
accessKeyId: accessToken.accessKeyId,
|
||||
secretAccessKey: accessToken.secretAccessKey,
|
||||
sessionToken: accessToken.sessionToken,
|
||||
accountId: accessToken.accountId,
|
||||
expiration: new Date(accessToken.expiresAt),
|
||||
};
|
||||
}
|
||||
get logger() {
|
||||
return this.init?.logger;
|
||||
}
|
||||
get loginSession() {
|
||||
return this.profileData.login_session;
|
||||
}
|
||||
async refresh(token) {
|
||||
const { SigninClient, CreateOAuth2TokenCommand } = await __webpack_require__.e(/* import() */ 762).then(__webpack_require__.t.bind(__webpack_require__, 9762, 19));
|
||||
const { logger, userAgentAppId } = this.callerClientConfig ?? {};
|
||||
const isH2 = (requestHandler) => {
|
||||
return requestHandler?.metadata?.handlerProtocol === "h2";
|
||||
};
|
||||
const requestHandler = isH2(this.callerClientConfig?.requestHandler)
|
||||
? undefined
|
||||
: this.callerClientConfig?.requestHandler;
|
||||
const region = this.profileData.region ?? (await this.callerClientConfig?.region?.()) ?? process.env.AWS_REGION;
|
||||
const client = new SigninClient({
|
||||
credentials: {
|
||||
accessKeyId: "",
|
||||
secretAccessKey: "",
|
||||
},
|
||||
region,
|
||||
requestHandler,
|
||||
logger,
|
||||
userAgentAppId,
|
||||
...this.init?.clientConfig,
|
||||
});
|
||||
this.createDPoPInterceptor(client.middlewareStack);
|
||||
const commandInput = {
|
||||
tokenInput: {
|
||||
clientId: token.clientId,
|
||||
refreshToken: token.refreshToken,
|
||||
grantType: "refresh_token",
|
||||
},
|
||||
};
|
||||
try {
|
||||
const response = await client.send(new CreateOAuth2TokenCommand(commandInput));
|
||||
const { accessKeyId, secretAccessKey, sessionToken } = response.tokenOutput?.accessToken ?? {};
|
||||
const { refreshToken, expiresIn } = response.tokenOutput ?? {};
|
||||
if (!accessKeyId || !secretAccessKey || !sessionToken || !refreshToken) {
|
||||
throw new propertyProvider.CredentialsProviderError("Token refresh response missing required fields", {
|
||||
logger: this.logger,
|
||||
tryNextLink: false,
|
||||
});
|
||||
}
|
||||
const expiresInMs = (expiresIn ?? 900) * 1000;
|
||||
const expiration = new Date(Date.now() + expiresInMs);
|
||||
const updatedToken = {
|
||||
...token,
|
||||
accessToken: {
|
||||
...token.accessToken,
|
||||
accessKeyId: accessKeyId,
|
||||
secretAccessKey: secretAccessKey,
|
||||
sessionToken: sessionToken,
|
||||
expiresAt: expiration.toISOString(),
|
||||
},
|
||||
refreshToken: refreshToken,
|
||||
};
|
||||
await this.saveToken(updatedToken);
|
||||
const newAccessToken = updatedToken.accessToken;
|
||||
return {
|
||||
accessKeyId: newAccessToken.accessKeyId,
|
||||
secretAccessKey: newAccessToken.secretAccessKey,
|
||||
sessionToken: newAccessToken.sessionToken,
|
||||
accountId: newAccessToken.accountId,
|
||||
expiration,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
if (error.name === "AccessDeniedException") {
|
||||
const errorType = error.error;
|
||||
let message;
|
||||
switch (errorType) {
|
||||
case "TOKEN_EXPIRED":
|
||||
message = "Your session has expired. Please reauthenticate.";
|
||||
break;
|
||||
case "USER_CREDENTIALS_CHANGED":
|
||||
message =
|
||||
"Unable to refresh credentials because of a change in your password. Please reauthenticate with your new password.";
|
||||
break;
|
||||
case "INSUFFICIENT_PERMISSIONS":
|
||||
message =
|
||||
"Unable to refresh credentials due to insufficient permissions. You may be missing permission for the 'CreateOAuth2Token' action.";
|
||||
break;
|
||||
default:
|
||||
message = `Failed to refresh token: ${String(error)}. Please re-authenticate using \`aws login\``;
|
||||
}
|
||||
throw new propertyProvider.CredentialsProviderError(message, { logger: this.logger, tryNextLink: false });
|
||||
}
|
||||
throw new propertyProvider.CredentialsProviderError(`Failed to refresh token: ${String(error)}. Please re-authenticate using aws login`, { logger: this.logger });
|
||||
}
|
||||
}
|
||||
async loadToken() {
|
||||
const tokenFilePath = this.getTokenFilePath();
|
||||
try {
|
||||
let tokenData;
|
||||
try {
|
||||
tokenData = await sharedIniFileLoader.readFile(tokenFilePath, { ignoreCache: this.init?.ignoreCache });
|
||||
}
|
||||
catch {
|
||||
tokenData = await node_fs.promises.readFile(tokenFilePath, "utf8");
|
||||
}
|
||||
const token = JSON.parse(tokenData);
|
||||
const missingFields = ["accessToken", "clientId", "refreshToken", "dpopKey"].filter((k) => !token[k]);
|
||||
if (!token.accessToken?.accountId) {
|
||||
missingFields.push("accountId");
|
||||
}
|
||||
if (missingFields.length > 0) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Token validation failed, missing fields: ${missingFields.join(", ")}`, {
|
||||
logger: this.logger,
|
||||
tryNextLink: false,
|
||||
});
|
||||
}
|
||||
return token;
|
||||
}
|
||||
catch (error) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Failed to load token from ${tokenFilePath}: ${String(error)}`, {
|
||||
logger: this.logger,
|
||||
tryNextLink: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
async saveToken(token) {
|
||||
const tokenFilePath = this.getTokenFilePath();
|
||||
const directory = node_path.dirname(tokenFilePath);
|
||||
try {
|
||||
await node_fs.promises.mkdir(directory, { recursive: true });
|
||||
}
|
||||
catch (error) {
|
||||
}
|
||||
await node_fs.promises.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
|
||||
}
|
||||
getTokenFilePath() {
|
||||
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? node_path.join(node_os.homedir(), ".aws", "login", "cache");
|
||||
const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
|
||||
const loginSessionSha256 = node_crypto.createHash("sha256").update(loginSessionBytes).digest("hex");
|
||||
return node_path.join(directory, `${loginSessionSha256}.json`);
|
||||
}
|
||||
derToRawSignature(derSignature) {
|
||||
let offset = 2;
|
||||
if (derSignature[offset] !== 0x02) {
|
||||
throw new Error("Invalid DER signature");
|
||||
}
|
||||
offset++;
|
||||
const rLength = derSignature[offset++];
|
||||
let r = derSignature.subarray(offset, offset + rLength);
|
||||
offset += rLength;
|
||||
if (derSignature[offset] !== 0x02) {
|
||||
throw new Error("Invalid DER signature");
|
||||
}
|
||||
offset++;
|
||||
const sLength = derSignature[offset++];
|
||||
let s = derSignature.subarray(offset, offset + sLength);
|
||||
r = r[0] === 0x00 ? r.subarray(1) : r;
|
||||
s = s[0] === 0x00 ? s.subarray(1) : s;
|
||||
const rPadded = Buffer.concat([Buffer.alloc(32 - r.length), r]);
|
||||
const sPadded = Buffer.concat([Buffer.alloc(32 - s.length), s]);
|
||||
return Buffer.concat([rPadded, sPadded]);
|
||||
}
|
||||
createDPoPInterceptor(middlewareStack) {
|
||||
middlewareStack.add((next) => async (args) => {
|
||||
if (protocolHttp.HttpRequest.isInstance(args.request)) {
|
||||
const request = args.request;
|
||||
const actualEndpoint = `${request.protocol}//${request.hostname}${request.port ? `:${request.port}` : ""}${request.path}`;
|
||||
const dpop = await this.generateDpop(request.method, actualEndpoint);
|
||||
request.headers = {
|
||||
...request.headers,
|
||||
DPoP: dpop,
|
||||
};
|
||||
}
|
||||
return next(args);
|
||||
}, {
|
||||
step: "finalizeRequest",
|
||||
name: "dpopInterceptor",
|
||||
override: true,
|
||||
});
|
||||
}
|
||||
async generateDpop(method = "POST", endpoint) {
|
||||
const token = await this.loadToken();
|
||||
try {
|
||||
const privateKey = node_crypto.createPrivateKey({
|
||||
key: token.dpopKey,
|
||||
format: "pem",
|
||||
type: "sec1",
|
||||
});
|
||||
const publicKey = node_crypto.createPublicKey(privateKey);
|
||||
const publicDer = publicKey.export({ format: "der", type: "spki" });
|
||||
let pointStart = -1;
|
||||
for (let i = 0; i < publicDer.length; i++) {
|
||||
if (publicDer[i] === 0x04) {
|
||||
pointStart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const x = publicDer.slice(pointStart + 1, pointStart + 33);
|
||||
const y = publicDer.slice(pointStart + 33, pointStart + 65);
|
||||
const header = {
|
||||
alg: "ES256",
|
||||
typ: "dpop+jwt",
|
||||
jwk: {
|
||||
kty: "EC",
|
||||
crv: "P-256",
|
||||
x: x.toString("base64url"),
|
||||
y: y.toString("base64url"),
|
||||
},
|
||||
};
|
||||
const payload = {
|
||||
jti: crypto.randomUUID(),
|
||||
htm: method,
|
||||
htu: endpoint,
|
||||
iat: Math.floor(Date.now() / 1000),
|
||||
};
|
||||
const headerB64 = Buffer.from(JSON.stringify(header)).toString("base64url");
|
||||
const payloadB64 = Buffer.from(JSON.stringify(payload)).toString("base64url");
|
||||
const message = `${headerB64}.${payloadB64}`;
|
||||
const asn1Signature = node_crypto.sign("sha256", Buffer.from(message), privateKey);
|
||||
const rawSignature = this.derToRawSignature(asn1Signature);
|
||||
const signatureB64 = rawSignature.toString("base64url");
|
||||
return `${message}.${signatureB64}`;
|
||||
}
|
||||
catch (error) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Failed to generate Dpop proof: ${error instanceof Error ? error.message : String(error)}`, { logger: this.logger, tryNextLink: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fromLoginCredentials = (init) => async ({ callerClientConfig } = {}) => {
|
||||
init?.logger?.debug?.("@aws-sdk/credential-providers - fromLoginCredentials");
|
||||
const profiles = await sharedIniFileLoader.parseKnownFiles(init || {});
|
||||
const profileName = sharedIniFileLoader.getProfileName({
|
||||
profile: init?.profile ?? callerClientConfig?.profile,
|
||||
});
|
||||
const profile = profiles[profileName];
|
||||
if (!profile?.login_session) {
|
||||
throw new propertyProvider.CredentialsProviderError(`Profile ${profileName} does not contain login_session.`, {
|
||||
tryNextLink: true,
|
||||
logger: init?.logger,
|
||||
});
|
||||
}
|
||||
const fetcher = new LoginCredentialsFetcher(profile, init, callerClientConfig);
|
||||
const credentials = await fetcher.loadCredentials();
|
||||
return client.setCredentialFeature(credentials, "CREDENTIALS_LOGIN", "AD");
|
||||
};
|
||||
|
||||
exports.fromLoginCredentials = fromLoginCredentials;
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
};
|
||||
;
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,50 @@
|
||||
const core = require('@actions/core');
|
||||
const { SES } = require("@aws-sdk/client-ses");
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const region = core.getInput('region');
|
||||
const version = core.getInput('version');
|
||||
const format = core.getInput('format');
|
||||
const Template = core.getInput('template');
|
||||
const dataFilePath = core.getInput('dataFile');
|
||||
const CcAddresses = JSON.parse(core.getInput('ccAddresses'));
|
||||
const ToAddresses = JSON.parse(core.getInput('toAddresses'));
|
||||
const ReplyToAddresses = JSON.parse(core.getInput('replyToAddresses'));
|
||||
const workflowURL = core.getInput('workflowURL');
|
||||
const subject = core.getInput('subject');
|
||||
const bodyPath = core.getInput('bodyPath');
|
||||
|
||||
const data = dataFilePath ? fs.readFileSync(dataFilePath, { encoding: 'utf-8' }) : "";
|
||||
const body = bodyPath ? fs.readFileSync(bodyPath, { encoding: 'utf-8' }) : "";
|
||||
|
||||
const templated = {
|
||||
version,
|
||||
format,
|
||||
results: data,
|
||||
workflowURL,
|
||||
subject,
|
||||
body,
|
||||
};
|
||||
|
||||
// Create sendEmail params
|
||||
const params = {
|
||||
Destination: { /* required */
|
||||
CcAddresses,
|
||||
ToAddresses,
|
||||
},
|
||||
Source: 'github-actions-bot@corp.ld-corp.com', /* required */
|
||||
Template,
|
||||
TemplateData: JSON.stringify(templated),
|
||||
ReplyToAddresses,
|
||||
};
|
||||
|
||||
console.log(params)
|
||||
|
||||
// Create the promise and SES service object
|
||||
const sendPromise = new SES({region}).sendTemplatedEmail(params);
|
||||
|
||||
// Handle promise's fulfilled/rejected states
|
||||
sendPromise
|
||||
.then((data) => console.log("Successfully sent email:", data.MessageId))
|
||||
.catch((err) => console.error(err, err.stack));
|
||||
+1333
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "ses-email-action",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"keywords": [],
|
||||
"author": "dolthub",
|
||||
"license": "ISC",
|
||||
"scripts": {
|
||||
"build": "ncc build index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.3",
|
||||
"@aws-sdk/client-ses": "^3.982.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/ncc": "^0.38.4"
|
||||
},
|
||||
"overrides": {
|
||||
"fast-xml-parser": "^5.3.6"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
name: 'Set up dolt config'
|
||||
description: 'Sets the global dolt user.name and user.email used by CI workflows. Requires the dolt binary to already be on PATH (e.g. via the build-dolt action).'
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Configure dolt
|
||||
shell: bash
|
||||
run: |
|
||||
dolt config --global --add metrics.disabled true
|
||||
dolt config --global --add user.name 'Dolthub Actions'
|
||||
dolt config --global --add user.email 'actions@dolthub.com'
|
||||
@@ -0,0 +1,31 @@
|
||||
name: 'Set up Go toolchain'
|
||||
description: 'Set up Go and platform-specific dependencies (ICU4C) needed to build dolt. On macOS, sets CGO flags pointing at brew icu4c. On Windows, installs MSYS2 with icu/toolchain/pkg-config and exposes the install path via the msys2-location output. On Linux, just sets up Go.'
|
||||
|
||||
outputs:
|
||||
msys2-location:
|
||||
description: 'Path to the MSYS2 installation (Windows only).'
|
||||
value: ${{ steps.msys2.outputs.msys2-location }}
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Install ICU4C (MacOS)
|
||||
if: runner.os == 'macOS'
|
||||
shell: bash
|
||||
run: |
|
||||
dir=$(brew --cellar icu4c)
|
||||
dir="$dir"/$(ls "$dir")
|
||||
echo CGO_CPPFLAGS=-I$dir/include >> $GITHUB_ENV
|
||||
echo CGO_LDFLAGS=-L$dir/lib >> $GITHUB_ENV
|
||||
- name: Install ICU4C (Windows)
|
||||
id: msys2
|
||||
if: runner.os == 'Windows'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
path-type: inherit
|
||||
msystem: UCRT64
|
||||
pacboy: icu:p toolchain:p pkg-config:p
|
||||
@@ -0,0 +1,14 @@
|
||||
:coffee: *An Automated Dependency Version Bump PR* :crown:
|
||||
|
||||
### Initial Changes
|
||||
|
||||
The initial changes contained in this PR were produced by `go get`ing the dependency.
|
||||
|
||||
```
|
||||
$ cd ./go
|
||||
$ go get github.com/dolthub/<dependency>/go@<commit>
|
||||
```
|
||||
|
||||
### Before Merging
|
||||
|
||||
This PR must have passing CI and a review before merging.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: ./get-dolt-correctness-job-json.sh <jobname> <version>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jobname="$1"
|
||||
version="$2"
|
||||
|
||||
echo '
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"name": "'$jobname'",
|
||||
"namespace": "fuzzer"
|
||||
},
|
||||
"spec": {
|
||||
"backoffLimit": 2,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"labels": {
|
||||
"k8s-liquidata-inc-monitored-job": "created-by-static-config",
|
||||
"app": "fuzzer"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"serviceAccountName": "fuzzer",
|
||||
"containers": [
|
||||
{
|
||||
"name": "fuzzer",
|
||||
"image": "407903926827.dkr.ecr.us-west-2.amazonaws.com/liquidata/fuzzer:latest",
|
||||
"env": [
|
||||
{ "name": "REPO_ACCESS_TOKEN", "value": "'$REPO_ACCESS_TOKEN'"},
|
||||
{ "name": "ACTOR", "value": "'$ACTOR'"},
|
||||
{ "name": "DOLT_BIN", "value": "/usr/local/bin"}
|
||||
],
|
||||
"args": [
|
||||
"--dolt-version='$version'",
|
||||
"--bucket=dolt-fuzzer-runs",
|
||||
"--region=us-west-2",
|
||||
"--version-gate-job",
|
||||
"--fuzzer-args=basic, --cycles=5"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "OnFailure"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$KUBECONFIG" ]; then
|
||||
echo "Must set KUBECONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$TEMPLATE_SCRIPT" ]; then
|
||||
echo "Must set TEMPLATE_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Must set VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "using dolt version: $VERSION"
|
||||
|
||||
if [ -z "$ACTOR" ]; then
|
||||
echo "Must set ACTOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
nomsFormat="ldnbf"
|
||||
if [ "$NOMS_BIN_FORMAT" == "__DOLT__"]; then
|
||||
nomsFormat="doltnbf"
|
||||
fi
|
||||
|
||||
# use first 8 characters of TO_VERSION to differentiate
|
||||
# jobs
|
||||
short=${VERSION:0:8}
|
||||
lowered=$(echo "$ACTOR" | tr '[:upper:]' '[:lower:]')
|
||||
actorShort="$lowered-$nomsFormat-$short"
|
||||
|
||||
jobname="$actorShort"
|
||||
|
||||
source "$TEMPLATE_SCRIPT" "$jobname" "$VERSION" > job.json
|
||||
|
||||
out=$(KUBECONFIG="$KUBECONFIG" kubectl apply -f job.json || true)
|
||||
|
||||
if [ "$out" != "job.batch/$jobname created" ]; then
|
||||
echo "something went wrong creating job... this job likely already exists in the cluster"
|
||||
echo "$out"
|
||||
exit 1
|
||||
else
|
||||
echo "$out"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,109 @@
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import random
|
||||
|
||||
if len(sys.argv) != 7:
|
||||
print("usage: python3 data.py <output-dir> <table-num> <row-num> <add-num> <delete-num> <update-num>")
|
||||
sys.exit(1)
|
||||
|
||||
table_dir = sys.argv[1]
|
||||
tables = int(sys.argv[2])
|
||||
rows = int(sys.argv[3])
|
||||
|
||||
adds = int(sys.argv[4])
|
||||
deletes = int(sys.argv[5])
|
||||
updates = int(sys.argv[6])
|
||||
|
||||
if __name__=="__main__":
|
||||
if deletes + updates > rows:
|
||||
raise ValueError(f"deletes({deletes}) + updates({updates}) = {updates+deletes} > total rows({rows})")
|
||||
if not os.path.exists(table_dir):
|
||||
shutil.rmtree(table_dir, ignore_errors=True)
|
||||
os.makedirs(table_dir)
|
||||
|
||||
ys = [i for i in range(rows+adds+deletes+updates)]
|
||||
random.shuffle(ys)
|
||||
|
||||
with open(f"{table_dir}/create.sql", "+w") as f:
|
||||
for i in range(tables):
|
||||
if i == 0:
|
||||
f.write(f"create table table{i} (x int primary key, y int, z int, key y_idx(y));\n")
|
||||
else:
|
||||
f.write(f"create table table{i} (x int primary key, y int, z int, key y_idx(y), foreign key (y) references table{i-1}(y));\n")
|
||||
|
||||
|
||||
for j in range(tables):
|
||||
with open(f"{table_dir}/table{j}.csv", "+w") as f:
|
||||
f.write("x,y,z\n")
|
||||
for i in range(rows+deletes+updates):
|
||||
f.write(f"{i},{ys[i]},{i}\n")
|
||||
|
||||
with open(f"{table_dir}/branch.sql", "+w") as f:
|
||||
for i in range(tables):
|
||||
f.write(f"set foreign_key_checks = 0;\n")
|
||||
f.write(f"set unique_checks = 0;\n")
|
||||
if adds > 0:
|
||||
f.write(f"insert into table{i} values\n")
|
||||
for j,k in enumerate(ys[rows+deletes+updates:rows+deletes+updates+adds]):
|
||||
if j == 0:
|
||||
f.write(f" ")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"({rows+deletes+updates+j},{k},{rows+deletes+updates+j})")
|
||||
f.write(f";\n")
|
||||
|
||||
if deletes > 0:
|
||||
f.write(f"delete from table{i} where x in\n")
|
||||
for j, y in enumerate(ys[:deletes]):
|
||||
if j == 0:
|
||||
f.write(f" (")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"{y}")
|
||||
f.write(f");\n")
|
||||
|
||||
if updates > 0:
|
||||
f.write(f"update table{i} set y=y+1 where x in\n")
|
||||
for j, y in enumerate(ys[deletes:deletes+updates]):
|
||||
if j == 0:
|
||||
f.write(f" (")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"{y}")
|
||||
f.write(f");\n")
|
||||
|
||||
with open(f"{table_dir}/diverge_main.sql", "+w") as f:
|
||||
for i in range(tables):
|
||||
f.write(f"set foreign_key_checks = 0;\n")
|
||||
f.write(f"set unique_checks = 0;\n")
|
||||
if adds > 0:
|
||||
# y value is one higher, conflict
|
||||
f.write(f"insert into table{i} values\n")
|
||||
for j,k in enumerate(ys[rows+deletes+updates:rows+deletes+updates+adds]):
|
||||
if j == 0:
|
||||
f.write(f" ")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"({rows+deletes+updates+j},{k+1},{rows+deletes+updates+j})")
|
||||
f.write(f";\n")
|
||||
|
||||
if deletes > 0:
|
||||
f.write(f"delete from table{i} where y in\n")
|
||||
for j, y in enumerate(ys[:deletes]):
|
||||
if j == 0:
|
||||
f.write(f" (")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"{y}")
|
||||
f.write(f");\n")
|
||||
|
||||
if updates > 0:
|
||||
f.write(f"update table{i} set y=y+1 where y in\n")
|
||||
for j, y in enumerate(ys[deletes:deletes+updates]):
|
||||
if j == 0:
|
||||
f.write(f" (")
|
||||
else:
|
||||
f.write(f", ")
|
||||
f.write(f"{y}")
|
||||
f.write(f");\n")
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "usage: setup.sh <dolt-dir> <data-dir>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIR=$1
|
||||
DATA=$2
|
||||
|
||||
rm -rf $DIR
|
||||
mkdir $DIR
|
||||
cd $DIR
|
||||
|
||||
dolt init
|
||||
|
||||
dolt sql < $DATA/create.sql
|
||||
|
||||
i=0
|
||||
for t in $(ls $DATA/ | grep "table"); do
|
||||
echo $t
|
||||
dolt table import --disable-fk-checks -u "table${i}" "$DATA/$t"
|
||||
((i++))
|
||||
done
|
||||
|
||||
dolt commit -Am "add tables"
|
||||
|
||||
dolt sql < $DATA/diverge_main.sql
|
||||
|
||||
dolt commit -Am "add rows to conflict"
|
||||
|
||||
dolt checkout -b feature
|
||||
dolt reset --hard head~1
|
||||
|
||||
dolt sql < $DATA/branch.sql
|
||||
|
||||
dolt commit -Am "new branch"
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 10 ]; then
|
||||
echo "Usage: ./get-job-json.sh <jobname> <fromServer> <fromVersion> <toServer> <toVersion> <timePrefix> <actorPrefix> <format> <issueNumber> <initBigRepo> <nomsBinFormat> <sysbenchTestTime> <withTpcc>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jobName="$1"
|
||||
fromServer="$2"
|
||||
fromVersion="$3"
|
||||
toServer="$4"
|
||||
toVersion="$5"
|
||||
timePrefix="$6"
|
||||
actorPrefix="$7"
|
||||
format="$8"
|
||||
issueNumber="$9"
|
||||
initBigRepo="${10}"
|
||||
nomsBinFormat="${11}"
|
||||
sysbenchTestTime="${12}"
|
||||
withTpcc="${13}"
|
||||
tpccRegex="tpcc%"
|
||||
|
||||
if [ -n "$initBigRepo" ]; then
|
||||
initBigRepo="\"--init-big-repo=$initBigRepo\","
|
||||
fi
|
||||
|
||||
if [ -n "$nomsBinFormat" ]; then
|
||||
nomsBinFormat="\"--noms-bin-format=$nomsBinFormat\","
|
||||
fi
|
||||
|
||||
if [ -n "$sysbenchTestTime" ]; then
|
||||
sysbenchTestTime="\"--sysbench-test-time=$sysbenchTestTime\","
|
||||
fi
|
||||
|
||||
if [ -n "$withTpcc" ]; then
|
||||
withTpcc="\"--withTpcc=$withTpcc\","
|
||||
fi
|
||||
|
||||
readTests="('oltp_read_only','oltp_point_select','select_random_points','select_random_ranges','covering_index_scan','index_scan','table_scan','groupby_scan','index_join_scan','types_table_scan','index_join')"
|
||||
|
||||
medianLatencyChangeReadsQuery="with result(test_name, from_latency, to_latency) as (select f.test_name, avg(f.latency_percentile), avg(t.latency_percentile) from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $readTests group by f.test_name) select test_name as read_tests, from_latency, to_latency, round(100 * ((to_latency - from_latency) / from_latency), 2) as percent_change from result;"
|
||||
|
||||
writeTests="('oltp_read_write','oltp_update_index','oltp_update_non_index','oltp_insert','oltp_write_only','oltp_delete_insert','types_delete_insert')"
|
||||
|
||||
medianLatencyChangeWritesQuery="with result(test_name, from_latency, to_latency) as (select f.test_name, avg(f.latency_percentile), avg(t.latency_percentile) from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $writeTests group by f.test_name) select test_name as write_tests, from_latency, to_latency, round(100 * ((to_latency - from_latency) / from_latency), 2) as percent_change from result;"
|
||||
|
||||
tpccLatencyQuery="with result(test_name, from_latency, to_latency) as (select f.test_name, avg(f.latency_percentile), avg(t.latency_percentile) from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name LIKE '$tpccRegex' group by f.test_name) select test_name, from_latency as from_latency_p95, to_latency as to_latency_p95, round(100 * ((to_latency - from_latency) / from_latency), 2) as percent_change from result;"
|
||||
|
||||
tpccTpsQuery="with result(test_name, from_server_name, from_server_version, from_tps, to_server_name, to_server_version, to_tps) as (select f.test_name, f.server_name, f.server_version, avg(f.sql_transactions_per_second), t.server_name, t.server_version, avg(t.sql_transactions_per_second) from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name LIKE 'tpcc%' group by f.test_name) select test_name, from_server_name, from_server_version, from_tps, to_server_name, to_server_version, to_tps, round(100 * ((to_tps - from_tps) / from_tps), 2) as percent_change from result;"
|
||||
|
||||
perfRegressionQuery="with result(from_lat, to_lat) as (select avg(f.latency_percentile), avg(t.latency_percentile) from from_results as f join to_results as t on f.test_name = t.test_name group by t.test_name) select sum((to_lat - from_lat) / from_lat > 0.05) from result;"
|
||||
|
||||
echo '
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"name": "'$jobName'",
|
||||
"namespace": "performance-benchmarking"
|
||||
},
|
||||
"spec": {
|
||||
"backoffLimit": 1,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"alert_recipients": "'$ACTOR_EMAIL'"
|
||||
},
|
||||
"labels": {
|
||||
"k8s-liquidata-inc-monitored-job": "created-by-static-config",
|
||||
"app": "performance-benchmarking"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"serviceAccountName": "performance-benchmarking",
|
||||
"containers": [
|
||||
{
|
||||
"name": "performance-benchmarking",
|
||||
"image": "407903926827.dkr.ecr.us-west-2.amazonaws.com/liquidata/performance-benchmarking:latest",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "7000m"
|
||||
}
|
||||
},
|
||||
"env": [
|
||||
{ "name": "GOMAXPROCS", "value": "7" },
|
||||
{ "name": "GOEXPERIMENT", "value": "greenteagc" },
|
||||
{ "name": "ACTOR", "value": "'$ACTOR'" },
|
||||
{ "name": "ACTOR_EMAIL", "value": "'$ACTOR_EMAIL'" },
|
||||
{ "name": "REPO_ACCESS_TOKEN", "value": "'$REPO_ACCESS_TOKEN'" }
|
||||
],
|
||||
"imagePullPolicy": "Always",
|
||||
"args": [
|
||||
"--schema=/app/schema.sql",
|
||||
"--useDoltHubLuaScriptsRepo",
|
||||
"--output='$format'",
|
||||
"--from-server='$fromServer'",
|
||||
"--from-version='$fromVersion'",
|
||||
"--to-server='$toServer'",
|
||||
"--to-version='$toVersion'",
|
||||
"--bucket=performance-benchmarking-github-actions-results",
|
||||
"--region=us-west-2",
|
||||
"--issue-number='$issueNumber'",
|
||||
"--results-dir='$timePrefix'",
|
||||
"--results-prefix='$actorPrefix'",
|
||||
"--perf-regression-query='"$perfRegressionQuery"'",
|
||||
'"$sysbenchTestTime"'
|
||||
'"$withTpcc"'
|
||||
'"$initBigRepo"'
|
||||
'"$nomsBinFormat"'
|
||||
"--sysbenchQueries='"$medianLatencyChangeReadsQuery"'",
|
||||
"--sysbenchQueries='"$medianLatencyChangeWritesQuery"'",
|
||||
"--tpccQueries='"$tpccLatencyQuery"'",
|
||||
"--tpccQueries='"$tpccTpsQuery"'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never",
|
||||
"nodeSelector": {
|
||||
"performance-benchmarking-worker": "true"
|
||||
},
|
||||
"tolerations": [
|
||||
{
|
||||
"effect": "NoSchedule",
|
||||
"key": "dedicated",
|
||||
"operator": "Equal",
|
||||
"value": "performance-benchmarking-worker"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
@@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 6 ]; then
|
||||
echo "Usage: ./get-job-json.sh <jobname> <version> <futureVersion> <timePrefix> <actorPrefix> <format> <initBigRepo> <nomsBinFormat>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jobName="$1"
|
||||
version="$2"
|
||||
futureVersion="$3"
|
||||
timePrefix="$4"
|
||||
actorPrefix="$5"
|
||||
format="$6"
|
||||
initBigRepo="$7"
|
||||
nomsBinFormat="$8"
|
||||
|
||||
if [ -n "$initBigRepo" ]; then
|
||||
initBigRepo="\"--init-big-repo=$initBigRepo\","
|
||||
fi
|
||||
|
||||
if [ -n "$nomsBinFormat" ]; then
|
||||
nomsBinFormat="\"--noms-bin-format=$nomsBinFormat\","
|
||||
fi
|
||||
|
||||
echo '
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"name": "'$jobName'",
|
||||
"namespace": "performance-benchmarking"
|
||||
},
|
||||
"spec": {
|
||||
"backoffLimit": 1,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"alert_recipients": "'$ACTOR_EMAIL'"
|
||||
},
|
||||
"labels": {
|
||||
"k8s-liquidata-inc-monitored-job": "created-by-static-config",
|
||||
"app": "performance-benchmarking"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"serviceAccountName": "performance-benchmarking",
|
||||
"containers": [
|
||||
{
|
||||
"name": "performance-benchmarking",
|
||||
"image": "407903926827.dkr.ecr.us-west-2.amazonaws.com/liquidata/performance-benchmarking:latest",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "7000m"
|
||||
}
|
||||
},
|
||||
"env": [
|
||||
{ "name": "GOMAXPROCS", "value": "7" },
|
||||
{ "name": "GOEXPERIMENT", "value": "greenteagc" },
|
||||
{ "name": "ACTOR", "value": "'$ACTOR'" },
|
||||
{ "name": "ACTOR_EMAIL", "value": "'$ACTOR_EMAIL'" },
|
||||
{ "name": "REPO_ACCESS_TOKEN", "value": "'$REPO_ACCESS_TOKEN'" },
|
||||
{ "name": "BRANCH", "value": "'$BRANCH'" }
|
||||
],
|
||||
"imagePullPolicy": "Always",
|
||||
"args": [
|
||||
"--schema=/app/schema.sql",
|
||||
"--useDoltHubLuaScriptsRepo",
|
||||
"--profile-version='"$version"'",
|
||||
"--future-version='"$futureVersion"'",
|
||||
"--bucket=performance-benchmarking-github-actions-results",
|
||||
"--region=us-west-2",
|
||||
"--results-dir='$timePrefix'",
|
||||
"--results-prefix='$actorPrefix'",
|
||||
'"$initBigRepo"'
|
||||
'"$nomsBinFormat"'
|
||||
"--output='$format'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never",
|
||||
"nodeSelector": {
|
||||
"performance-benchmarking-worker": "true"
|
||||
},
|
||||
"tolerations": [
|
||||
{
|
||||
"effect": "NoSchedule",
|
||||
"key": "dedicated",
|
||||
"operator": "Equal",
|
||||
"value": "performance-benchmarking-worker"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 12 ]; then
|
||||
echo "Usage: ./get-job-json.sh <jobname> <fromServer> <fromVersion> <toServer> <toVersion> <timeprefix> <actorprefix> <format> <issueNumber> <initBigRepo> <nomsBinFormat> <sysbenchTestTime> <withTpcc>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jobname="$1"
|
||||
fromServer="$2"
|
||||
fromVersion="$3"
|
||||
toServer="$4"
|
||||
toVersion="$5"
|
||||
timeprefix="$6"
|
||||
actorprefix="$7"
|
||||
format="$8"
|
||||
issueNumber="$9"
|
||||
initBigRepo="${10}"
|
||||
nomsBinFormat="${11}"
|
||||
sysbenchTestTime="${12}"
|
||||
withTpcc="${13}"
|
||||
precision="2"
|
||||
tpccRegex="tpcc%"
|
||||
toProfileKey=""
|
||||
|
||||
if [ -n "$initBigRepo" ]; then
|
||||
initBigRepo="\"--init-big-repo=$initBigRepo\","
|
||||
fi
|
||||
|
||||
if [ -n "$nomsBinFormat" ]; then
|
||||
nomsBinFormat="\"--noms-bin-format=$nomsBinFormat\","
|
||||
fi
|
||||
|
||||
if [ -n "$sysbenchTestTime" ]; then
|
||||
sysbenchTestTime="\"--sysbench-test-time=$sysbenchTestTime\","
|
||||
fi
|
||||
|
||||
if [ -n "$withTpcc" ]; then
|
||||
withTpcc="\"--withTpcc=$withTpcc\","
|
||||
fi
|
||||
|
||||
if [ -n "$TO_PROFILE_KEY" ]; then
|
||||
toProfileKey="\"--to-profile-key=$TO_PROFILE_KEY\","
|
||||
fi
|
||||
|
||||
readTests="('oltp_read_only', 'oltp_point_select', 'select_random_points', 'select_random_ranges', 'covering_index_scan', 'index_scan', 'table_scan', 'groupby_scan', 'index_join_scan', 'types_table_scan', 'index_join')"
|
||||
medianLatencyMultiplierReadsQuery="select f.test_name as read_tests, f.server_name, f.server_version, avg(f.latency_percentile) as from_latency_median, t.server_name, t.server_version, avg(t.latency_percentile) as to_latency_median, ROUND(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision) as multiplier from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $readTests group by f.test_name;"
|
||||
meanMultiplierReadsQuery="select round(avg(multipliers), $precision) as reads_mean_multiplier from (select (round(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision)) as multipliers from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $readTests group by f.test_name)"
|
||||
|
||||
writeTests="('oltp_read_write', 'oltp_update_index', 'oltp_update_non_index', 'oltp_insert', 'oltp_write_only', 'oltp_delete_insert', 'types_delete_insert')"
|
||||
medianLatencyMultiplierWritesQuery="select f.test_name as write_tests, f.server_name, f.server_version, avg(f.latency_percentile) as from_latency_median, t.server_name, t.server_version, avg(t.latency_percentile) as to_latency_median, ROUND(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision) as multiplier from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $writeTests group by f.test_name;"
|
||||
meanMultiplierWritesQuery="select round(avg(multipliers), $precision) as writes_mean_multiplier from (select (round(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision)) as multipliers from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name in $writeTests group by f.test_name)"
|
||||
|
||||
meanMultiplierOverallQuery="select round(avg(multipliers), $precision) as overall_mean_multiplier from (select (round(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision)) as multipliers from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name != 'bulk_insert' group by f.test_name)"
|
||||
|
||||
tpccLatencyQuery="select f.test_name as tpcc_latency, f.server_name, f.server_version, avg(f.latency_percentile) as from_latency_p95, t.server_name, t.server_version, avg(t.latency_percentile) as to_latency_p95, ROUND(avg(t.latency_percentile) / (avg(f.latency_percentile) + .000001), $precision) as multiplier from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name LIKE '$tpccRegex' group by f.test_name;"
|
||||
tpccTpsQuery="select f.test_name as tpcc_tps, f.server_name, f.server_version, avg(f.sql_transactions_per_second) as from_tps, t.test_name as test_name, t.server_name, t.server_version, avg(t.sql_transactions_per_second) as to_tps, ROUND(avg(f.sql_transactions_per_second) / (avg(t.sql_transactions_per_second) + .000001), $precision) as multiplier from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name LIKE 'tpcc%' group by f.test_name;"
|
||||
tpccTpsMultiplierQuery="select ROUND(avg(f.sql_transactions_per_second) / (avg(t.sql_transactions_per_second) + .000001), $precision) as tpcc_tps_multiplier from from_results as f join to_results as t on f.test_name = t.test_name where f.test_name like 'tpcc%' group by f.test_name"
|
||||
|
||||
echo '
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"name": "'$jobname'",
|
||||
"namespace": "performance-benchmarking"
|
||||
},
|
||||
"spec": {
|
||||
"backoffLimit": 3,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"alert_recipients": "'$ACTOR_EMAIL'"
|
||||
},
|
||||
"labels": {
|
||||
"k8s-liquidata-inc-monitored-job": "created-by-static-config",
|
||||
"app": "performance-benchmarking"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"serviceAccountName": "performance-benchmarking",
|
||||
"containers": [
|
||||
{
|
||||
"name": "performance-benchmarking",
|
||||
"image": "407903926827.dkr.ecr.us-west-2.amazonaws.com/liquidata/performance-benchmarking:latest",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "7000m"
|
||||
}
|
||||
},
|
||||
"env": [
|
||||
{ "name": "GOMAXPROCS", "value": "7" },
|
||||
{ "name": "GOEXPERIMENT", "value": "greenteagc" },
|
||||
{ "name": "ACTOR", "value": "'$ACTOR'" },
|
||||
{ "name": "ACTOR_EMAIL", "value": "'$ACTOR_EMAIL'" },
|
||||
{ "name": "REPO_ACCESS_TOKEN", "value": "'$REPO_ACCESS_TOKEN'" }
|
||||
],
|
||||
"imagePullPolicy": "Always",
|
||||
"args": [
|
||||
"--schema=/app/schema.sql",
|
||||
"--useDoltHubLuaScriptsRepo",
|
||||
"--output='$format'",
|
||||
"--mysql-exec=/usr/sbin/mysqld",
|
||||
"--mysql-socket=/home/tester/.mysql/mysqld.sock",
|
||||
"--mysql-protocol=unix",
|
||||
"--from-server='$fromServer'",
|
||||
"--from-version='$fromVersion'",
|
||||
"--to-server='$toServer'",
|
||||
"--to-version='$toVersion'",
|
||||
'"$toProfileKey"'
|
||||
"--bucket=performance-benchmarking-github-actions-results",
|
||||
"--region=us-west-2",
|
||||
"--results-dir='$timeprefix'",
|
||||
"--results-prefix='$actorprefix'",
|
||||
'"$sysbenchTestTime"'
|
||||
'"$withTpcc"'
|
||||
'"$initBigRepo"'
|
||||
'"$nomsBinFormat"'
|
||||
"--sysbenchQueries='"$medianLatencyMultiplierReadsQuery"'",
|
||||
"--sysbenchQueries='"$meanMultiplierReadsQuery"'",
|
||||
"--sysbenchQueries='"$medianLatencyMultiplierWritesQuery"'",
|
||||
"--sysbenchQueries='"$meanMultiplierWritesQuery"'",
|
||||
"--sysbenchQueries='"$meanMultiplierOverallQuery"'",
|
||||
"--tpccQueries='"$tpccLatencyQuery"'",
|
||||
"--tpccQueries='"$tpccTpsQuery"'",
|
||||
"--tpccQueries='"$tpccTpsMultiplierQuery"'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never",
|
||||
"nodeSelector": {
|
||||
"performance-benchmarking-worker": "true"
|
||||
},
|
||||
"tolerations": [
|
||||
{
|
||||
"effect": "NoSchedule",
|
||||
"key": "dedicated",
|
||||
"operator": "Equal",
|
||||
"value": "performance-benchmarking-worker"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$KUBECONFIG" ]; then
|
||||
echo "Must set KUBECONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$TEMPLATE_SCRIPT" ]; then
|
||||
echo "Must set TEMPLATE_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$NOMS_BIN_FORMAT" ]; then
|
||||
echo "Must set NOMS_BIN_FORMAT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$PROFILE" ]; then
|
||||
if [ -z "$FROM_VERSION" ]; then
|
||||
echo "Must set FROM_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$FUTURE_VERSION" ]; then
|
||||
echo "Setting FUTURE_VERSION to $FROM_VERSION"
|
||||
export FUTURE_VERSION="$FROM_VERSION"
|
||||
fi
|
||||
|
||||
echo "Setting profile version to $FROM_VERSION"
|
||||
else
|
||||
if [ -z "$FROM_SERVER" ] || [ -z "$FROM_VERSION" ] || [ -z "$TO_SERVER" ] || [ -z "$TO_VERSION" ]; then
|
||||
echo "Must set FROM_SERVER FROM_VERSION TO_SERVER and TO_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Setting from $FROM_SERVER: $FROM_VERSION"
|
||||
echo "Setting to $TO_SERVER: $TO_VERSION"
|
||||
fi
|
||||
|
||||
if [ -z "$ACTOR" ]; then
|
||||
echo "Must set ACTOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$MODE" ]; then
|
||||
echo "Must set MODE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$NOMS_BIN_FORMAT" = "__DOLT__" ]; then
|
||||
INIT_BIG_REPO="false"
|
||||
fi
|
||||
|
||||
# use first 8 characters of FROM_VERSION | TO_VERSION to differentiate
|
||||
# jobs
|
||||
short=${TO_VERSION:0:8}
|
||||
if [ -n "$PROFILE" ]; then
|
||||
short=${FROM_VERSION:0:8}
|
||||
fi
|
||||
|
||||
lowered=$(echo "$ACTOR" | tr '[:upper:]' '[:lower:]')
|
||||
actorShort="$lowered-$short"
|
||||
|
||||
# random sleep
|
||||
sleep 0.$[ ( $RANDOM % 10 ) + 1 ]s
|
||||
|
||||
timesuffix=`date +%s%N`
|
||||
|
||||
jobname="$actorShort"
|
||||
if [ -n "$WITH_TPCC" ]; then
|
||||
jobname="$jobname-tpcc"
|
||||
elif [ -n "$PROFILE" ]; then
|
||||
jobname="$jobname-profile"
|
||||
fi
|
||||
|
||||
jobname="$jobname-$timesuffix"
|
||||
|
||||
timeprefix=$(date +%Y/%m/%d)
|
||||
|
||||
actorprefix="$MODE/$lowered/$jobname/$NOMS_BIN_FORMAT"
|
||||
|
||||
format="markdown"
|
||||
if [[ "$MODE" = "release" || "$MODE" = "nightly" ]]; then
|
||||
format="html"
|
||||
fi
|
||||
|
||||
export TO_PROFILE_KEY
|
||||
|
||||
# set value to ISSUE_NUMBER environment variable
|
||||
# or default to -1
|
||||
issuenumber=${ISSUE_NUMBER:-"-1"}
|
||||
|
||||
if [ -n "$PROFILE" ]; then
|
||||
source \
|
||||
"$TEMPLATE_SCRIPT" \
|
||||
"$jobname" \
|
||||
"$FROM_VERSION" \
|
||||
"$FUTURE_VERSION" \
|
||||
"$timeprefix" \
|
||||
"$actorprefix" \
|
||||
"$format" \
|
||||
"$INIT_BIG_REPO" \
|
||||
"$NOMS_BIN_FORMAT" > job.json
|
||||
else
|
||||
source \
|
||||
"$TEMPLATE_SCRIPT" \
|
||||
"$jobname" \
|
||||
"$FROM_SERVER" \
|
||||
"$FROM_VERSION" \
|
||||
"$TO_SERVER" \
|
||||
"$TO_VERSION" \
|
||||
"$timeprefix" \
|
||||
"$actorprefix" \
|
||||
"$format" \
|
||||
"$issuenumber" \
|
||||
"$INIT_BIG_REPO" \
|
||||
"$NOMS_BIN_FORMAT" \
|
||||
"$SYSBENCH_TEST_TIME" \
|
||||
"$WITH_TPCC" > job.json
|
||||
fi
|
||||
|
||||
out=$(KUBECONFIG="$KUBECONFIG" kubectl apply -f job.json || true)
|
||||
|
||||
if [ "$out" != "job.batch/$jobname created" ]; then
|
||||
echo "something went wrong creating job... this job likely already exists in the cluster"
|
||||
echo "$out"
|
||||
exit 1
|
||||
else
|
||||
echo "$out"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: ./validate-commentor.sh COMMENTOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
validcommentors="coffeegoddd bheni Hydrocharged reltuk tbantle22 timsehn zachmu nicktobey fulghum macneale4 jycor angelamayxie elianddb"
|
||||
|
||||
contains() {
|
||||
[[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && echo "valid=true" >> $GITHUB_OUTPUT || exit 0
|
||||
}
|
||||
|
||||
contains "$validcommentors" "$1"
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# Inputs via environment variables
|
||||
RAW_DEP=${RAW_DEP:-}
|
||||
RAW_SHA=${RAW_SHA:-}
|
||||
RAW_USER=${RAW_USER:-}
|
||||
RAW_MAIL=${RAW_MAIL:-}
|
||||
|
||||
# --- Validate dependency via allow-list and map to module path + label
|
||||
case "${RAW_DEP:-}" in
|
||||
go-mysql-server)
|
||||
MODULE='github.com/dolthub/go-mysql-server'
|
||||
LABEL='gms-bump'
|
||||
;;
|
||||
eventsapi_schema)
|
||||
MODULE='github.com/dolthub/eventsapi_schema'
|
||||
LABEL='eventsapi_schema-bump'
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported dependency '${RAW_DEP:-}'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# --- Validate head SHA/tag (conservative)
|
||||
# allow only hex SHAs or safe tag-ish: letters, digits, dot, dash, underscore, plus
|
||||
if [ -z "${RAW_SHA:-}" ] || ! printf '%s' "$RAW_SHA" | grep -qE '^[A-Za-z0-9._+-]+$'; then
|
||||
echo "Invalid head_commit_sha" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Keep a short 8-char form if it's a hex SHA; otherwise derive short safe token
|
||||
if printf '%s' "$RAW_SHA" | grep -qiE '^[0-9a-f]{40}$'; then
|
||||
SHORT_SHA="${RAW_SHA:0:8}"
|
||||
else
|
||||
SHORT_SHA="$(printf '%s' "$RAW_SHA" | tr -cd 'A-Za-z0-9._+-' | cut -c1-12)"
|
||||
fi
|
||||
|
||||
# --- Validate assignee username (GitHub-compatible subset)
|
||||
if [ -z "${RAW_USER:-}" ] || ! printf '%s' "$RAW_USER" | grep -qE '^[A-Za-z0-9-]{1,39}$'; then
|
||||
echo "Invalid assignee username" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Validate email; if invalid, fall back to GitHub noreply
|
||||
if [ -n "${RAW_MAIL:-}" ] && printf '%s' "$RAW_MAIL" | grep -qE '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'; then
|
||||
SAFE_EMAIL="$RAW_MAIL"
|
||||
else
|
||||
SAFE_EMAIL="${RAW_USER}+noreply@users.noreply.github.com"
|
||||
fi
|
||||
|
||||
# --- Build a safe branch name: <assignee>-<short>
|
||||
BRANCH_NAME="$(printf '%s-%s' "$RAW_USER" "$SHORT_SHA" | tr -cd 'A-Za-z0-9._-')"
|
||||
|
||||
# Expose sanitized values as step outputs
|
||||
{
|
||||
echo "label=$LABEL"
|
||||
echo "safe_module=$MODULE"
|
||||
echo "safe_head=$RAW_SHA"
|
||||
echo "safe_assignee=$RAW_USER"
|
||||
echo "safe_email=$SAFE_EMAIL"
|
||||
echo "safe_branch=$BRANCH_NAME"
|
||||
echo "safe_short=$SHORT_SHA"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
@@ -0,0 +1 @@
|
||||
100
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$#" -lt 5 ]; then
|
||||
echo "Usage: ./get-dolt-correctness-job-json.sh <jobname> <version> <timeprefix> <actorprefix> <format> <nomsBinFormat> <issueNumber> <regressComp> <branchRef>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
jobname="$1"
|
||||
version="$2"
|
||||
timeprefix="$3"
|
||||
actorprefix="$4"
|
||||
format="$5"
|
||||
nomsBinFormat="$6"
|
||||
issueNumber="$7"
|
||||
regressComp="$8"
|
||||
branchRef="$9"
|
||||
|
||||
precision="6"
|
||||
|
||||
if [ -n "$nomsBinFormat" ]; then
|
||||
nomsBinFormat="\"--noms-bin-format=$nomsBinFormat\","
|
||||
fi
|
||||
|
||||
if [ -n "$issueNumber" ]; then
|
||||
issueNumber="\"--issue-number=$issueNumber\","
|
||||
fi
|
||||
|
||||
regressPrec=""
|
||||
if [ -n "$regressComp" ]; then
|
||||
regressComp="\"--regress-compare=$regressComp\","
|
||||
regressPrec="\"--regress-precision=$precision\","
|
||||
branchRef="\"--branch=$branchRef\","
|
||||
fi
|
||||
|
||||
resultCountQuery="select version, result, count(*) as total from results where result != 'skipped' group by result;"
|
||||
testCountQuery="select version, count(*) as total_tests from results where result != 'skipped';"
|
||||
correctnessQuery="select ROUND(100.0 * (cast(ok_results.total as decimal) / (cast(all_results.total as decimal) + .000001)), $precision) as correctness_percentage from (select count(*) as total from results where result = 'ok') as ok_results join (select count(*) as total from results where result != 'skipped') as all_results"
|
||||
|
||||
echo '
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"metadata": {
|
||||
"name": "'$jobname'",
|
||||
"namespace": "sql-correctness"
|
||||
},
|
||||
"spec": {
|
||||
"backoffLimit": 3,
|
||||
"template": {
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"alert_recipients": "'$ACTOR_EMAIL'"
|
||||
},
|
||||
"labels": {
|
||||
"k8s-liquidata-inc-monitored-job": "created-by-static-config",
|
||||
"app": "sql-correctness"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"serviceAccountName": "sql-correctness",
|
||||
"containers": [
|
||||
{
|
||||
"name": "sql-correctness",
|
||||
"image": "407903926827.dkr.ecr.us-west-2.amazonaws.com/liquidata/sql-correctness:latest",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "7000m"
|
||||
}
|
||||
},
|
||||
"env": [
|
||||
{ "name": "REPO_ACCESS_TOKEN", "value": "'$REPO_ACCESS_TOKEN'"},
|
||||
{ "name": "ACTOR", "value": "'$ACTOR'"},
|
||||
{ "name": "ACTOR_EMAIL", "value": "'$ACTOR_EMAIL'"}
|
||||
],
|
||||
"args": [
|
||||
"--schema=/app/correctness.sql",
|
||||
"--concurrent",
|
||||
"--output='$format'",
|
||||
"--version='$version'",
|
||||
"--timeout=600",
|
||||
'"$nomsBinFormat"'
|
||||
'"$issueNumber"'
|
||||
'"$regressComp"'
|
||||
'"$regressPrec"'
|
||||
'"$branchRef"'
|
||||
"--bucket=sql-correctness-github-actions-results",
|
||||
"--region=us-west-2",
|
||||
"--results-dir='$timeprefix'",
|
||||
"--results-prefix='$actorprefix'",
|
||||
"'"$resultCountQuery"'",
|
||||
"'"$testCountQuery"'",
|
||||
"'"$correctnessQuery"'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never",
|
||||
"nodeSelector": {
|
||||
"sql-correctness-worker": "true"
|
||||
},
|
||||
"tolerations": [
|
||||
{
|
||||
"effect": "NoSchedule",
|
||||
"key": "dedicated",
|
||||
"operator": "Equal",
|
||||
"value": "sql-correctness-worker"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$KUBECONFIG" ]; then
|
||||
echo "Must set KUBECONFIG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$TEMPLATE_SCRIPT" ]; then
|
||||
echo "Must set TEMPLATE_SCRIPT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$NOMS_BIN_FORMAT" ]; then
|
||||
echo "Must set NOMS_BIN_FORMAT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Must set VERSION for correctness run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$ACTOR" ]; then
|
||||
echo "Must set ACTOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$MODE" ]; then
|
||||
echo "Must set MODE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
if [ -z "$REGRESS_COMP" ]; then
|
||||
echo "Must set REGRESS_COMP for PR correctness comparisons"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$PR_BRANCH_REF" ]; then
|
||||
echo "Must set PR_BRANCH_REF for PR correctness comparisons"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# use first 8 characters of VERSION to differentiate
|
||||
# jobs
|
||||
short=${VERSION:0:8}
|
||||
lowered=$(echo "$ACTOR" | tr '[:upper:]' '[:lower:]')
|
||||
actorShort="$lowered-$short"
|
||||
|
||||
# random sleep
|
||||
sleep 0.$[ ( $RANDOM % 10 ) + 1 ]s
|
||||
|
||||
timesuffix=`date +%s%N`
|
||||
|
||||
jobname=""
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
jobname="$lowered-$PR_NUMBER"
|
||||
else
|
||||
jobname="$actorShort-$timesuffix"
|
||||
fi
|
||||
|
||||
timeprefix=$(date +%Y/%m/%d)
|
||||
|
||||
actorprefix="$MODE/$lowered/$jobname/$NOMS_BIN_FORMAT"
|
||||
|
||||
format="markdown"
|
||||
if [[ "$MODE" = "release" || "$MODE" = "nightly" ]]; then
|
||||
format="html"
|
||||
fi
|
||||
|
||||
# set value to PR_NUMBER environment variable
|
||||
# or default to -1
|
||||
issuenumber=${PR_NUMBER:-"-1"}
|
||||
|
||||
source \
|
||||
"$TEMPLATE_SCRIPT" \
|
||||
"$jobname" \
|
||||
"$VERSION" \
|
||||
"$timeprefix" \
|
||||
"$actorprefix" \
|
||||
"$format" \
|
||||
"$NOMS_BIN_FORMAT" \
|
||||
"$issuenumber" \
|
||||
"$REGRESS_COMP" \
|
||||
"$PR_BRANCH_REF" > job.json
|
||||
|
||||
# delete existing job with same name if this is a pr job
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
out=$(KUBECONFIG="$KUBECONFIG" kubectl delete job/"$jobname" -n sql-correctness || true)
|
||||
echo "Delete pr job if exists: $out"
|
||||
sleep 45
|
||||
fi
|
||||
|
||||
out=$(KUBECONFIG="$KUBECONFIG" kubectl apply -f job.json || true)
|
||||
|
||||
if [ "$out" != "job.batch/$jobname created" ]; then
|
||||
echo "something went wrong creating job... this job likely already exists in the cluster"
|
||||
echo "$out"
|
||||
exit 1
|
||||
else
|
||||
echo "$out"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,28 @@
|
||||
# Dolt's GitHub Actions
|
||||
|
||||
This doc will provide context for the types of Workflows we use in this repository. This doc is not a comprehensive GitHub Actions tutorial. To familiarize yourself with GitHub Actions concepts and the terminology, please see the [documentation](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions).
|
||||
|
||||
Dolt uses GitHub Actions Workflows in four primary ways:
|
||||
|
||||
* To run continuous integration tests on pull requests and pushes to `main`
|
||||
* To release and publish new Dolt assets
|
||||
* To deploy various benchmarking jobs to contexts _other_ than GitHub Actions (like in a Kubernetes cluster, for example).
|
||||
* To handle misc. [repository_dispatch](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#repository_dispatch) events triggered by external clients.
|
||||
|
||||
## Continuous Integration Workflows
|
||||
|
||||
Workflows prefixed with `ci-` are run on pull requests to `main`, though some run on pushes to `main` (after a pull request is merged). These workflows are synchronous and don't trigger any other workflows to run.
|
||||
|
||||
## Dolt Release Workflows
|
||||
|
||||
Workflows prefixed with `cd-` are used for releasing Dolt. Some of these workflows are asynchronous, meaning that they only perform part of a task before triggering the next part of a task to run in a _different_ workflow, sometimes in other GitHub repositories, using `repository_dispatch` events.
|
||||
|
||||
## Benchmarking Workflows
|
||||
|
||||
Benchmarking workflows are used as an interface for deploying benchmarking jobs to one of our Kubernetes Clusters. Workflows that deploy Kubernetes Jobs are prefixed with `k8s-` and can only be triggered with `repository_dispatch` events. Notice that benchmarking workflows, like `workflows/performance-benchmarks-email-report.yaml` for example, trigger these events using the `peter-evans/repository-dispatch@v2.0.0` Action.
|
||||
|
||||
These Kubernetes Jobs do not run on GitHub Actions Hosted Runners, so the workflow logs do not contain any information about the deployed Kubernetes Job or any errors it might have encountered. The workflow logs can only tell you if a Job was created successfully or not. To investigate an error or issue with a Job in our Kubernetes Cluster, see the debugging guide [here](https://github.com/dolthub/ld/blob/main/k8s/README.md#debug-performance-benchmarks-and-sql-correctness-jobs).
|
||||
|
||||
## Misc. Repository Dispatch Workflows
|
||||
|
||||
Some workflows perform single, common tasks and are triggered by `repository_dispatch` events. These include the `workflows/email-report.yaml` that emails the results of performance benchmarks to the team, or the `workflows/pull-report.yaml` that posts those same results to an open pull request. Workflows like these are triggered by external clients.
|
||||
@@ -0,0 +1,221 @@
|
||||
name: Bump Deps
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ bump-dependency ]
|
||||
|
||||
jobs:
|
||||
sanitize-payload:
|
||||
name: Sanitize Payload
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
label: ${{ steps.sanitize.outputs.label }}
|
||||
safe_module: ${{ steps.sanitize.outputs.safe_module }}
|
||||
safe_head: ${{ steps.sanitize.outputs.safe_head }}
|
||||
safe_assignee: ${{ steps.sanitize.outputs.safe_assignee }}
|
||||
safe_email: ${{ steps.sanitize.outputs.safe_email }}
|
||||
safe_branch: ${{ steps.sanitize.outputs.safe_branch }}
|
||||
safe_short: ${{ steps.sanitize.outputs.safe_short }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Validate & Sanitize Payload (script)
|
||||
id: sanitize
|
||||
env:
|
||||
RAW_DEP: ${{ github.event.client_payload.dependency }}
|
||||
RAW_SHA: ${{ github.event.client_payload.head_commit_sha }}
|
||||
RAW_USER: ${{ github.event.client_payload.assignee }}
|
||||
RAW_MAIL: ${{ github.event.client_payload.assignee_email }}
|
||||
run: bash .github/scripts/sanitize_payload.sh
|
||||
|
||||
stale-bump-prs:
|
||||
name: Retrieving Stale Bump PRs
|
||||
needs: sanitize-payload
|
||||
outputs:
|
||||
stale-pulls: ${{ steps.get-stale-prs.outputs.open-pulls }}
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Get Open Bump PRs
|
||||
id: get-stale-prs
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
LABEL: ${{ needs.sanitize-payload.outputs.label }}
|
||||
with:
|
||||
debug: true
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
script: |
|
||||
try {
|
||||
const { LABEL } = process.env;
|
||||
const { owner, repo } = context.repo;
|
||||
const res = await github.rest.pulls.list({
|
||||
owner,
|
||||
repo,
|
||||
state: 'open',
|
||||
sort: 'created',
|
||||
direction: 'desc',
|
||||
});
|
||||
|
||||
const { data } = res;
|
||||
|
||||
const reduced = data.reduce((acc, p) => {
|
||||
if (p.labels.length < 1) return acc;
|
||||
|
||||
let keepAlive = false;
|
||||
let shouldPush = false;
|
||||
|
||||
for (const label of p.labels) {
|
||||
if (label.name === LABEL) {
|
||||
shouldPush = true;
|
||||
}
|
||||
if (label.name === "keep-alive") {
|
||||
keepAlive = true;
|
||||
}
|
||||
}
|
||||
if (shouldPush) {
|
||||
acc.push({
|
||||
number: p.number,
|
||||
keepAlive,
|
||||
headRef: p.head.ref,
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
console.log(reduced);
|
||||
if (reduced.length > 0) core.setOutput("open-pulls", JSON.stringify(reduced));
|
||||
process.exit(0);
|
||||
} catch(err) {
|
||||
console.log("Error:", err);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
open-bump-pr:
|
||||
needs: [sanitize-payload, stale-bump-prs]
|
||||
name: Open Bump PR
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
latest-pr: ${{ steps.latest-pr.outputs.pr_url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Bump dependency (safe)
|
||||
working-directory: go
|
||||
env:
|
||||
SAFE_MODULE: ${{ needs.sanitize-payload.outputs.safe_module }}
|
||||
SAFE_HEAD: ${{ needs.sanitize-payload.outputs.safe_head }}
|
||||
run: |
|
||||
GOOS=linux go get "${SAFE_MODULE}@${SAFE_HEAD}"
|
||||
go mod tidy
|
||||
- name: Get Assignee and Reviewer (safe)
|
||||
id: get_reviewer
|
||||
env:
|
||||
ASSIGNEE: ${{ needs.sanitize-payload.outputs.safe_assignee }}
|
||||
run: |
|
||||
if [ "${ASSIGNEE}" == "zachmu" ]
|
||||
then
|
||||
echo "reviewer=Hydrocharged" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "reviewer=zachmu" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Create and Push new branch (safe)
|
||||
env:
|
||||
GIT_USER: ${{ needs.sanitize-payload.outputs.safe_assignee }}
|
||||
GIT_MAIL: ${{ needs.sanitize-payload.outputs.safe_email }}
|
||||
BRANCH: ${{ needs.sanitize-payload.outputs.safe_branch }}
|
||||
COMMIT_BY: ${{ needs.sanitize-payload.outputs.safe_assignee }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git config --global user.name "${GIT_USER}"
|
||||
git config --global user.email "${GIT_MAIL}"
|
||||
git checkout -b "${BRANCH}"
|
||||
git add .
|
||||
git commit -m "[ga-bump-dep] Bump dependency in Dolt by ${COMMIT_BY}"
|
||||
git push origin "${BRANCH}"
|
||||
- name: pull-request
|
||||
uses: repo-sync/pull-request@v2
|
||||
id: latest-pr
|
||||
with:
|
||||
source_branch: ${{ needs.sanitize-payload.outputs.safe_branch }}
|
||||
destination_branch: "main"
|
||||
github_token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
pr_title: "[auto-bump] [no-release-notes] dependency by ${{ needs.sanitize-payload.outputs.safe_assignee }}"
|
||||
pr_template: ".github/markdown-templates/dep-bump.md"
|
||||
pr_reviewer: ${{ steps.get_reviewer.outputs.reviewer }}
|
||||
pr_assignee: ${{ needs.sanitize-payload.outputs.safe_assignee }}
|
||||
pr_label: ${{ needs.sanitize-payload.outputs.label }}
|
||||
|
||||
comment-on-stale-prs:
|
||||
needs: [open-bump-pr, stale-bump-prs]
|
||||
if: ${{ needs.stale-bump-prs.outputs.stale-pulls != '' }}
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
pull: ${{ fromJson(needs.stale-bump-prs.outputs.stale-pulls) }}
|
||||
steps:
|
||||
- name: Comment/Close Stale PRs
|
||||
id: get-stale-prs
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PULL: ${{ toJson(matrix.pull) }}
|
||||
SUPERSEDED_BY: ${{ needs.open-bump-pr.outputs.latest-pr }}
|
||||
with:
|
||||
debug: true
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
script: |
|
||||
try {
|
||||
const { owner, repo } = context.repo;
|
||||
const { PULL, SUPERSEDED_BY } = process.env;
|
||||
const pull = JSON.parse(PULL);
|
||||
|
||||
if (pull.keepAlive) process.exit(0);
|
||||
|
||||
const checkSuiteRes = await github.rest.checks.listSuitesForRef({
|
||||
owner,
|
||||
repo,
|
||||
ref: pull.headRef,
|
||||
});
|
||||
|
||||
if (checkSuiteRes.data) {
|
||||
const okConclusions = new Set(["success", "neutral", "skipped"]);
|
||||
for (const suite of checkSuiteRes.data.check_suites) {
|
||||
console.log("suite id:", suite.id);
|
||||
console.log("suite app slug:", suite.app.slug);
|
||||
console.log("suite status:", suite.status);
|
||||
console.log("suite conclusion:", suite.conclusion);
|
||||
if (suite.app.slug === "github-actions") {
|
||||
if (suite.status !== "completed") {
|
||||
console.log(`Leaving pr open due to status:${suite.status} conclusion:${suite.conclusion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
if (!suite.conclusion || !okConclusions.has(suite.conclusion)) {
|
||||
console.log(`Leaving pr open due to status:${suite.status} conclusion:${suite.conclusion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Closing open pr ${pull.number}`);
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: pull.number,
|
||||
owner,
|
||||
repo,
|
||||
body: `This PR has been superseded by ${SUPERSEDED_BY}`
|
||||
});
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner,
|
||||
repo,
|
||||
pull_number: pull.number,
|
||||
state: 'closed',
|
||||
});
|
||||
|
||||
process.exit(0);
|
||||
} catch(err) {
|
||||
console.log("Error:", err);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
name: Bump Dolt on winget
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
repository_dispatch:
|
||||
types: [ bump-winget ]
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
name: Get Version
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.get_version.outputs.version }}
|
||||
steps:
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: |
|
||||
version=""
|
||||
|
||||
if [ "${{ github.event_name }}" == "repository_dispatch" ]
|
||||
then
|
||||
version="${{ github.event.client_payload.version }}"
|
||||
else
|
||||
version="${{ github.event.inputs.version }}"
|
||||
fi
|
||||
|
||||
echo "version=$version" >> $GITHUB_OUTPUT
|
||||
|
||||
winget-bump:
|
||||
needs: get-version
|
||||
name: Bump Dolt winget
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: powershell
|
||||
steps:
|
||||
- name: Create winget PR
|
||||
run: |
|
||||
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
|
||||
.\wingetcreate.exe update DoltHub.Dolt -u $Env:URL -v $Env:VERSION -t $Env:TOKEN --submit
|
||||
env:
|
||||
TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
VERSION: ${{ needs.get-version.outputs.version }}
|
||||
URL: ${{ format('https://github.com/dolthub/dolt/releases/download/v{0}/dolt-windows-amd64.msi', needs.get-version.outputs.version) }}
|
||||
@@ -0,0 +1,71 @@
|
||||
name: Create Release Notes
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
repository_dispatch:
|
||||
types: [ release-notes ]
|
||||
|
||||
jobs:
|
||||
create-release-notes:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Get Vars
|
||||
id: get_vars
|
||||
run: |
|
||||
if [ "$EVENT_NAME" == "workflow_dispatch" ]
|
||||
then
|
||||
release_id=$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/dolthub/dolt/releases/tags/v${{ github.event.inputs.version }} | jq '.id')
|
||||
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
|
||||
echo "release_id=$release_id" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=${{ github.event.client_payload.version }}" >> $GITHUB_OUTPUT
|
||||
echo "release_id=${{ github.event.client_payload.release_id }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
- name: Checkout Release Notes Generator
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: dolthub/release-notes-generator
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
- name: Install Dependencies
|
||||
run: sudo ./install-deps.sh
|
||||
env:
|
||||
PERL_MM_USE_DEFAULT: 1
|
||||
- name: Create Notes
|
||||
run: |
|
||||
git clone https://github.com/dolthub/dolt.git
|
||||
./gen_release_notes.pl \
|
||||
--token "$TOKEN" \
|
||||
-d dolthub/go-mysql-server \
|
||||
-d dolthub/vitess dolthub/dolt v${{ steps.get_vars.outputs.version }} > changelog.txt
|
||||
env:
|
||||
TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
- name: Post Changelog to Release
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
debug: true
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const path = require('path')
|
||||
try {
|
||||
const body = fs.readFileSync(path.join(process.env.WORKSPACE, "changelog.txt"), { encoding: "utf8" })
|
||||
const res = await github.rest.repos.updateRelease({
|
||||
owner: "dolthub",
|
||||
repo: "dolt",
|
||||
release_id: parseInt(process.env.RELEASE_ID, 10),
|
||||
body,
|
||||
});
|
||||
console.log("Successfully updated release notes", res)
|
||||
} catch (err) {
|
||||
console.log("Error", err);
|
||||
process.exit(1);
|
||||
}
|
||||
env:
|
||||
WORKSPACE: ${{ github.workspace }}
|
||||
RELEASE_ID: ${{ steps.get_vars.outputs.release_id }}
|
||||
@@ -0,0 +1,98 @@
|
||||
name: Push Docker Image to DockerHub
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
push_latest:
|
||||
description: 'Also tag and push as latest'
|
||||
type: boolean
|
||||
default: true
|
||||
repository_dispatch:
|
||||
types: [ push-docker-image ]
|
||||
|
||||
jobs:
|
||||
get-release-id:
|
||||
name: Get Dolt Release Id
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
release_id: ${{ steps.get_release.outputs.release_id }}
|
||||
steps:
|
||||
- name: Get Release
|
||||
id: get_release
|
||||
run: |
|
||||
release_id="$RELEASE_ID"
|
||||
if [ "$EVENT_TYPE" == "workflow_dispatch" ]; then
|
||||
release_id=$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/dolthub/dolt/releases/tags/v${{ github.event.inputs.version }} | jq '.id')
|
||||
fi
|
||||
echo "release_id=$release_id" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
EVENT_TYPE: ${{ github.event_name }}
|
||||
RELEASE_ID: ${{ github.event.client_payload.release_id }}
|
||||
|
||||
docker-image-push:
|
||||
name: Push Docker Image
|
||||
needs: get-release-id
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Build and push dolt image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
file: ./docker/Dockerfile
|
||||
push: true
|
||||
tags: dolthub/dolt:${{ github.event.inputs.version || github.event.client_payload.version }}${{ (github.event_name != 'workflow_dispatch' || inputs.push_latest) && ' , dolthub/dolt:latest' || '' }}
|
||||
build-args: |
|
||||
DOLT_VERSION=${{ github.event.inputs.version || github.event.client_payload.version }}
|
||||
- name: Build and push dolt-sql-server image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
file: ./docker/serverDockerfile
|
||||
push: true
|
||||
tags: dolthub/dolt-sql-server:${{ github.event.inputs.version || github.event.client_payload.version }}${{ (github.event_name != 'workflow_dispatch' || inputs.push_latest) && ' , dolthub/dolt-sql-server:latest' || '' }}
|
||||
build-args: |
|
||||
DOLT_VERSION=${{ github.event.inputs.version || github.event.client_payload.version }}
|
||||
- name: Update Docker Hub Readme for dolt image
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
repository: dolthub/dolt
|
||||
readme-filepath: ./docker/README.md
|
||||
- name: Update Docker Hub Readme for dolt-sql-server image
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||
repository: dolthub/dolt-sql-server
|
||||
readme-filepath: ./docker/serverREADME.md
|
||||
- run: |
|
||||
gh api \
|
||||
--method PATCH \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
/repos/$REPO_OWNER/$REPO_NAME/releases/$RELEASE_ID \
|
||||
-F "draft=false" -F "prerelease=false" -F "make_latest=true"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
REPO_OWNER: dolthub
|
||||
REPO_NAME: dolt
|
||||
RELEASE_ID: ${{ needs.get-release-id.outputs.release_id }}
|
||||
@@ -0,0 +1,256 @@
|
||||
name: Release PGO Dolt
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
profile_bucket:
|
||||
description: 's3 bucket of dolt profile used to build pgo'
|
||||
required: true
|
||||
profile_key:
|
||||
description: 's3 key of dolt profile used to build pgo'
|
||||
required: true
|
||||
branch:
|
||||
description: 'git branch to release from'
|
||||
required: false
|
||||
default: 'main'
|
||||
commit_sha:
|
||||
description: 'exact commit SHA to build from'
|
||||
required: false
|
||||
skip_rpm:
|
||||
description: 'skips rpm releases for older dolt releases'
|
||||
required: false
|
||||
default: false
|
||||
|
||||
repository_dispatch:
|
||||
types: [ pgo-release ]
|
||||
|
||||
jobs:
|
||||
format-version:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.format_version.outputs.version }}
|
||||
steps:
|
||||
- name: Format Input
|
||||
id: format_version
|
||||
run: |
|
||||
version="${{ github.event.inputs.version || github.event.client_payload.version }}"
|
||||
if [[ $version == v* ]];
|
||||
then
|
||||
version="${version:1}"
|
||||
fi
|
||||
echo "version=$version" >> $GITHUB_OUTPUT
|
||||
|
||||
create-pgo-release:
|
||||
needs: format-version
|
||||
runs-on: ubuntu-22.04
|
||||
name: Release PGO Dolt
|
||||
outputs:
|
||||
release_id: ${{ steps.create_release.outputs.id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch || github.event.client_payload.branch || 'main' }}
|
||||
token: ${{ secrets.DOLT_RELEASE_TOKEN }}
|
||||
- name: Pin to exact commit SHA
|
||||
if: ${{ github.event.inputs.commit_sha || github.event.client_payload.from_version }}
|
||||
run: git checkout -B "$BRANCH" "$SHA"
|
||||
env:
|
||||
BRANCH: ${{ github.event.inputs.branch || github.event.client_payload.branch || 'main' }}
|
||||
SHA: ${{ github.event.inputs.commit_sha || github.event.client_payload.from_version }}
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Get Results
|
||||
id: get-results
|
||||
run: aws s3api get-object --bucket="$BUCKET" --key="$KEY" dolt-cpu-profile.pprof
|
||||
env:
|
||||
KEY: ${{ github.event.inputs.profile_key || github.event.client_payload.profile_key }}
|
||||
BUCKET: ${{ github.event.inputs.profile_bucket || github.event.client_payload.bucket }}
|
||||
- name: Update dolt version command
|
||||
run: sed -i -e 's/ Version = ".*"/ Version = "'"$NEW_VERSION"'"/' "$FILE"
|
||||
env:
|
||||
FILE: ${{ format('{0}/go/cmd/dolt/doltversion/version.go', github.workspace) }}
|
||||
NEW_VERSION: ${{ needs.format-version.outputs.version }}
|
||||
- name: Set minver TBD to version
|
||||
run: sed -i -e 's/minver:"TBD"/minver:"'"$NEW_VERSION"'"/' "$FILE"
|
||||
env:
|
||||
FILE: ${{ format('{0}/go/libraries/doltcore/servercfg/yaml_config.go', github.workspace) }}
|
||||
NEW_VERSION: ${{ needs.format-version.outputs.version }}
|
||||
- name: update minver_validation.txt
|
||||
working-directory: ./go
|
||||
run: go run -mod=readonly ./utils/genminver_validation/ $FILE
|
||||
env:
|
||||
FILE: ${{ format('{0}/go/libraries/doltcore/servercfg/testdata/minver_validation.txt', github.workspace) }}
|
||||
- uses: EndBug/add-and-commit@v9.1.4
|
||||
with:
|
||||
message: ${{ format('[ga-bump-release] Update Dolt version to {0} and release v{0}', needs.format-version.outputs.version) }}
|
||||
add: ${{ format('["{0}/go/cmd/dolt/doltversion/version.go", "{0}/go/libraries/doltcore/servercfg/yaml_config.go", "{0}/go/libraries/doltcore/servercfg/testdata/minver_validation.txt"]', github.workspace) }}
|
||||
cwd: "."
|
||||
pull: "--ff"
|
||||
- name: Build PGO Binaries
|
||||
id: build_binaries
|
||||
run: |
|
||||
latest=$(git rev-parse HEAD)
|
||||
echo "commitish=$latest" >> $GITHUB_OUTPUT
|
||||
GO_BUILD_VERSION=1.26.2 go/utils/publishrelease/buildpgobinaries.sh
|
||||
env:
|
||||
GO_BUILD_VERSION: "1.26.2"
|
||||
PROFILE: ${{ format('{0}/dolt-cpu-profile.pprof', github.workspace) }}
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: dolthub/create-release@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: v${{ needs.format-version.outputs.version }}
|
||||
release_name: ${{ needs.format-version.outputs.version }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
commitish: ${{ steps.build_binaries.outputs.commitish }}
|
||||
- name: Upload Linux AMD64 Distro
|
||||
id: upload-linux-amd64-distro
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-linux-amd64.tar.gz
|
||||
asset_name: dolt-linux-amd64.tar.gz
|
||||
asset_content_type: application/zip
|
||||
- name: Upload Linux ARM64 Distro
|
||||
id: upload-linux-arm64-distro
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-linux-arm64.tar.gz
|
||||
asset_name: dolt-linux-arm64.tar.gz
|
||||
asset_content_type: application/zip
|
||||
- name: Upload OSX AMD64 Distro
|
||||
id: upload-osx-amd64-distro
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-darwin-amd64.tar.gz
|
||||
asset_name: dolt-darwin-amd64.tar.gz
|
||||
asset_content_type: application/zip
|
||||
- name: Upload OSX ARM64 Distro
|
||||
id: upload-osx-arm64-distro
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-darwin-arm64.tar.gz
|
||||
asset_name: dolt-darwin-arm64.tar.gz
|
||||
asset_content_type: application/zip
|
||||
- name: Upload Windows Distro
|
||||
id: upload-windows-distro
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-windows-amd64.zip
|
||||
asset_name: dolt-windows-amd64.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Upload Windows Distro 7z
|
||||
id: upload-windows-distro-7z
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-windows-amd64.7z
|
||||
asset_name: dolt-windows-amd64.7z
|
||||
asset_content_type: application/x-7z-compressed
|
||||
- name: Upload Install Script
|
||||
id: upload-install-script
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/install.sh
|
||||
asset_name: install.sh
|
||||
asset_content_type: text/plain
|
||||
- name: Upload Linux AMD64 RPM
|
||||
if: ${{ !github.event.inputs.skip_rpm }}
|
||||
id: upload-linux-amd64-rpm
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-${{ needs.format-version.outputs.version }}-1.x86_64.rpm
|
||||
asset_name: dolt-${{ needs.format-version.outputs.version }}-1.x86_64.rpm
|
||||
asset_content_type: application/zip
|
||||
- name: Upload Linux ARM64 RPM
|
||||
if: ${{ !github.event.inputs.skip_rpm }}
|
||||
id: upload-linux-arm64-rpm
|
||||
uses: dolthub/upload-release-asset@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: go/out/dolt-${{ needs.format-version.outputs.version }}-1.aarch64.rpm
|
||||
asset_name: dolt-${{ needs.format-version.outputs.version }}-1.aarch64.rpm
|
||||
asset_content_type: application/zip
|
||||
|
||||
create-windows-msi:
|
||||
needs: [format-version, create-pgo-release]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger Upload MSI
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: upload-msi
|
||||
repository: dolthub/windows-msi-creator
|
||||
client-payload: '{"tag": "${{ needs.format-version.outputs.version }}", "release_id": "${{ needs.create-pgo-release.outputs.release_id }}", "actor": "${{ github.actor }}", "bucket": "${{ github.event.inputs.profile_bucket || github.event.client_payload.bucket }}", "profile_key": "${{ github.event.inputs.profile_key || github.event.client_payload.profile_key }}"}'
|
||||
|
||||
create-release-notes:
|
||||
needs: [format-version, create-pgo-release]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger Release Notes
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: release-notes
|
||||
client-payload: '{"version": "${{ needs.format-version.outputs.version }}", "release_id": "${{ needs.create-pgo-release.outputs.release_id }}"}'
|
||||
|
||||
trigger-performance-benchmark-email:
|
||||
needs: [format-version, create-pgo-release]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger Performance Benchmarks
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: release-dolt
|
||||
client-payload: '{"version": "${{ needs.format-version.outputs.version }}", "actor": "${{ github.actor }}", "profile_key": "${{ github.event.inputs.profile_key || github.event.client_payload.profile_key }}"}'
|
||||
|
||||
docker-image-push:
|
||||
needs: [format-version, create-pgo-release]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Trigger Push Docker Image
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: push-docker-image
|
||||
client-payload: '{"version": "${{ needs.format-version.outputs.version }}", "release_id": "${{ needs.create-pgo-release.outputs.release_id }}" }'
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Release Dolt
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
branch:
|
||||
description: 'git branch to release from'
|
||||
required: false
|
||||
default: 'main'
|
||||
|
||||
jobs:
|
||||
format-version:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.format_version.outputs.version }}
|
||||
steps:
|
||||
- name: Format Input
|
||||
id: format_version
|
||||
run: |
|
||||
version="${{ github.event.inputs.version }}"
|
||||
if [[ $version == v* ]];
|
||||
then
|
||||
version="${version:1}"
|
||||
fi
|
||||
echo "version=$version" >> $GITHUB_OUTPUT
|
||||
|
||||
profile-benchmark-dolt:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: format-version
|
||||
name: Trigger Benchmark Profile K8s Workflows
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
- name: Get sha
|
||||
id: get_sha
|
||||
run: |
|
||||
sha=$(git rev-parse --short HEAD)
|
||||
echo "sha=$sha" >> $GITHUB_OUTPUT
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: profile-dolt
|
||||
client-payload: '{"from_version": "${{ steps.get_sha.outputs.sha }}", "future_version": "${{ needs.format-version.outputs.version }}", "mode": "release", "actor": "${{ github.actor }}", "actor_email": "dustin@dolthub.com", "template_script": "./.github/scripts/performance-benchmarking/get-dolt-profile-job-json.sh", "branch": "${{ github.event.inputs.branch }}"}'
|
||||
@@ -0,0 +1,138 @@
|
||||
name: Test Bats MacOS
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 1 * * *'
|
||||
|
||||
concurrency:
|
||||
group: ci-bats-mac-nightly
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Bats tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
use_credentials: ${{ secrets.AWS_SECRET_ACCESS_KEY != '' && secrets.AWS_ACCESS_KEY_ID != '' }}
|
||||
steps:
|
||||
- name: Conditionally Set ENV VARS for AWS tests
|
||||
run: |
|
||||
if [[ $use_credentials == true ]]; then
|
||||
echo "AWS_SDK_LOAD_CONFIG=1" >> $GITHUB_ENV
|
||||
echo "AWS_REGION=us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_TABLE=dolt-ci-bats-manifests-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_BUCKET=dolt-ci-bats-chunks-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_EXISTING_REPO=aws_remote_bats_tests__dolt__" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 10800 # 3 hours D:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Setup Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ^16
|
||||
- name: Build dolt
|
||||
uses: ./.github/actions/build-dolt
|
||||
with:
|
||||
remotesrv: 'true'
|
||||
noms: 'true'
|
||||
- name: Install Bats
|
||||
run: |
|
||||
npm i bats
|
||||
echo "$(pwd)/node_modules/.bin" >> $GITHUB_PATH
|
||||
working-directory: ./.ci_bin
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
pip install mysql-connector-python
|
||||
pip install pandas
|
||||
pip install pyarrow
|
||||
- name: Install MySQL client LTS release (8.4)
|
||||
run: |
|
||||
brew update
|
||||
brew install mysql-client@8.4
|
||||
brew link mysql-client@8.4 --force
|
||||
mysql --version
|
||||
- name: Setup Dolt Config
|
||||
uses: ./.github/actions/setup-dolt-config
|
||||
- name: Install Maven
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -LO https://dlcdn.apache.org/maven/maven-3/3.9.15/binaries/apache-maven-3.9.15-bin.tar.gz
|
||||
tar -xf apache-maven-3.9.15-bin.tar.gz
|
||||
echo "$(pwd)/apache-maven-3.9.15/bin" >> $GITHUB_PATH
|
||||
- name: Install Hadoop
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
|
||||
tar xvf hadoop-3.3.6.tar.gz
|
||||
echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH
|
||||
- name: Install parquet-cli
|
||||
id: parquet_cli
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -OL https://github.com/apache/parquet-mr/archive/refs/tags/apache-parquet-1.12.3.tar.gz
|
||||
tar zxvf apache-parquet-1.12.3.tar.gz
|
||||
cd parquet-java-apache-parquet-1.12.3/parquet-cli
|
||||
mvn clean install -DskipTests
|
||||
runtime_jar="$(pwd)"/target/parquet-cli-1.12.3-runtime.jar
|
||||
echo "runtime_jar=$runtime_jar" >> $GITHUB_OUTPUT
|
||||
- name: Check expect
|
||||
run: expect -v
|
||||
- name: Test all Mac
|
||||
env:
|
||||
SQL_ENGINE: "local-engine"
|
||||
PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }}
|
||||
BATS_TEST_RETRIES: "3"
|
||||
run: |
|
||||
bats --tap $BATS_FILTER .
|
||||
working-directory: ./integration-tests/bats
|
||||
|
||||
report-bats-failure:
|
||||
name: Report Bats MacOS Failure via Email
|
||||
needs: test
|
||||
runs-on: ubuntu-22.04
|
||||
if: always() && (needs.test.result == 'failure')
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Send Email
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
region: us-west-2
|
||||
version: ${{ github.ref }}
|
||||
template: 'BatsMacFailureTemplate'
|
||||
toAddresses: '["${{ github.event.inputs.email }}"]'
|
||||
workflowURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
- name: Send Email
|
||||
if: ${{ github.event_name == 'schedule' }}
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
region: us-west-2
|
||||
version: ${{ github.event.client_payload.ref }}
|
||||
template: 'BatsMacFailureTemplate'
|
||||
toAddresses: '["dolts@dolthub.com", "tim@dolthub.com"]'
|
||||
workflowURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@@ -0,0 +1,101 @@
|
||||
name: Test Bats Unix Remote
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-bats-unix-remote${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Bats tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
use_credentials: ${{ secrets.AWS_SECRET_ACCESS_KEY != '' && secrets.AWS_ACCESS_KEY_ID != '' }}
|
||||
# We only run these as seaparte workflow if we do not have AWS credentials.
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
- name: Set up Go toolchain
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Setup Python 3.x
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- uses: actions/setup-node@v4
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
with:
|
||||
node-version: ^16
|
||||
- name: Build dolt
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
uses: ./.github/actions/build-dolt
|
||||
with:
|
||||
remotesrv: 'true'
|
||||
noms: 'true'
|
||||
- name: Install Bats
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
run: |
|
||||
npm i bats
|
||||
echo "$(pwd)/node_modules/.bin" >> $GITHUB_PATH
|
||||
working-directory: ./.ci_bin
|
||||
- name: Install Python Deps
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
run: |
|
||||
pip install mysql-connector-python
|
||||
pip install pandas
|
||||
pip install pyarrow
|
||||
- name: Setup Dolt Config
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
uses: ./.github/actions/setup-dolt-config
|
||||
- name: Install expect
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
run: sudo apt-get install -y expect
|
||||
- name: Install Maven
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -LO https://dlcdn.apache.org/maven/maven-3/3.9.15/binaries/apache-maven-3.9.15-bin.tar.gz
|
||||
tar -xf apache-maven-3.9.15-bin.tar.gz
|
||||
echo "$(pwd)/apache-maven-3.9.15/bin" >> $GITHUB_PATH
|
||||
- name: Install Hadoop
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
|
||||
tar xvf hadoop-3.3.6.tar.gz
|
||||
echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH
|
||||
- name: Install parquet-cli
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
id: parquet_cli
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -OL https://github.com/apache/parquet-mr/archive/refs/tags/apache-parquet-1.12.3.tar.gz
|
||||
tar zxvf apache-parquet-1.12.3.tar.gz
|
||||
cd parquet-java-apache-parquet-1.12.3/parquet-cli
|
||||
mvn clean install -DskipTests
|
||||
runtime_jar="$(pwd)"/target/parquet-cli-1.12.3-runtime.jar
|
||||
echo "runtime_jar=$runtime_jar" >> $GITHUB_OUTPUT
|
||||
- name: Check expect
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
run: expect -v
|
||||
- name: Test all Unix
|
||||
if: ${{ env.use_credentials != 'true' }}
|
||||
env:
|
||||
SQL_ENGINE: "remote-engine"
|
||||
PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }}
|
||||
BATS_TEST_RETRIES: "3"
|
||||
run: |
|
||||
bats --print-output-on-failure --tap .
|
||||
working-directory: ./integration-tests/bats
|
||||
@@ -0,0 +1,134 @@
|
||||
name: Test Bats Unix
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-bats-unix-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Bats tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ ubuntu-22.04 ]
|
||||
env:
|
||||
use_credentials: ${{ secrets.AWS_SECRET_ACCESS_KEY != '' && secrets.AWS_ACCESS_KEY_ID != '' }}
|
||||
steps:
|
||||
# Docker entrypoint and docker tests in general may use more space than is available in the GitHub default runner,
|
||||
# so we remove unused pre-installed programs.
|
||||
- name: Free disk space
|
||||
run: |
|
||||
NAME="DISK-CLEANUP"
|
||||
echo "[${NAME}] Starting background cleanup..."
|
||||
[ -d /usr/share/dotnet ] && sudo rm -rf /usr/share/dotnet &
|
||||
[ -d /usr/local/lib/android ] && sudo rm -rf /usr/local/lib/android &
|
||||
[ -d /opt/ghc ] && sudo rm -rf /opt/ghc &
|
||||
[ -d /usr/local/share/boost ] && sudo rm -rf /usr/local/share/boost &
|
||||
|
||||
- name: Conditionally Set ENV VARS for AWS tests
|
||||
run: |
|
||||
if [[ $use_credentials == true ]]; then
|
||||
echo "AWS_SDK_LOAD_CONFIG=1" >> $GITHUB_ENV
|
||||
echo "AWS_REGION=us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_TABLE=dolt-ci-bats-manifests-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_BUCKET=dolt-ci-bats-chunks-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_EXISTING_REPO=aws_remote_bats_tests__dolt__" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Configure filter tags for lambda bats
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' && env.use_credentials == 'true' }}
|
||||
run: |
|
||||
echo "BATS_FILTER=--filter-tags no_lambda" >> $GITHUB_ENV
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 10800 # 3 hours D:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Setup Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ^16
|
||||
- name: Build dolt
|
||||
uses: ./.github/actions/build-dolt
|
||||
with:
|
||||
remotesrv: 'true'
|
||||
noms: 'true'
|
||||
- name: Install Bats
|
||||
run: |
|
||||
npm i bats
|
||||
echo "$(pwd)/node_modules/.bin" >> $GITHUB_PATH
|
||||
working-directory: ./.ci_bin
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
pip install mysql-connector-python
|
||||
pip install pandas
|
||||
pip install pyarrow
|
||||
- name: Setup Dolt Config
|
||||
uses: ./.github/actions/setup-dolt-config
|
||||
- name: Install expect
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: sudo apt-get install -y expect
|
||||
- name: Install pcre2grep
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: sudo apt-get install -y pcre2-utils
|
||||
- name: Install openssh-server
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: sudo apt-get install -y openssh-server
|
||||
- name: Install Maven
|
||||
run: sudo apt-get install -y maven
|
||||
- name: Install Hadoop
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -LO https://downloads.apache.org/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz
|
||||
tar xvf hadoop-3.3.6.tar.gz
|
||||
echo "$(pwd)/hadoop-3.3.6/bin" >> $GITHUB_PATH
|
||||
- name: Install parquet-cli
|
||||
id: parquet_cli
|
||||
working-directory: ./.ci_bin
|
||||
run: |
|
||||
curl -OL https://github.com/apache/parquet-mr/archive/refs/tags/apache-parquet-1.12.3.tar.gz
|
||||
tar zxvf apache-parquet-1.12.3.tar.gz
|
||||
cd parquet-java-apache-parquet-1.12.3/parquet-cli
|
||||
mvn clean install -DskipTests
|
||||
runtime_jar="$(pwd)"/target/parquet-cli-1.12.3-runtime.jar
|
||||
echo "runtime_jar=$runtime_jar" >> $GITHUB_OUTPUT
|
||||
- name: Check expect
|
||||
run: expect -v
|
||||
- name: Test all Unix
|
||||
env:
|
||||
SQL_ENGINE: "local-engine"
|
||||
PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }}
|
||||
BATS_TEST_RETRIES: "3"
|
||||
run: |
|
||||
bats --print-output-on-failure --tap $BATS_FILTER .
|
||||
working-directory: ./integration-tests/bats
|
||||
- name: Test all Unix, SQL_ENGINE=remote-engine
|
||||
# If we have AWS credentials, we run these remote-engine tests here instead of in the separate job.
|
||||
if: ${{ env.use_credentials == 'true' && matrix.os == 'ubuntu-22.04' }}
|
||||
env:
|
||||
SQL_ENGINE: "remote-engine"
|
||||
PARQUET_RUNTIME_JAR: ${{ steps.parquet_cli.outputs.runtime_jar }}
|
||||
BATS_TEST_RETRIES: "3"
|
||||
run: |
|
||||
bats --print-output-on-failure --tap $BATS_FILTER .
|
||||
working-directory: ./integration-tests/bats
|
||||
@@ -0,0 +1,173 @@
|
||||
name: Test Bats Windows
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
email:
|
||||
description: 'Email address to receive bats failure notification'
|
||||
required: true
|
||||
default: ''
|
||||
repository_dispatch:
|
||||
types: [ bats-windows ]
|
||||
|
||||
jobs:
|
||||
get-files:
|
||||
name: Get file list
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
files: ${{ steps.get_file_list.outputs.files }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ github.event_name == 'repository_dispatch' }}
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
- name: Get file list
|
||||
id: get_file_list
|
||||
run: |
|
||||
files=$(ls *.bats)
|
||||
|
||||
SAVEIFS=$IFS
|
||||
IFS=$'\n'
|
||||
|
||||
file_arr=($files)
|
||||
echo "files=${file_arr[@]}" >> $GITHUB_OUTPUT
|
||||
|
||||
IFS=$SAVEIFS
|
||||
working-directory: ./integration-tests/bats
|
||||
format-files-output:
|
||||
name: Format files output
|
||||
runs-on: ubuntu-22.04
|
||||
needs: get-files
|
||||
outputs:
|
||||
files: ${{ steps.format_files.outputs.files }}
|
||||
steps:
|
||||
- name: Format
|
||||
id: format_files
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
FILES: ${{ needs.get-files.outputs.files }}
|
||||
with:
|
||||
debug: true
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
try {
|
||||
const { FILES } = process.env;
|
||||
const fileList = FILES.split(" ");
|
||||
core.setOutput("files", JSON.stringify(fileList));
|
||||
process.exit(0);
|
||||
} catch(err) {
|
||||
console.log("Error:", err);
|
||||
process.exit(1);
|
||||
}
|
||||
test-per-file:
|
||||
name: Test file
|
||||
needs: format-files-output
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
use_credentials: ${{ secrets.AWS_SECRET_ACCESS_KEY != '' && secrets.AWS_ACCESS_KEY_ID != '' }}
|
||||
strategy:
|
||||
matrix:
|
||||
file: ${{ fromJson(needs.format-files-output.outputs.files) }}
|
||||
steps:
|
||||
- name: Conditionally Set ENV VARS for AWS tests
|
||||
run: |
|
||||
if [[ $use_credentials == true ]]; then
|
||||
echo "AWS_SDK_LOAD_CONFIG=1" >> $GITHUB_ENV
|
||||
echo "AWS_REGION=us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_TABLE=dolt-ci-bats-manifests-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_BUCKET=dolt-ci-bats-chunks-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_EXISTING_REPO=aws_remote_bats_tests" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 3600
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ github.event_name == 'repository_dispatch' }}
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Setup Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ^16
|
||||
- name: Build dolt
|
||||
uses: ./.github/actions/build-dolt
|
||||
with:
|
||||
remotesrv: 'true'
|
||||
noms: 'true'
|
||||
- name: Install Bats Windows
|
||||
run: |
|
||||
git clone https://github.com/bats-core/bats-core.git
|
||||
cd bats-core
|
||||
./install.sh $HOME
|
||||
working-directory: ./.ci_bin
|
||||
- name: Install wslpath
|
||||
run: |
|
||||
choco install wget
|
||||
wget 'https://raw.githubusercontent.com/laurent22/wslpath/master/wslpath'
|
||||
chmod 755 wslpath
|
||||
mv wslpath /usr/bin/
|
||||
cp /c/tools/php/php /usr/bin/
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
pip install mysql-connector-python
|
||||
pip install pandas
|
||||
pip install pyarrow
|
||||
- name: Setup Dolt Config
|
||||
uses: ./.github/actions/setup-dolt-config
|
||||
- name: Test file
|
||||
run: bats --tap ${{ matrix.file }}
|
||||
working-directory: ./integration-tests/bats
|
||||
env:
|
||||
IS_WINDOWS: true
|
||||
WINDOWS_BASE_DIR: "/d/a"
|
||||
BATS_TEST_RETRIES: "3"
|
||||
|
||||
report-bats-failure:
|
||||
name: Report Bats Windows Failure via Email
|
||||
needs: test-per-file
|
||||
runs-on: ubuntu-22.04
|
||||
if: always() && (needs.test-per-file.result == 'failure')
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Send Email
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
region: us-west-2
|
||||
version: ${{ github.ref }}
|
||||
template: 'BatsWindowsFailureTemplate'
|
||||
toAddresses: '["${{ github.event.inputs.email }}"]'
|
||||
workflowURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
- name: Send Email
|
||||
if: ${{ github.event_name == 'repository_dispatch' }}
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
region: us-west-2
|
||||
version: ${{ github.event.client_payload.ref }}
|
||||
template: 'BatsWindowsFailureTemplate'
|
||||
toAddresses: '["${{ github.event.client_payload.actor_email }}", "tim@dolthub.com"]'
|
||||
workflowURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Test Benchmark Runner Utility Works
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-benchmark-runner-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
benchmark_runner:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Test Benchmark Runner
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Copy Dockerfile
|
||||
run: cp -r ./go/performance/continuous_integration/. .
|
||||
- name: Test runner
|
||||
uses: ./.github/actions/benchmark-runner-tests
|
||||
@@ -0,0 +1,56 @@
|
||||
name: Test Binlog
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ci-binlog-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
binlog-test:
|
||||
name: Binlog tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Test Binlog
|
||||
working-directory: ./go
|
||||
run: |
|
||||
# Test binlog packages
|
||||
go test -vet=off -timeout 60m ./libraries/doltcore/sqle/binlogreplication/...
|
||||
env:
|
||||
MATRIX_OS: ${{ matrix.os }}
|
||||
binlog-race-test:
|
||||
name: Binlog tests - race
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Test Binlog with Race
|
||||
working-directory: ./go
|
||||
run: |
|
||||
# Test binlog packages with race detector
|
||||
go test -vet=off -timeout 60m -race ./libraries/doltcore/sqle/binlogreplication/...
|
||||
env:
|
||||
MATRIX_OS: ${{ matrix.os }}
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Check for correctness_approved label
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
branches: [main]
|
||||
types: [opened, labeled, unlabeled, synchronize]
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mheap/github-action-required-labels@v5
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
labels: "correctness_approved"
|
||||
add_comment: true
|
||||
message: "This PR is being tested for SQL correctness. Please allow ~25 mins for this to complete. If this PR does not result in a SQL correctness regression, the `correctness_approved` label will be automatically added to this PR and the `Check for correctness_approved` workflow will succeed."
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Check for performance_approved label
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
branches: [main]
|
||||
types: [opened, labeled, unlabeled, synchronize]
|
||||
jobs:
|
||||
label:
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: mheap/github-action-required-labels@v5
|
||||
with:
|
||||
mode: exactly
|
||||
count: 1
|
||||
labels: "performance_approved"
|
||||
add_comment: true
|
||||
message: "<!-- go-run-output -->\nThis PR is being tested for performance. Please allow ~25 mins for this to complete. If this PR does not result in a performance regression, the `performance_approved` label will be automatically added to this PR."
|
||||
@@ -0,0 +1,157 @@
|
||||
name: Check Formatting, Committers and Generated Code
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
concurrency:
|
||||
group: ci-check-repo-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
name: Verify format and committers
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
format: ${{ steps.should_format.outputs.format }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Check all
|
||||
id: should_format
|
||||
working-directory: ./go
|
||||
# Keep this in sync with //go/utils/prepr/prepr.sh.
|
||||
run: |
|
||||
GOFLAGS="-mod=readonly" go build ./...
|
||||
go vet -mod=readonly ./...
|
||||
go run -mod=readonly ./utils/copyrightshdrs/
|
||||
./Godeps/verify.sh
|
||||
./utils/repofmt/check_bats_fmt.sh
|
||||
|
||||
if ./utils/repofmt/check_fmt.sh ; then
|
||||
echo "code is formatted"
|
||||
else
|
||||
echo "code is not formatted"
|
||||
if [ "${{ github.repository }}" != "dolthub/dolt" ]; then
|
||||
echo "Pull requests from forks must be manually formatted."
|
||||
echo "Please run dolt/go/utils/repofmt/format_repo.sh to format this pull request."
|
||||
exit 1;
|
||||
fi
|
||||
echo "format=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref }}
|
||||
CHANGE_TARGET: ${{ github.base_ref }}
|
||||
- name: Check generated protobufs and flatbuffers
|
||||
working-directory: ./proto
|
||||
run: |
|
||||
bazel run //:update
|
||||
changes=$(git status --porcelain)
|
||||
diff=$(git diff)
|
||||
if [ ! -z "$changes" ]; then
|
||||
echo "ERROR: Generated protobuf structs and/or flatbuffer messages are different from the checked in version."
|
||||
echo "$changes"
|
||||
echo "$diff"
|
||||
exit 1
|
||||
fi
|
||||
get-artifacts:
|
||||
needs: verify
|
||||
if: ${{ needs.verify.outputs.format == 'true' }}
|
||||
name: Get artifacts
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: "main"
|
||||
repository: "dolthub/dolt"
|
||||
submodules: true
|
||||
- name: Setup Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Copy script
|
||||
working-directory: ./go/utils/repofmt
|
||||
run: cp format_repo.sh _format_repo.sh
|
||||
- name: Build go deps tool
|
||||
working-directory: go/utils/3pdeps
|
||||
run: go build .
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: update-godeps-tool
|
||||
path: go/utils/3pdeps/3pdeps
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: format-code-script
|
||||
path: go/utils/repofmt/_format_repo.sh
|
||||
format:
|
||||
needs: [verify, get-artifacts]
|
||||
if: ${{ needs.verify.outputs.format == 'true' }}
|
||||
name: Format PR
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref || github.ref }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
submodules: true
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
- name: Run go mod tidy
|
||||
run: go mod tidy
|
||||
working-directory: ./go
|
||||
- name: Install goimports
|
||||
run: go install golang.org/x/tools/cmd/goimports@latest
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: format-code-script
|
||||
path: go/utils/repofmt
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: update-godeps-tool
|
||||
path: go
|
||||
- name: Format repo
|
||||
working-directory: ./go
|
||||
run: |
|
||||
chmod +x ./utils/repofmt/_format_repo.sh
|
||||
./utils/repofmt/_format_repo.sh
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref }}
|
||||
CHANGE_TARGET: ${{ github.base_ref }}
|
||||
- name: Update Go deps
|
||||
working-directory: ./go
|
||||
run: |
|
||||
chmod +x ./3pdeps
|
||||
( GOOS=linux GOARCH=amd64 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=linux GOARCH=386 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=linux GOARCH=arm64 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=windows GOARCH=amd64 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=windows GOARCH=arm64 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=darwin GOARCH=amd64 go list -deps -json ./cmd/dolt/. && \
|
||||
GOOS=darwin GOARCH=arm64 go list -deps -json ./cmd/dolt/. ) \
|
||||
| ./3pdeps > ./Godeps/LICENSES
|
||||
- name: Remove artifacts
|
||||
run: |
|
||||
rm go/3pdeps
|
||||
rm go/utils/repofmt/_format_repo.sh
|
||||
- name: Changes detected
|
||||
id: detect-changes
|
||||
run: |
|
||||
changes=$(git status --porcelain)
|
||||
if [ ! -z "$changes" ]; then
|
||||
echo "has-changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- uses: EndBug/add-and-commit@v9.1.4
|
||||
if: ${{ steps.detect-changes.outputs.has-changes == 'true' }}
|
||||
with:
|
||||
message: "[ga-format-pr] Run go/utils/repofmt/format_repo.sh and go/Godeps/update.sh"
|
||||
add: "."
|
||||
cwd: "."
|
||||
pull: "--ff"
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Check Compatibility
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-compatibility-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Compatibility Test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ ubuntu-22.04 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ^16
|
||||
- name: Install netcat
|
||||
run: sudo apt-get update && sudo apt-get install -y netcat-openbsd
|
||||
- name: Build dolt
|
||||
uses: ./.github/actions/build-dolt
|
||||
- name: Install Bats
|
||||
run: |
|
||||
npm i bats
|
||||
echo "$(pwd)/node_modules/.bin" >> $GITHUB_PATH
|
||||
working-directory: ./.ci_bin
|
||||
- name: Setup Dolt Config
|
||||
uses: ./.github/actions/setup-dolt-config
|
||||
- name: Test all
|
||||
run: ./runner.sh
|
||||
working-directory: ./integration-tests/compatibility
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Test Data Dump Loading integrations
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-data-dump-loading-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
data_dump_laoding_integrations_job:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
name: Run tests
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Copy go package
|
||||
run: cp -r ./go ./integration-tests/go
|
||||
- name: Test data dump loading integrations
|
||||
uses: ./.github/actions/data-dump-loading-tests
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Race tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
racetests:
|
||||
name: Go race tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-22.04 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Test engine
|
||||
working-directory: ./go
|
||||
run: |
|
||||
DOLT_SKIP_PREPARED_ENGINETESTS=1 go test -vet=off -v -race -timeout 30m github.com/dolthub/dolt/go/libraries/doltcore/sqle/enginetest
|
||||
- name: Test concurrentmap
|
||||
working-directory: ./go
|
||||
run: |
|
||||
go test -vet=off -v -race -timeout 1m github.com/dolthub/dolt/go/libraries/utils/concurrentmap
|
||||
@@ -0,0 +1,96 @@
|
||||
name: Test Go
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- '.github/workflows/ci-go-tests.yaml'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ci-go-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Go tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
id: toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Test All
|
||||
working-directory: ./go
|
||||
run: |
|
||||
files=$(go list ./...)
|
||||
SAVEIFS=$IFS
|
||||
IFS=$'\n'
|
||||
file_arr=($files)
|
||||
IFS=$SAVEIFS
|
||||
if [ "$MATRIX_OS" == 'windows-latest' ]; then
|
||||
export PATH=$(cygpath -u "$MSYS2_LOCATION"/ucrt64/bin):"$PATH"
|
||||
fi
|
||||
|
||||
for (( i=0; i<${#file_arr[@]}; i++ ))
|
||||
do
|
||||
# Skip binlog tests as they run in a separate CI job
|
||||
if [[ "${file_arr[$i]}" == *binlogreplication* ]]; then
|
||||
echo "Skipping binlog package: ${file_arr[$i]} (runs in separate CI)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Testing Package: ${file_arr[$i]}"
|
||||
if [ "$MATRIX_OS" == 'ubuntu-22.04' ]
|
||||
then
|
||||
if [[ "${file_arr[$i]}" != *enginetest* ]]; then
|
||||
go test -vet=off -timeout 45m -race "${file_arr[$i]}"
|
||||
else
|
||||
echo "skipping enginetests for -race"
|
||||
fi
|
||||
else
|
||||
go test -vet=off -timeout 45m "${file_arr[$i]}"
|
||||
fi
|
||||
succeeded=$(echo "$?")
|
||||
if [ "$succeeded" -ne 0 ]; then
|
||||
echo "Testing failed in package ${file_arr[$i]}"
|
||||
exit 1;
|
||||
fi
|
||||
done
|
||||
env:
|
||||
MATRIX_OS: ${{ matrix.os }}
|
||||
MSYS2_LOCATION: ${{ steps.toolchain.outputs.msys2-location }}
|
||||
noracetest:
|
||||
name: Go tests - no race
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-22.04, windows-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
id: toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Test All
|
||||
working-directory: ./go
|
||||
run: |
|
||||
if [ "$MATRIX_OS" == 'windows-latest' ]; then
|
||||
export PATH=$(cygpath -u "$MSYS2_LOCATION"/ucrt64/bin):"$PATH"
|
||||
fi
|
||||
go test -vet=off -timeout 30m ./libraries/doltcore/sqle/integration_test
|
||||
env:
|
||||
MATRIX_OS: ${{ matrix.os }}
|
||||
DOLT_TEST_RUN_NON_RACE_TESTS: "true"
|
||||
MSYS2_LOCATION: ${{ steps.toolchain.outputs.msys2-location }}
|
||||
@@ -0,0 +1,63 @@
|
||||
name: Test Bats Unix
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-lambdabats-unix-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Bats tests, run with lambdabats
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: true
|
||||
env:
|
||||
use_credentials: ${{ secrets.AWS_SECRET_ACCESS_KEY != '' && secrets.AWS_ACCESS_KEY_ID != '' }}
|
||||
steps:
|
||||
- name: Conditionally Set ENV VARS for AWS tests
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
run: |
|
||||
echo "AWS_SDK_LOAD_CONFIG=1" >> $GITHUB_ENV
|
||||
echo "AWS_REGION=us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_TABLE=dolt-ci-bats-manifests-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_BUCKET=dolt-ci-bats-chunks-us-west-2" >> $GITHUB_ENV
|
||||
echo "DOLT_BATS_AWS_EXISTING_REPO=aws_remote_bats_tests__dolt__" >> $GITHUB_ENV
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
|
||||
role-duration-seconds: 10800 # 3 hours D:
|
||||
- uses: actions/checkout@v6
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
- name: Setup Go 1.x
|
||||
uses: actions/setup-go@v5
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
id: go
|
||||
- name: install lambdabats
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
run: go install github.com/dolthub/lambdabats/lambdabats@latest
|
||||
- name: Test all Unix
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
run: |
|
||||
lambdabats -use-aws-environment-credentials -s lambda_skip -F tap .
|
||||
working-directory: ./integration-tests/bats
|
||||
- name: Test all Unix, SQL_ENGINE=remote-engine
|
||||
if: ${{ env.use_credentials == 'true' }}
|
||||
run: |
|
||||
lambdabats -env SQL_ENGINE=remote-engine -s lambda_skip -use-aws-environment-credentials -F tap .
|
||||
working-directory: ./integration-tests/bats
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Test MySQL Client integrations
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
|
||||
concurrency:
|
||||
group: ci-mysql-client-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
mysql_client_integrations:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: dolt
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
NAME="DISK-CLEANUP"
|
||||
echo "[${NAME}] Starting background cleanup..."
|
||||
[ -d "$AGENT_TOOLSDIRECTORY" ] && sudo rm -rf "$AGENT_TOOLSDIRECTORY" &
|
||||
[ -d /usr/share/dotnet ] && sudo rm -rf /usr/share/dotnet &
|
||||
[ -d /usr/local/lib/android ] && sudo rm -rf /usr/local/lib/android &
|
||||
[ -d /opt/ghc ] && sudo rm -rf /opt/ghc &
|
||||
[ -d /usr/local/share/boost ] && sudo rm -rf /usr/local/share/boost &
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Ensure cache directory exists
|
||||
run: |
|
||||
sudo mkdir -p /mnt/.buildx-cache
|
||||
sudo chown $USER:$USER /mnt/.buildx-cache
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /mnt/.buildx-cache
|
||||
key: ${{ runner.os }}-docker-mysql-client-integrations
|
||||
restore-keys: |
|
||||
${{ runner.os }}-docker
|
||||
|
||||
- name: Build MySQL test image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: dolt/integration-tests/mysql-client-tests/Dockerfile
|
||||
tags: mysql-client-tests:latest
|
||||
load: true
|
||||
cache-from: type=local,src=/mnt/.buildx-cache
|
||||
cache-to: type=local,dest=/mnt/.buildx-cache
|
||||
|
||||
- name: Test MySQL client integrations
|
||||
run: docker run --rm mysql-client-tests:latest
|
||||
@@ -0,0 +1,54 @@
|
||||
name: Test ORM integrations
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
- 'integration-tests/**'
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
types: [ test-orm-integrations ]
|
||||
|
||||
concurrency:
|
||||
group: ci-orm-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
orm_integrations_job:
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
name: ORM tests
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: dolt
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Build ORM test image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: dolt/integration-tests/orm-tests/Dockerfile
|
||||
tags: orm-tests:latest
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
- name: Test ORM integrations
|
||||
run: docker run --rm orm-tests:latest
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ failure() && !env.ACT }}
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Send Email
|
||||
if: ${{ failure() && !env.ACT }}
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
template: 'OrmIntegrationFailureTemplate'
|
||||
region: us-west-2
|
||||
version: ${{ github.ref }}
|
||||
toAddresses: '["jennifer@dolthub.com", "tim@dolthub.com"]'
|
||||
workflowURL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
@@ -0,0 +1,33 @@
|
||||
name: sql-server Integration Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "go/**"
|
||||
- "integration-tests/go-sql-server-driver/**"
|
||||
|
||||
concurrency:
|
||||
group: ci-sql-server-integration-tests-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: sql-server Integration Tests
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Go toolchain
|
||||
uses: ./.github/actions/setup-go-toolchain
|
||||
- name: Build dolt
|
||||
uses: ./.github/actions/build-dolt
|
||||
- name: Test all
|
||||
run: go test .
|
||||
working-directory: ./integration-tests/go-sql-server-driver
|
||||
@@ -0,0 +1,92 @@
|
||||
name: Test Integration with DoltgreSQL
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
issue_comment:
|
||||
types: [created, edited, deleted]
|
||||
|
||||
jobs:
|
||||
test-integration:
|
||||
if: github.event_name == 'issue_comment' && github.event.issue.pull_request != '' || github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Set timezone for Unix
|
||||
uses: szenius/set-timezone@v2.0
|
||||
with:
|
||||
timezoneLinux: "America/Los_Angeles"
|
||||
- name: Checkout Dolt
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Setup Git User
|
||||
uses: fregante/setup-git-user@v2
|
||||
|
||||
- name: Merge main into PR
|
||||
id: merge_main
|
||||
run: |
|
||||
git fetch --all --unshallow
|
||||
git merge origin/main --no-commit --no-ff
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Skipping the remainder of the workflow due to a merge conflict."
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Merge performed successfully, continuing workflow."
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check for a DoltgreSQL PR link
|
||||
id: check_doltgresql_pr
|
||||
if: steps.merge_main.outputs.skip == 'false'
|
||||
run: |
|
||||
PR_DESCRIPTION=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number != '' && github.event.pull_request.number || github.event.issue.number }})
|
||||
COMMENTS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
||||
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number != '' && github.event.pull_request.number || github.event.issue.number }}/comments)
|
||||
echo "$PR_DESCRIPTION$COMMENTS"
|
||||
if echo "$PR_DESCRIPTION$COMMENTS" | grep -q "github.com/dolthub/doltgresql/pull/"; then
|
||||
echo "comment_exists=true" >> $GITHUB_OUTPUT
|
||||
echo "DoltgreSQL PR link exists"
|
||||
else
|
||||
echo "comment_exists=false" >> $GITHUB_OUTPUT
|
||||
echo "DoltgreSQL PR link does not exist"
|
||||
fi
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v5
|
||||
if: steps.merge_main.outputs.skip == 'false'
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
|
||||
- name: Clone DoltgreSQL repository
|
||||
if: steps.merge_main.outputs.skip == 'false' && steps.check_doltgresql_pr.outputs.comment_exists == 'false'
|
||||
run: git clone https://github.com/dolthub/doltgresql.git
|
||||
|
||||
- name: Build DoltgreSQL's parser
|
||||
if: steps.merge_main.outputs.skip == 'false' && steps.check_doltgresql_pr.outputs.comment_exists == 'false'
|
||||
run: |
|
||||
cd doltgresql
|
||||
./postgres/parser/build.sh
|
||||
|
||||
- name: Test DoltgreSQL against main
|
||||
id: test_doltgresql_main
|
||||
if: steps.merge_main.outputs.skip == 'false' && steps.check_doltgresql_pr.outputs.comment_exists == 'false'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd doltgresql
|
||||
go get github.com/dolthub/dolt/go@main
|
||||
go mod tidy
|
||||
cd testing/go
|
||||
go test ./... --count=1 -skip Replication
|
||||
|
||||
- name: Test DoltgreSQL against PR
|
||||
if: steps.merge_main.outputs.skip == 'false' && steps.check_doltgresql_pr.outputs.comment_exists == 'false' && steps.test_doltgresql_main.outcome == 'success'
|
||||
run: |
|
||||
cd doltgresql
|
||||
git reset --hard
|
||||
go mod edit -replace github.com/dolthub/dolt/go=../go
|
||||
go mod tidy
|
||||
cd testing/go
|
||||
go test ./... --count=1 -skip Replication
|
||||
@@ -0,0 +1,44 @@
|
||||
name: Email Team Members
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ email-report ]
|
||||
|
||||
jobs:
|
||||
email-team:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Email Team Members
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Get Results
|
||||
id: get-results
|
||||
run: aws s3api get-object --bucket="$BUCKET" --key="$KEY" results.log
|
||||
env:
|
||||
KEY: ${{ github.event.client_payload.key }}
|
||||
BUCKET: ${{ github.event.client_payload.bucket }}
|
||||
- name: Get Addresses
|
||||
id: get-addresses
|
||||
run: |
|
||||
addresses="$TEAM"
|
||||
if [ ! -z "$RECIPIENT" ]; then
|
||||
addresses="[\"$RECIPIENT\"]"
|
||||
fi
|
||||
echo "addresses=$addresses" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
RECIPIENT: ${{ github.event.client_payload.email_recipient }}
|
||||
TEAM: '["${{ secrets.PERF_REPORTS_EMAIL_ADDRESS }}"]'
|
||||
- name: Send Email
|
||||
uses: ./.github/actions/ses-email-action
|
||||
with:
|
||||
template: ${{ github.event.client_payload.template }}
|
||||
region: us-west-2
|
||||
version: ${{ github.event.client_payload.version }}
|
||||
format: ${{ github.event.client_payload.noms_bin_format }}
|
||||
toAddresses: ${{ steps.get-addresses.outputs.addresses }}
|
||||
dataFile: ${{ format('{0}/results.log', github.workspace) }}
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Run Import Benchmark on Pull Requests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened ]
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
validate-commentor:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
valid: ${{ steps.set_valid.outputs.valid }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Validate Commentor
|
||||
id: set_valid
|
||||
run: ./.github/scripts/performance-benchmarking/validate-commentor.sh "$ACTOR"
|
||||
env:
|
||||
ACTOR: ${{ github.actor }}
|
||||
|
||||
check-comments:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: validate-commentor
|
||||
if: ${{ needs.validate-commentor.outputs.valid == 'true' }}
|
||||
outputs:
|
||||
benchmark: ${{ steps.set_benchmark.outputs.benchmark }}
|
||||
comment-body: ${{ steps.set_body.outputs.body }}
|
||||
steps:
|
||||
- name: Check for Deploy Trigger
|
||||
uses: dolthub/pull-request-comment-trigger@v2
|
||||
id: check
|
||||
with:
|
||||
trigger: '#import-benchmark'
|
||||
reaction: rocket
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set Benchmark
|
||||
if: ${{ steps.check.outputs.triggered == 'true' }}
|
||||
id: set_benchmark
|
||||
run: |
|
||||
echo "benchmark=true" >> $GITHUB_OUTPUT
|
||||
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate-commentor, check-comments]
|
||||
if: ${{ needs.check-comments.outputs.benchmark == 'true' }}
|
||||
name: Trigger Benchmark Import Workflow
|
||||
steps:
|
||||
- uses: dolthub/pull-request-comment-branch@v3
|
||||
id: comment-branch
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get pull number
|
||||
uses: actions/github-script@v7
|
||||
id: get_pull_number
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: core.setOutput("pull_number", JSON.stringify(context.issue.number));
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-import
|
||||
client-payload: |
|
||||
{
|
||||
"version": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"run_file": "ci.yaml",
|
||||
"summary": "summary.sql",
|
||||
"report": "three_way_compare.sql",
|
||||
"commit_to_branch": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"actor": "${{ github.actor }}",
|
||||
"issue_id": "${{ steps.get_pull_number.outputs.pull_number }}"
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
name: Import Benchmarks
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ benchmark-import ]
|
||||
env:
|
||||
BENCH_DIR: 'go/performance/import_benchmarker'
|
||||
MYSQL_PORT: 3309
|
||||
MYSQL_PASSWORD: password
|
||||
jobs:
|
||||
bench:
|
||||
name: Benchmark
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
strategy:
|
||||
fail-fast: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.version }}
|
||||
|
||||
- name: Set up Go 1.x
|
||||
id: go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
|
||||
- name: Dolt version
|
||||
id: version
|
||||
run: |
|
||||
version=${{ github.event.client_payload.version }}
|
||||
|
||||
- name: Install dolt
|
||||
working-directory: ./go
|
||||
run: go install ./cmd/dolt
|
||||
|
||||
- uses: shogo82148/actions-setup-mysql@v1
|
||||
with:
|
||||
mysql-version: '8.0'
|
||||
auto-start: true
|
||||
root-password: ${{ env.MYSQL_PASSWORD }}
|
||||
my-cnf: |
|
||||
local_infile=1
|
||||
socket=/tmp/mysqld2.sock
|
||||
port=${{ env.MYSQL_PORT }}
|
||||
|
||||
- name: Setup MySQL
|
||||
run: mysql -uroot -p${{ env.MYSQL_PASSWORD }} -h127.0.0.1 -P${{ env.MYSQL_PORT }} -e 'create database test;'
|
||||
|
||||
- name: Run bench
|
||||
id: bench
|
||||
working-directory: go/
|
||||
run: |
|
||||
out="$GITHUB_WORKSPACE/results.sql"
|
||||
testspec="../${{ env.BENCH_DIR }}/testdata/${{ github.event.client_payload.run_file }}"
|
||||
go run \
|
||||
"github.com/dolthub/dolt/${{ env.BENCH_DIR }}/cmd" \
|
||||
-test "$testspec" \
|
||||
-out "$out"
|
||||
echo "result_path=$out" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report
|
||||
id: report
|
||||
run: |
|
||||
gw=$GITHUB_WORKSPACE
|
||||
in="${{ steps.bench.outputs.result_path }}"
|
||||
query="$(pwd)/${{ env.BENCH_DIR }}/reporting/${{ github.event.client_payload.report }}"
|
||||
summaryq="$(pwd)/${{ env.BENCH_DIR }}/reporting/${{ github.event.client_payload.summary }}"
|
||||
|
||||
out="$gw/results.csv"
|
||||
dolt_dir="$gw/import-perf"
|
||||
|
||||
dolt config --global --add user.email "import-perf@dolthub.com"
|
||||
dolt config --global --add user.name "import-perf"
|
||||
|
||||
echo '${{ secrets.DOLTHUB_IMPORT_PERF_CREDS_VALUE }}' | dolt creds import
|
||||
dolt clone import-perf/import-perf "$dolt_dir"
|
||||
|
||||
cd "$dolt_dir"
|
||||
|
||||
branch="${{ github.event.client_payload.commit_to_branch }}"
|
||||
# checkout branch
|
||||
if [ -z $(dolt sql -q "select 1 from dolt_branches where name = '$branch';") ]; then
|
||||
dolt checkout -b $branch
|
||||
else
|
||||
dolt checkout $branch
|
||||
fi
|
||||
|
||||
dolt sql -q "drop table if exists import_perf_results"
|
||||
|
||||
# load results
|
||||
dolt sql < "$in"
|
||||
|
||||
# push results to dolthub
|
||||
dolt add import_perf_results
|
||||
dolt commit -m "CI commit"
|
||||
dolt push -f origin $branch
|
||||
|
||||
# generate report
|
||||
dolt sql -r csv < "$query" > "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "report_path=$out" >> $GITHUB_OUTPUT
|
||||
|
||||
avg=$(dolt sql -r csv < "$summaryq" | tail -1)
|
||||
echo "avg=$avg" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Format HTML
|
||||
id: html
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
run: |
|
||||
gw="$GITHUB_WORKSPACE"
|
||||
in="${{ steps.report.outputs.report_path }}"
|
||||
out="$gw/results.html"
|
||||
|
||||
echo "<table>" > "$out"
|
||||
print_header=true
|
||||
while read line; do
|
||||
if "$print_header"; then
|
||||
echo " <tr><th>${line//,/</th><th>}</th></tr>" >> "$out"
|
||||
print_header=false
|
||||
continue
|
||||
fi
|
||||
echo " <tr><td>${line//,/</td><td>}</td></tr>" >> "$out"
|
||||
done < "$in"
|
||||
echo "</table>" >> "$out"
|
||||
|
||||
avg="${{ steps.report.outputs.avg }}"
|
||||
echo "<table><tr><th>Average</th></tr><tr><td>$avg</tr></td></table>" >> "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "html=$(echo $out)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Send Email
|
||||
uses: ./.github/actions/ses-email-action
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
with:
|
||||
region: us-west-2
|
||||
toAddresses: '["${{ github.event.client_payload.email_recipient }}"]'
|
||||
subject: 'Import Performance Benchmarks: ${{ github.event.client_payload.version }}'
|
||||
bodyPath: ${{ steps.html.outputs.html }}
|
||||
template: 'SysbenchTemplate'
|
||||
|
||||
- name: Read CSV
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
id: csv
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: "${{ steps.report.outputs.report_path }}"
|
||||
|
||||
- name: Create MD
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
uses: dolthub/csv-to-md-table-action@v4
|
||||
id: md
|
||||
with:
|
||||
csvinput: ${{ steps.csv.outputs.content }}
|
||||
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue: ${{ github.event.client_payload.issue_id }}
|
||||
message-failure: import benchmark failed
|
||||
message-cancelled: import benchmark cancelled
|
||||
allow-repeats: true
|
||||
message: |
|
||||
@${{ github.event.client_payload.actor }} __DOLT__
|
||||
${{ steps.md.outputs.markdown-table }}
|
||||
@@ -0,0 +1,74 @@
|
||||
name: Benchmark Latency
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ benchmark-latency ]
|
||||
|
||||
jobs:
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Benchmark Performance
|
||||
strategy:
|
||||
matrix:
|
||||
dolt_fmt: [ "__DOLT__" ]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: 'v1.23.6'
|
||||
- name: Install aws-iam-authenticator
|
||||
run: |
|
||||
curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \
|
||||
chmod +x ./aws-iam-authenticator && \
|
||||
sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
|
||||
aws-iam-authenticator version
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Create and Auth kubeconfig
|
||||
run: |
|
||||
echo "$CONFIG" > kubeconfig
|
||||
KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1
|
||||
KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=performance-benchmarking
|
||||
KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context
|
||||
env:
|
||||
CONFIG: ${{ secrets.CORP_KUBECONFIG }}
|
||||
- name: Create Sysbench Performance Benchmarking K8s Job
|
||||
run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh
|
||||
env:
|
||||
FROM_SERVER: ${{ github.event.client_payload.from_server }}
|
||||
FROM_VERSION: ${{ github.event.client_payload.from_version }}
|
||||
TO_SERVER: ${{ github.event.client_payload.to_server }}
|
||||
TO_VERSION: ${{ github.event.client_payload.to_version }}
|
||||
TO_PROFILE_KEY: ${{ github.event.client_payload.to_profile_key }}
|
||||
MODE: ${{ github.event.client_payload.mode }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }}
|
||||
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
KUBECONFIG: "./kubeconfig"
|
||||
INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }}
|
||||
NOMS_BIN_FORMAT: ${{ matrix.dolt_fmt }}
|
||||
SYSBENCH_TEST_TIME: ${{ github.event.client_payload.sysbench_test_time }}
|
||||
TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}
|
||||
- name: Create TPCC Performance Benchmarking K8s Job
|
||||
run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh
|
||||
env:
|
||||
FROM_SERVER: ${{ github.event.client_payload.from_server }}
|
||||
FROM_VERSION: ${{ github.event.client_payload.from_version }}
|
||||
TO_SERVER: ${{ github.event.client_payload.to_server }}
|
||||
TO_VERSION: ${{ github.event.client_payload.to_version }}
|
||||
MODE: ${{ github.event.client_payload.mode }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }}
|
||||
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
KUBECONFIG: "./kubeconfig"
|
||||
INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }}
|
||||
NOMS_BIN_FORMAT: ${{ matrix.dolt_fmt }}
|
||||
WITH_TPCC: "true"
|
||||
TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}
|
||||
@@ -0,0 +1,51 @@
|
||||
name: Profile Dolt while Benchmarking
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ profile-dolt ]
|
||||
|
||||
jobs:
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Profile Dolt while Benchmarking
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: 'v1.23.6'
|
||||
- name: Install aws-iam-authenticator
|
||||
run: |
|
||||
curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \
|
||||
chmod +x ./aws-iam-authenticator && \
|
||||
sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
|
||||
aws-iam-authenticator version
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Create and Auth kubeconfig
|
||||
run: |
|
||||
echo "$CONFIG" > kubeconfig
|
||||
KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1
|
||||
KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=performance-benchmarking
|
||||
KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context
|
||||
env:
|
||||
CONFIG: ${{ secrets.CORP_KUBECONFIG }}
|
||||
- name: Create Profile Benchmarking K8s Job
|
||||
run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh
|
||||
env:
|
||||
PROFILE: "true"
|
||||
FUTURE_VERSION: ${{ github.event.client_payload.future_version }}
|
||||
FROM_VERSION: ${{ github.event.client_payload.from_version }}
|
||||
MODE: ${{ github.event.client_payload.mode }}
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }}
|
||||
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
KUBECONFIG: "./kubeconfig"
|
||||
INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }}
|
||||
NOMS_BIN_FORMAT: "__DOLT__"
|
||||
TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}
|
||||
BRANCH: ${{ github.event.client_payload.branch || 'main' }}
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Fuzzer
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'go/**'
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
fuzzer:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Fuzzer
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: 'v1.23.6'
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Install aws-iam-authenticator
|
||||
run: |
|
||||
curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \
|
||||
chmod +x ./aws-iam-authenticator && \
|
||||
sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
|
||||
aws-iam-authenticator version
|
||||
- name: Create and Auth kubeconfig
|
||||
run: |
|
||||
echo "$CONFIG" > kubeconfig
|
||||
KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1
|
||||
KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=fuzzer
|
||||
KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context
|
||||
env:
|
||||
CONFIG: ${{ secrets.CORP_KUBECONFIG }}
|
||||
- name: Create Fuzzer (GateKeeper) K8s Job
|
||||
run: ./.github/scripts/fuzzer/run-fuzzer.sh
|
||||
env:
|
||||
VERSION: ${{ github.sha }}
|
||||
ACTOR: "Hydrocharged"
|
||||
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
KUBECONFIG: "./kubeconfig"
|
||||
TEMPLATE_SCRIPT: "./.github/scripts/fuzzer/get-fuzzer-job-json.sh"
|
||||
@@ -0,0 +1,52 @@
|
||||
name: SQL Correctness
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ sql-correctness ]
|
||||
|
||||
jobs:
|
||||
correctness:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Dolt SQL Correctness
|
||||
strategy:
|
||||
matrix:
|
||||
dolt_fmt: [ "__DOLT__" ]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: azure/setup-kubectl@v4
|
||||
with:
|
||||
version: 'v1.23.6'
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Install aws-iam-authenticator
|
||||
run: |
|
||||
curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \
|
||||
chmod +x ./aws-iam-authenticator && \
|
||||
sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
|
||||
aws-iam-authenticator version
|
||||
- name: Create and Auth kubeconfig
|
||||
run: |
|
||||
echo "$CONFIG" > kubeconfig
|
||||
KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1
|
||||
KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=performance-benchmarking
|
||||
KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context
|
||||
env:
|
||||
CONFIG: ${{ secrets.CORP_KUBECONFIG }}
|
||||
- name: Create SQL Correctness K8s Job
|
||||
run: ./.github/scripts/sql-correctness/run-correctness.sh
|
||||
env:
|
||||
PR_BRANCH_REF: ${{ github.event.client_payload.branch_ref }}
|
||||
REGRESS_COMP: ${{ github.event.client_payload.regress_comp }}
|
||||
PR_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
VERSION: ${{ github.event.client_payload.version }}
|
||||
MODE: ${{ github.event.client_payload.mode }}
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }}
|
||||
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
KUBECONFIG: "./kubeconfig"
|
||||
NOMS_BIN_FORMAT: ${{ matrix.dolt_fmt }}
|
||||
TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}
|
||||
@@ -0,0 +1,19 @@
|
||||
name: Label Customer Issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request_target:
|
||||
branches: [main]
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
label_customer_issues:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dolthub/label-customer-issues@main
|
||||
with:
|
||||
repo-token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
issue-label: customer issue
|
||||
pr-label: contribution
|
||||
exclude: dependabot
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Run Merge Benchmark on Pull Requests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened ]
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
validate-commentor:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
valid: ${{ steps.set_valid.outputs.valid }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Validate Commentor
|
||||
id: set_valid
|
||||
run: ./.github/scripts/performance-benchmarking/validate-commentor.sh "$ACTOR"
|
||||
env:
|
||||
ACTOR: ${{ github.actor }}
|
||||
|
||||
check-comments:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: validate-commentor
|
||||
if: ${{ needs.validate-commentor.outputs.valid == 'true' }}
|
||||
outputs:
|
||||
benchmark: ${{ steps.set_benchmark.outputs.benchmark }}
|
||||
comment-body: ${{ steps.set_body.outputs.body }}
|
||||
steps:
|
||||
- name: Check for Deploy Trigger
|
||||
uses: dolthub/pull-request-comment-trigger@v2
|
||||
id: check
|
||||
with:
|
||||
trigger: '#merge-benchmark'
|
||||
reaction: rocket
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set Benchmark
|
||||
if: ${{ steps.check.outputs.triggered == 'true' }}
|
||||
id: set_benchmark
|
||||
run: |
|
||||
echo "benchmark=true" >> $GITHUB_OUTPUT
|
||||
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate-commentor, check-comments]
|
||||
if: ${{ needs.check-comments.outputs.benchmark == 'true' }}
|
||||
name: Trigger Benchmark Merge Workflow
|
||||
steps:
|
||||
- uses: dolthub/pull-request-comment-branch@v3
|
||||
id: comment-branch
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get pull number
|
||||
uses: actions/github-script@v7
|
||||
id: get_pull_number
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: core.setOutput("pull_number", JSON.stringify(context.issue.number));
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-merge
|
||||
client-payload: |
|
||||
{
|
||||
"version": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"commit_to_branch": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"actor": "${{ github.actor }}",
|
||||
"issue_id": "${{ steps.get_pull_number.outputs.pull_number }}"
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
name: Merge Benchmarks
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ benchmark-merge ]
|
||||
env:
|
||||
SCRIPT_DIR: '.github/scripts/merge-perf'
|
||||
RESULT_TABLE_NAME: 'merge_perf_results'
|
||||
DOLTHUB_DB: 'import-perf/merge-perf'
|
||||
jobs:
|
||||
bench:
|
||||
name: Benchmark
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
strategy:
|
||||
fail-fast: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.version }}
|
||||
|
||||
- name: Set up Go 1.x
|
||||
id: go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
|
||||
- name: Setup Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Dolt version
|
||||
id: version
|
||||
run: |
|
||||
version=${{ github.event.client_payload.version }}
|
||||
|
||||
- name: Install dolt
|
||||
working-directory: ./go
|
||||
run: go install ./cmd/dolt
|
||||
|
||||
- name: Config dolt
|
||||
id: config
|
||||
run: |
|
||||
dolt config --global --add user.email "merge-perf@dolthub.com"
|
||||
dolt config --global --add user.name "merge-perf"
|
||||
|
||||
- name: Run bench
|
||||
id: bench
|
||||
run: |
|
||||
gw=$GITHUB_WORKSPACE
|
||||
DATADIR=$gw/data
|
||||
|
||||
# initialize results sql import
|
||||
RESULTS=$gw/results.sql
|
||||
echo "CREATE TABLE ${{env.RESULT_TABLE_NAME }} (name varchar(50) primary key, table_cnt int, run_cnt int, add_cnt int, delete_cnt int, update_cnt int, conflict_cnt int, fks bool, latency float);" >> $RESULTS
|
||||
|
||||
# parameters for testing
|
||||
ROW_NUM=1000000
|
||||
TABLE_NUM=2
|
||||
EDIT_CNT=60000
|
||||
names=('adds_only' 'deletes_only' 'updates_only' 'adds_updates_deletes')
|
||||
adds=($EDIT_CNT 0 0 $EDIT_CNT)
|
||||
deletes=(0 $EDIT_CNT 0 $EDIT_CNT)
|
||||
updates=(0 0 $EDIT_CNT $EDIT_CNT)
|
||||
|
||||
wd=$(pwd)
|
||||
for i in {0..3}; do
|
||||
cd $wd
|
||||
echo "${names[$i]}, ${adds[$i]}, ${deletes[$i]}, ${updates[$i]}"
|
||||
|
||||
# data.py creates files for import
|
||||
python ${{ env.SCRIPT_DIR }}/data.py $DATADIR $TABLE_NUM $ROW_NUM ${adds[$i]} ${deletes[$i]} ${updates[$i]}
|
||||
|
||||
# setup.sh runs the import and commit process for a set of data files
|
||||
TMPDIR=$gw/tmp
|
||||
./${{ env.SCRIPT_DIR}}/setup.sh $TMPDIR $DATADIR
|
||||
|
||||
# small python script times merge, we suppress errcodes but print error messages
|
||||
cd $TMPDIR
|
||||
python3 -c "import time, subprocess, sys; start = time.time(); res=subprocess.run(['dolt', 'merge', '--squash', 'main'], capture_output=True); err = res.stdout + res.stderr if res.returncode != 0 else ''; latency = time.time() -start; print(latency); sys.stderr.write(str(err))" 1> lat.log 2>err.log
|
||||
latency=$(cat lat.log)
|
||||
cat err.log
|
||||
|
||||
# count conflicts in first table
|
||||
conflicts=$(dolt sql -r csv -q "select count(*) from dolt_conflicts_table0;" | tail -1)
|
||||
|
||||
echo "INSERT INTO ${{ env.RESULT_TABLE_NAME }} values ('"${names[$i]}"', $TABLE_NUM, $ROW_NUM, ${adds[$i]}, ${deletes[$i]}, ${updates[$i]}, $conflicts, true, $latency);" >> $RESULTS
|
||||
done
|
||||
echo "result_path=$RESULTS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report
|
||||
id: report
|
||||
run: |
|
||||
gw=$GITHUB_WORKSPACE
|
||||
in="${{ steps.bench.outputs.result_path }}"
|
||||
query="select name, add_cnt, delete_cnt, update_cnt, round(latency, 2) as latency from ${{ env.RESULT_TABLE_NAME }}"
|
||||
summaryq="select round(avg(latency), 2) as avg from ${{ env.RESULT_TABLE_NAME }}"
|
||||
|
||||
out="$gw/results.csv"
|
||||
dolt_dir="$gw/merge-perf"
|
||||
|
||||
dolt config --global --add user.email "merge-perf@dolthub.com"
|
||||
dolt config --global --add user.name "merge-perf"
|
||||
|
||||
echo '${{ secrets.DOLTHUB_IMPORT_PERF_CREDS_VALUE }}' | dolt creds import
|
||||
dolt clone ${{ env.DOLTHUB_DB }} "$dolt_dir"
|
||||
|
||||
cd "$dolt_dir"
|
||||
|
||||
branch="${{ github.event.client_payload.commit_to_branch }}"
|
||||
# checkout branch
|
||||
if [ -z $(dolt sql -q "select 1 from dolt_branches where name = '$branch';") ]; then
|
||||
dolt checkout -b $branch
|
||||
else
|
||||
dolt checkout $branch
|
||||
fi
|
||||
|
||||
dolt sql -q "drop table if exists ${{ env.RESULT_TABLE_NAME }}"
|
||||
|
||||
# load results
|
||||
dolt sql < "$in"
|
||||
|
||||
# push results to dolthub
|
||||
dolt add ${{ env.RESULT_TABLE_NAME }}
|
||||
dolt commit -m "CI commit"
|
||||
dolt push -f origin $branch
|
||||
|
||||
# generate report
|
||||
dolt sql -r csv -q "$query" > "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "report_path=$out" >> $GITHUB_OUTPUT
|
||||
|
||||
avg=$(dolt sql -r csv -q "$summaryq" | tail -1)
|
||||
echo "avg=$avg" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Format Results
|
||||
id: html
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
run: |
|
||||
gw="$GITHUB_WORKSPACE"
|
||||
in="${{ steps.report.outputs.report_path }}"
|
||||
out="$gw/results.html"
|
||||
|
||||
echo "<table>" > "$out"
|
||||
print_header=true
|
||||
while read line; do
|
||||
if "$print_header"; then
|
||||
echo " <tr><th>${line//,/</th><th>}</th></tr>" >> "$out"
|
||||
print_header=false
|
||||
continue
|
||||
fi
|
||||
echo " <tr><td>${line//,/</td><td>}</td></tr>" >> "$out"
|
||||
done < "$in"
|
||||
echo "</table>" >> "$out"
|
||||
|
||||
avg="${{ steps.report.outputs.avg }}"
|
||||
echo "<table><tr><th>Average</th></tr><tr><td>$avg</tr></td></table>" >> "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "html=$(echo $out)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Send Email
|
||||
uses: ./.github/actions/ses-email-action
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
with:
|
||||
region: us-west-2
|
||||
toAddresses: '["${{ github.event.client_payload.email_recipient }}"]'
|
||||
subject: 'Merge Performance Benchmarks: ${{ github.event.client_payload.version }}'
|
||||
bodyPath: ${{ steps.html.outputs.html }}
|
||||
template: 'SysbenchTemplate'
|
||||
|
||||
- name: Read CSV
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
id: csv
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: "${{ steps.report.outputs.report_path }}"
|
||||
|
||||
- name: Create MD
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
uses: dolthub/csv-to-md-table-action@v4
|
||||
id: md
|
||||
with:
|
||||
csvinput: ${{ steps.csv.outputs.content }}
|
||||
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue: ${{ github.event.client_payload.issue_id }}
|
||||
message-failure: merge benchmark failed
|
||||
message-cancelled: merge benchmark cancelled
|
||||
allow-repeats: true
|
||||
message: |
|
||||
@${{ github.event.client_payload.actor }} __DOLT__
|
||||
${{ steps.md.outputs.markdown-table }}
|
||||
@@ -0,0 +1,65 @@
|
||||
name: Nightly Benchmarks
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
jobs:
|
||||
perf:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Trigger Benchmark Latency, Benchmark Import, and SQL Correctness K8s Workflows
|
||||
steps:
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-latency
|
||||
client-payload: '{"from_server": "mysql", "from_version": "8.0.35", "to_server": "dolt", "to_version": "${{ github.sha }}", "mode": "nightly", "actor": "${{ github.actor }}", "template_script": "./.github/scripts/performance-benchmarking/get-mysql-dolt-job-json.sh"}'
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: sql-correctness
|
||||
client-payload: '{"version": "${{ github.sha }}", "mode": "nightly", "actor": "${{ github.actor }}", "template_script": "./.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh"}'
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-import
|
||||
client-payload: |
|
||||
{
|
||||
"email_recipient": "${{ secrets.PERF_REPORTS_EMAIL_ADDRESS }}",
|
||||
"version": "${{ github.sha }}",
|
||||
"run_file": "ci.yaml",
|
||||
"summary": "summary.sql",
|
||||
"report": "three_way_compare.sql",
|
||||
"commit_to_branch": "nightly",
|
||||
"actor": "${{ github.actor }}"
|
||||
}
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: test-orm-integrations
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-systab
|
||||
client-payload: |
|
||||
{
|
||||
"email_recipient": "${{ secrets.PERF_REPORTS_EMAIL_ADDRESS }}",
|
||||
"version": "${{ github.sha }}",
|
||||
"run_file": "systab.yaml",
|
||||
"report": "systab.sql",
|
||||
"summary": "systab_summary.sql",
|
||||
"commit_to_branch": "nightly",
|
||||
"actor": "${{ github.actor }}"
|
||||
}
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-merge
|
||||
client-payload: |
|
||||
{
|
||||
"email_recipient": "${{ secrets.PERF_REPORTS_EMAIL_ADDRESS }}",
|
||||
"version": "${{ github.sha }}",
|
||||
"commit_to_branch": "nightly",
|
||||
"actor": "${{ github.actor }}"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Benchmark Dolt vs MySQL
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ release-dolt ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
default: ''
|
||||
email:
|
||||
description: 'Email address to receive results'
|
||||
required: true
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
set-version-actor:
|
||||
name: Set Version and Actor
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.set-vars.outputs.version }}
|
||||
actor: ${{ steps.set-vars.outputs.actor }}
|
||||
actor_email: ${{ steps.set-vars.outputs.actor_email }}
|
||||
steps:
|
||||
- name: Set variables
|
||||
id: set-vars
|
||||
run: |
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "actor=$ACTOR" >> $GITHUB_OUTPUT
|
||||
echo "actor_email=$ACTOR_EMAIL" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
VERSION: ${{ github.event.inputs.version || github.event.client_payload.version }}
|
||||
ACTOR: ${{ github.event.client_payload.actor || github.actor }}
|
||||
ACTOR_EMAIL: ${{ github.event.inputs.email }}
|
||||
|
||||
benchmark-dolt-mysql:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: set-version-actor
|
||||
name: Trigger Benchmark Latency and Benchmark Import K8s Workflows
|
||||
steps:
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
if: ${{ github.event.client_payload.profile_key == '' }}
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-latency
|
||||
client-payload: '{"from_server": "mysql", "from_version": "8.0.35", "to_server": "dolt", "to_version": "${{ needs.set-version-actor.outputs.version }}", "mode": "release", "actor": "${{ needs.set-version-actor.outputs.actor }}", "actor_email": "${{ needs.set-version-actor.outputs.actor_email }}", "template_script": "./.github/scripts/performance-benchmarking/get-mysql-dolt-job-json.sh"}'
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
if: ${{ github.event.client_payload.profile_key != '' }}
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-latency
|
||||
client-payload: '{"from_server": "mysql", "from_version": "8.0.35", "to_server": "dolt", "to_version": "${{ needs.set-version-actor.outputs.version }}", "profile_key": "${{ github.event.client_payload.profile_key }}", "mode": "release", "actor": "${{ needs.set-version-actor.outputs.actor }}", "actor_email": "${{ needs.set-version-actor.outputs.actor_email }}", "template_script": "./.github/scripts/performance-benchmarking/get-mysql-dolt-job-json.sh"}'
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-import
|
||||
client-payload: |
|
||||
{
|
||||
"email_recipient": "${{ needs.set-version-actor.outputs.actor_email }}",
|
||||
"version": "${{ github.sha }}",
|
||||
"run_file": "ci.yaml",
|
||||
"report": "three_way_compare.sql",
|
||||
"summary": "summary.sql",
|
||||
"commit_to_branch": "main",
|
||||
"actor": "${{ github.actor }}"
|
||||
}
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-systab
|
||||
client-payload: |
|
||||
{
|
||||
"email_recipient": "${{ needs.set-version-actor.outputs.actor_email }}",
|
||||
"version": "${{ github.sha }}",
|
||||
"run_file": "systab.yaml",
|
||||
"report": "systab.sql",
|
||||
"summary": "systab_summary.sql",
|
||||
"commit_to_branch": "main",
|
||||
"actor": "${{ github.actor }}"
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
name: Benchmark Pull Requests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened ]
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
validate-commentor:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
valid: ${{ steps.set_valid.outputs.valid }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Validate Commentor
|
||||
id: set_valid
|
||||
run: ./.github/scripts/performance-benchmarking/validate-commentor.sh "$ACTOR"
|
||||
env:
|
||||
ACTOR: ${{ github.actor }}
|
||||
|
||||
check-comments:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: validate-commentor
|
||||
if: ${{ needs.validate-commentor.outputs.valid == 'true' }}
|
||||
outputs:
|
||||
benchmark: ${{ steps.set_benchmark.outputs.benchmark }}
|
||||
sysbench-test-time: ${{ steps.set_benchmark_mini.outputs.sysbench-test-time }}
|
||||
comment-body: ${{ steps.set_body.outputs.body }}
|
||||
steps:
|
||||
- name: Check for Deploy Trigger
|
||||
uses: dolthub/pull-request-comment-trigger@v2
|
||||
id: check
|
||||
with:
|
||||
trigger: '#benchmark'
|
||||
reaction: rocket
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set Benchmark
|
||||
if: ${{ steps.check.outputs.triggered == 'true' }}
|
||||
id: set_benchmark
|
||||
run: |
|
||||
echo "benchmark=true" >> $GITHUB_OUTPUT
|
||||
- name: Check for Deploy Mini Trigger
|
||||
uses: dolthub/pull-request-comment-trigger@v2
|
||||
id: check_mini
|
||||
with:
|
||||
trigger: '#benchmark-mini'
|
||||
reaction: rocket
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set Benchmark Mini
|
||||
if: ${{ steps.check_mini.outputs.triggered == 'true' }}
|
||||
id: set_benchmark_mini
|
||||
run: |
|
||||
echo "benchmark=true" >> $GITHUB_OUTPUT
|
||||
echo "sysbench-test-time=20" >> $GITHUB_OUTPUT
|
||||
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate-commentor, check-comments]
|
||||
if: ${{ needs.check-comments.outputs.benchmark == 'true' }}
|
||||
name: Trigger Benchmark Latency K8s Workflow
|
||||
steps:
|
||||
- uses: dolthub/pull-request-comment-branch@v3
|
||||
id: comment-branch
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get pull number
|
||||
uses: actions/github-script@v7
|
||||
id: get_pull_number
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: core.setOutput("pull_number", JSON.stringify(context.issue.number));
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-latency
|
||||
client-payload: '{"from_server": "dolt", "from_version": "${{ github.sha }}", "to_server": "dolt", "to_version": "${{ steps.comment-branch.outputs.head_sha }}", "mode": "pullRequest", "issue_number": "${{ steps.get_pull_number.outputs.pull_number }}", "init_big_repo": "true", "actor": "${{ github.actor }}", "sysbench_test_time": "${{ needs.check-comments.outputs.sysbench-test-time }}", "template_script": "./.github/scripts/performance-benchmarking/get-dolt-dolt-job-json.sh"}'
|
||||
@@ -0,0 +1,293 @@
|
||||
name: Post to Pull Request
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ pull-report ]
|
||||
|
||||
jobs:
|
||||
report-pull-request:
|
||||
name: Report Performance Benchmarks/Correctness on Pull Request
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ github.event.client_payload.issue_number != -1 }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
- name: Print Correctness Info
|
||||
run: |
|
||||
echo "correctness info: is_regression: $IS_REGRESSION"
|
||||
echo "correctness info: correctness_percentage: $CORRECTNESS_PERCENTAGE"
|
||||
echo "correctness info: branch_ref: $BRANCH_REF"
|
||||
echo "job_type: $JOB_TYPE"
|
||||
env:
|
||||
IS_REGRESSION: ${{ github.event.client_payload.correctness_info.is_regression }}
|
||||
CORRECTNESS_PERCENTAGE: ${{ github.event.client_payload.correctness_info.correctness_percentage }}
|
||||
BRANCH_REF: ${{ github.event.client_payload.correctness_info.branch_ref }}
|
||||
JOB_TYPE: ${{ github.event.client_payload.job_type }}
|
||||
CORRECTNESS_REGRESSION: ${{ github.event.client_payload.correctness_info.is_regression == 'true' && github.event.client_payload.job_type == 'sql-correctness' }}
|
||||
- name: Get benchmark/correctness results
|
||||
id: get-results
|
||||
run: aws s3api get-object --bucket="$BUCKET" --key="$KEY" results.log
|
||||
env:
|
||||
KEY: ${{ github.event.client_payload.key }}
|
||||
BUCKET: ${{ github.event.client_payload.bucket }}
|
||||
- name: Post results to PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { ACTOR, FORMAT, ISSUE_NUMBER, JOB_TYPE, GITHUB_WORKSPACE } = process.env;
|
||||
const { owner, repo } = context.repo;
|
||||
const issue_number = parseInt(ISSUE_NUMBER, 10);
|
||||
|
||||
const fs = require('fs').promises;
|
||||
const resData = await fs.readFile(`${GITHUB_WORKSPACE}/results.log`, 'utf8');
|
||||
|
||||
// Consider also deleting stale sql-correctness comments
|
||||
// Both correctness and performance are posted/deleted here, they may delete each other
|
||||
if (JOB_TYPE == "performance-benchmarking") {
|
||||
const commentMarker = '<!-- go-run-output -->';
|
||||
|
||||
// List comments on the PR
|
||||
const { data: comments } = await github.rest.issues.listComments({
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo
|
||||
});
|
||||
|
||||
// Find correct comment to update
|
||||
let comment = null;
|
||||
if (resData.includes("tpcc-scale-factor-1")) {
|
||||
comment = comments.find(comment => comment.body.includes(commentMarker) && comment.body.includes("tpcc-scale-factor-1"))
|
||||
} else if (resData.includes("read_tests")) {
|
||||
comment = comments.find(comment => comment.body.includes(commentMarker) && comment.body.includes("read_tests"))
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
// Update the existing comment
|
||||
await github.rest.issues.updateComment({
|
||||
comment_id: comment.id,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `${commentMarker}\n@${ACTOR} ${FORMAT}\n${resData}`
|
||||
})
|
||||
} else {
|
||||
// Create a new comment
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `${commentMarker}\n@${ACTOR} ${FORMAT}\n${resData}`
|
||||
});
|
||||
}
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: issue_number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: `@${ACTOR} ${FORMAT}\n${resData}`
|
||||
});
|
||||
}
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
FORMAT: ${{ github.event.client_payload.noms_bin_format }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
JOB_TYPE: ${{ github.event.client_payload.job_type }}
|
||||
- name: Remove Passing Labels if regression detected
|
||||
if: ${{ github.event.client_payload.correctness_info.is_regression == true && github.event.client_payload.job_type == 'sql-correctness' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { ACTOR, ISSUE_NUMBER, LABEL, GITHUB_WORKSPACE } = process.env;
|
||||
const issue_number = parseInt(ISSUE_NUMBER, 10);
|
||||
const { owner, repo } = context.repo;
|
||||
try {
|
||||
const res = await github.rest.issues.listLabelsOnIssue({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
|
||||
if (res.data) {
|
||||
const labels = res.data;
|
||||
|
||||
for (const label of labels) {
|
||||
if (label.name === LABEL) {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
name: label.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
LABEL: 'correctness_approved'
|
||||
- name: Add Passing Labels if no regression detected
|
||||
if: ${{ github.event.client_payload.correctness_info.is_regression != true && github.event.client_payload.job_type == 'sql-correctness' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { ACTOR, ISSUE_NUMBER, LABEL, GITHUB_WORKSPACE } = process.env;
|
||||
const issue_number = parseInt(ISSUE_NUMBER, 10);
|
||||
const { owner, repo } = context.repo;
|
||||
try {
|
||||
const res = await github.rest.issues.listLabelsOnIssue({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
|
||||
if (res.data) {
|
||||
const labels = res.data;
|
||||
|
||||
for (const label of labels) {
|
||||
if (label.name === LABEL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
labels: [LABEL],
|
||||
});
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
LABEL: 'correctness_approved'
|
||||
- name: Remove Passing Performance Labels if performance regression detected
|
||||
if: ${{ github.event.client_payload.is_performance_regression == true && github.event.client_payload.job_type == 'performance-benchmarking' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { ACTOR, ISSUE_NUMBER, LABEL, GITHUB_WORKSPACE } = process.env;
|
||||
const issue_number = parseInt(ISSUE_NUMBER, 10);
|
||||
const { owner, repo } = context.repo;
|
||||
try {
|
||||
const res = await github.rest.issues.listLabelsOnIssue({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
|
||||
if (res.data) {
|
||||
const labels = res.data;
|
||||
|
||||
for (const label of labels) {
|
||||
if (label.name === LABEL) {
|
||||
await github.rest.issues.removeLabel({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
name: label.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
LABEL: 'performance_approved'
|
||||
- name: Add Passing Performance Labels if no regression detected
|
||||
if: ${{ github.event.client_payload.is_performance_regression != true && github.event.client_payload.job_type == 'performance-benchmarking' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { ACTOR, ISSUE_NUMBER, LABEL, GITHUB_WORKSPACE } = process.env;
|
||||
const issue_number = parseInt(ISSUE_NUMBER, 10);
|
||||
const { owner, repo } = context.repo;
|
||||
try {
|
||||
const res = await github.rest.issues.listLabelsOnIssue({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
});
|
||||
|
||||
if (res.data) {
|
||||
const labels = res.data;
|
||||
|
||||
for (const label of labels) {
|
||||
if (label.name === LABEL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await github.rest.issues.addLabels({
|
||||
issue_number,
|
||||
owner,
|
||||
repo,
|
||||
labels: [LABEL],
|
||||
});
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor }}
|
||||
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
|
||||
LABEL: 'performance_approved'
|
||||
|
||||
update-correctness-file:
|
||||
name: Update Correctness File
|
||||
needs: report-pull-request
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ github.event.client_payload.correctness_info.is_regression != 'true' && github.event.client_payload.job_type == 'sql-correctness' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.correctness_info.branch_ref }}
|
||||
repository: ${{ github.repository }}
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Write new correctness file
|
||||
working-directory: ./.github/scripts/sql-correctness
|
||||
env:
|
||||
CORRECTNESS_PERCENTAGE: ${{ github.event.client_payload.correctness_info.correctness_percentage }}
|
||||
run: |
|
||||
if [ -z "$CORRECTNESS_PERCENTAGE" ]; then
|
||||
echo "correctness percentage was empty, something went wrong"
|
||||
exit 1
|
||||
fi
|
||||
echo "$CORRECTNESS_PERCENTAGE" > current_correctness.txt
|
||||
- name: Changes detected
|
||||
id: detect-changes
|
||||
run: |
|
||||
changes=$(git status --porcelain)
|
||||
if [ ! -z "$changes" ]; then
|
||||
echo "has-changes=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- uses: EndBug/add-and-commit@v9.1.4
|
||||
if: ${{ steps.detect-changes.outputs.has-changes == 'true' }}
|
||||
with:
|
||||
message: ${{ format('[skip actions] [ga-update-correctness] SQL Correctness updated to {0}', github.event.client_payload.correctness_info.correctness_percentage) }}
|
||||
add: "./current_correctness.txt"
|
||||
cwd: "./.github/scripts/sql-correctness"
|
||||
pull: "--ff"
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Benchmark SQL Correctness
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ release-dolt ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'SemVer format release tag, i.e. 0.24.5'
|
||||
required: true
|
||||
default: ''
|
||||
email:
|
||||
description: 'Email address to receive results'
|
||||
required: true
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
set-version-actor:
|
||||
name: Set Version and Actor
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
version: ${{ steps.set-vars.outputs.version }}
|
||||
actor: ${{ steps.set-vars.outputs.actor }}
|
||||
steps:
|
||||
- name: Set variables
|
||||
id: set-vars
|
||||
run: |
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "actor=$ACTOR" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
VERSION: ${{ github.event.inputs.version || github.event.client_payload.version }}
|
||||
ACTOR: ${{ github.event.client_payload.actor || github.actor }}
|
||||
|
||||
correctness:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: set-version-actor
|
||||
name: Trigger SQL Correctness K8s Workflow
|
||||
steps:
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: sql-correctness
|
||||
client-payload: '{"version": "${{ needs.set-version-actor.outputs.version }}", "mode": "release", "actor": "${{ needs.set-version-actor.outputs.actor }}", "actor_email": "${{ needs.set-version-actor.outputs.actor_email }}", "template_script": "./.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh"}'
|
||||
@@ -0,0 +1,57 @@
|
||||
name: Benchmark SQL Correctness on PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
set-version-actor:
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
name: Set Version and Actor
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
regress_comp: ${{ steps.regress-comp.outputs.regress_comp }}
|
||||
version: ${{ steps.set-vars.outputs.version }}
|
||||
actor: ${{ steps.set-vars.outputs.actor }}
|
||||
steps:
|
||||
- name: Checkout BASE REF
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.base_ref }}
|
||||
- name: Get Current Correctness
|
||||
id: regress-comp
|
||||
working-directory: ./.github/scripts/sql-correctness
|
||||
run: |
|
||||
out=$(cat current_correctness.txt)
|
||||
echo "regress_comp=$out" >> $GITHUB_OUTPUT
|
||||
- name: Checkout PR HEAD REF
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
- name: Set variables
|
||||
id: set-vars
|
||||
run: |
|
||||
echo "actor=$ACTOR" >> $GITHUB_OUTPUT
|
||||
sha=$(git rev-parse --short HEAD)
|
||||
echo "version=$sha" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
ACTOR: ${{ github.event.client_payload.actor || github.actor }}
|
||||
|
||||
correctness:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: set-version-actor
|
||||
name: Trigger SQL Correctness K8s Workflow
|
||||
steps:
|
||||
- name: Get pull number
|
||||
uses: actions/github-script@v7
|
||||
id: get_pull_number
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: core.setOutput("pull_number", JSON.stringify(context.issue.number));
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: sql-correctness
|
||||
client-payload: '{"issue_number": "${{ steps.get_pull_number.outputs.pull_number }}", "branch_ref": "${{ github.head_ref }}", "regress_comp": "${{ needs.set-version-actor.outputs.regress_comp }}", "version": "${{ needs.set-version-actor.outputs.version }}", "mode": "release", "actor": "${{ needs.set-version-actor.outputs.actor }}", "actor_email": "${{ needs.set-version-actor.outputs.actor_email }}", "template_script": "./.github/scripts/sql-correctness/get-dolt-correctness-job-json.sh"}'
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Run Systab Benchmark on Pull Requests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened ]
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
validate-commentor:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
valid: ${{ steps.set_valid.outputs.valid }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Validate Commentor
|
||||
id: set_valid
|
||||
run: ./.github/scripts/performance-benchmarking/validate-commentor.sh "$ACTOR"
|
||||
env:
|
||||
ACTOR: ${{ github.actor }}
|
||||
|
||||
check-comments:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: validate-commentor
|
||||
if: ${{ needs.validate-commentor.outputs.valid == 'true' }}
|
||||
outputs:
|
||||
benchmark: ${{ steps.set_benchmark.outputs.benchmark }}
|
||||
comment-body: ${{ steps.set_body.outputs.body }}
|
||||
steps:
|
||||
- name: Check for Deploy Trigger
|
||||
uses: dolthub/pull-request-comment-trigger@v2
|
||||
id: check
|
||||
with:
|
||||
trigger: '#systab-benchmark'
|
||||
reaction: rocket
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set Benchmark
|
||||
if: ${{ steps.check.outputs.triggered == 'true' }}
|
||||
id: set_benchmark
|
||||
run: |
|
||||
echo "benchmark=true" >> $GITHUB_OUTPUT
|
||||
|
||||
performance:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate-commentor, check-comments]
|
||||
if: ${{ needs.check-comments.outputs.benchmark == 'true' }}
|
||||
name: Trigger Benchmark Systab Workflow
|
||||
steps:
|
||||
- uses: dolthub/pull-request-comment-branch@v3
|
||||
id: comment-branch
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get pull number
|
||||
uses: actions/github-script@v7
|
||||
id: get_pull_number
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: core.setOutput("pull_number", JSON.stringify(context.issue.number));
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-systab
|
||||
client-payload: |
|
||||
{
|
||||
"version": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"run_file": "systab.yaml",
|
||||
"report": "systab.sql",
|
||||
"summary": "systab_summary.sql",
|
||||
"commit_to_branch": "${{ steps.comment-branch.outputs.head_sha }}",
|
||||
"actor": "${{ github.actor }}",
|
||||
"issue_id": "${{ steps.get_pull_number.outputs.pull_number }}"
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
name: Systab Benchmarks
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ benchmark-systab ]
|
||||
env:
|
||||
BENCH_DIR: 'go/performance/sysbench'
|
||||
RESULT_TABLE_NAME: 'sysbench_results'
|
||||
DOLTHUB_DB: 'import-perf/systab-perf'
|
||||
jobs:
|
||||
bench:
|
||||
name: Benchmark
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
strategy:
|
||||
fail-fast: true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.version }}
|
||||
|
||||
- name: Set up Go 1.x
|
||||
id: go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go/go.mod
|
||||
|
||||
- name: Dolt version
|
||||
id: version
|
||||
run: |
|
||||
version=${{ github.event.client_payload.version }}
|
||||
|
||||
- name: install sysbench
|
||||
run: |
|
||||
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.deb.sh | sudo bash
|
||||
sudo apt -y install sysbench
|
||||
|
||||
- name: Install dolt
|
||||
working-directory: ./go
|
||||
run: go install ./cmd/dolt
|
||||
|
||||
- name: Clone sysbench scripts
|
||||
run: |
|
||||
scripts=$GITHUB_WORKSPACE/scripts
|
||||
git clone https://github.com/dolthub/systab-sysbench-scripts.git "$scripts"
|
||||
|
||||
- name: Run bench
|
||||
id: bench
|
||||
working-directory: go/
|
||||
run: |
|
||||
out="$GITHUB_WORKSPACE/results.sql"
|
||||
testspec="../${{ env.BENCH_DIR }}/testdata/${{ github.event.client_payload.run_file }}"
|
||||
config="../${{ env.BENCH_DIR }}/testdata/default-config.yaml"
|
||||
scripts="$GITHUB_WORKSPACE/scripts"
|
||||
go run \
|
||||
"github.com/dolthub/dolt/${{ env.BENCH_DIR }}/cmd" \
|
||||
-run "$testspec" \
|
||||
-config "$config" \
|
||||
-script-dir "$scripts" \
|
||||
-out "$out"
|
||||
echo "result_path=$out" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Report
|
||||
id: report
|
||||
run: |
|
||||
gw=$GITHUB_WORKSPACE
|
||||
in="${{ steps.bench.outputs.result_path }}"
|
||||
query="$(pwd)/${{ env.BENCH_DIR }}/reporting/${{ github.event.client_payload.report }}"
|
||||
summaryq="$(pwd)/${{ env.BENCH_DIR }}/reporting/${{ github.event.client_payload.summary }}"
|
||||
|
||||
out="$gw/results.csv"
|
||||
dolt_dir="$gw/systab-perf"
|
||||
|
||||
dolt config --global --add user.email "systab-perf@dolthub.com"
|
||||
dolt config --global --add user.name "systab-perf"
|
||||
|
||||
echo '${{ secrets.DOLTHUB_IMPORT_PERF_CREDS_VALUE }}' | dolt creds import
|
||||
dolt clone ${{ env.DOLTHUB_DB }} "$dolt_dir"
|
||||
|
||||
cd "$dolt_dir"
|
||||
|
||||
branch="${{ github.event.client_payload.commit_to_branch }}"
|
||||
# checkout branch
|
||||
if [ -z $(dolt sql -q "select 1 from dolt_branches where name = '$branch';") ]; then
|
||||
dolt checkout -b $branch
|
||||
else
|
||||
dolt checkout $branch
|
||||
fi
|
||||
|
||||
dolt sql -q "drop table if exists sysbench_results"
|
||||
|
||||
# load results
|
||||
dolt sql < "$in"
|
||||
|
||||
# push results to dolthub
|
||||
dolt add sysbench_results
|
||||
dolt commit -m "CI commit"
|
||||
dolt push -f origin $branch
|
||||
|
||||
# generate report
|
||||
dolt sql -r csv < "$query" > "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "report_path=$out" >> $GITHUB_OUTPUT
|
||||
|
||||
avg=$(dolt sql -r csv < "$summaryq" | tail -1)
|
||||
echo "avg=$avg" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Format Results
|
||||
id: html
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
run: |
|
||||
gw="$GITHUB_WORKSPACE"
|
||||
in="${{ steps.report.outputs.report_path }}"
|
||||
out="$gw/results.html"
|
||||
|
||||
echo "<table>" > "$out"
|
||||
print_header=true
|
||||
while read line; do
|
||||
if "$print_header"; then
|
||||
echo " <tr><th>${line//,/</th><th>}</th></tr>" >> "$out"
|
||||
print_header=false
|
||||
continue
|
||||
fi
|
||||
echo " <tr><td>${line//,/</td><td>}</td></tr>" >> "$out"
|
||||
done < "$in"
|
||||
echo "</table>" >> "$out"
|
||||
|
||||
avg="${{ steps.report.outputs.avg }}"
|
||||
echo "<table><tr><th>Average</th></tr><tr><td>$avg</tr></td></table>" >> "$out"
|
||||
|
||||
cat "$out"
|
||||
echo "html=$(echo $out)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-west-2
|
||||
|
||||
- name: Send Email
|
||||
uses: ./.github/actions/ses-email-action
|
||||
if: ${{ github.event.client_payload.email_recipient }} != ""
|
||||
with:
|
||||
region: us-west-2
|
||||
toAddresses: '["${{ github.event.client_payload.email_recipient }}"]'
|
||||
subject: 'System Table Performance Benchmarks: ${{ github.event.client_payload.version }}'
|
||||
bodyPath: ${{ steps.html.outputs.html }}
|
||||
template: 'SysbenchTemplate'
|
||||
|
||||
- name: Read CSV
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
id: csv
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: "${{ steps.report.outputs.report_path }}"
|
||||
|
||||
- name: Create MD
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
uses: dolthub/csv-to-md-table-action@v4
|
||||
id: md
|
||||
with:
|
||||
csvinput: ${{ steps.csv.outputs.content }}
|
||||
|
||||
- uses: mshick/add-pr-comment@v2
|
||||
if: ${{ github.event.client_payload.issue_id }} != ""
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue: ${{ github.event.client_payload.issue_id }}
|
||||
message-failure: systab benchmark failed
|
||||
message-cancelled: systab benchmark cancelled
|
||||
allow-repeats: true
|
||||
message: |
|
||||
@${{ github.event.client_payload.actor }} __DOLT__
|
||||
${{ steps.md.outputs.markdown-table }}
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Benchmark Mini Sysbench Performance on PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'go/**'
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
performance:
|
||||
name: Trigger Mini Benchmark Latency K8s Workflow
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Build benchmark payload (main HEAD + PR HEAD)
|
||||
uses: actions/github-script@v7
|
||||
id: build_payload
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
// For PR benchmarks, use the PR base commit (the exact target commit this PR was opened/updated against),
|
||||
// not the moving HEAD of `main`.
|
||||
const fromSha = context.payload.pull_request.base.sha;
|
||||
|
||||
// The latest commit on the PR branch.
|
||||
const toSha = context.payload.pull_request.head.sha;
|
||||
|
||||
const payload = {
|
||||
from_server: "dolt",
|
||||
from_version: fromSha,
|
||||
to_server: "dolt",
|
||||
to_version: toSha,
|
||||
mode: "pullRequest",
|
||||
issue_number: String(context.issue.number),
|
||||
init_big_repo: "true",
|
||||
actor: context.actor,
|
||||
sysbench_test_time: "20",
|
||||
template_script: "./.github/scripts/performance-benchmarking/get-dolt-dolt-job-json.sh",
|
||||
};
|
||||
|
||||
core.setOutput("from_sha", fromSha);
|
||||
core.setOutput("to_sha", toSha);
|
||||
core.setOutput("payload", JSON.stringify(payload));
|
||||
- name: Log benchmark versions
|
||||
shell: bash
|
||||
run: |
|
||||
echo "from_version_sha=${{ steps.build_payload.outputs.from_sha }}"
|
||||
echo "to_version_sha=${{ steps.build_payload.outputs.to_sha }}"
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
event-type: benchmark-latency
|
||||
client-payload: ${{ steps.build_payload.outputs.payload }}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
**/.idea/
|
||||
**/.dolt/
|
||||
.vscode
|
||||
.run
|
||||
venv
|
||||
|
||||
.DS_Store
|
||||
.sqlhistory
|
||||
.doltcfg
|
||||
test.sh
|
||||
*eventsapi@*
|
||||
|
||||
# ignore cp'd sysbench runner testing files
|
||||
SysbenchDockerfile
|
||||
SysbenchDockerfile.dockerignore
|
||||
sysbench-runner-tests-entrypoint.sh
|
||||
config.json
|
||||
integration-tests/bats/batsee_results
|
||||
|
||||
# ignore CLAUDE.md for now
|
||||
CLAUDE.md
|
||||
|
||||
*~
|
||||
.dir-locals.el
|
||||
.beads
|
||||
.gitattributes
|
||||
|
||||
.de/
|
||||
.cursor
|
||||
AGENTS.md
|
||||
.claude/
|
||||
.cursorrules
|
||||
@@ -0,0 +1,4 @@
|
||||
[submodule "integration-tests/mysql-client-tests/cpp/third_party/mysql-connector-cpp"]
|
||||
path = integration-tests/mysql-client-tests/cpp/third_party/mysql-connector-cpp
|
||||
url = https://github.com/mysql/mysql-connector-cpp.git
|
||||
ignore = dirty
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Lines starting with '#' are comments.
|
||||
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# These owners will be the default owners for everything in the repo.
|
||||
|
||||
# * @defunkt
|
||||
|
||||
# Order is important. The last matching pattern has the most precedence.
|
||||
|
||||
# So if a pull request only touches javascript files, only these owners
|
||||
|
||||
# will be requested to review.
|
||||
|
||||
# *.js @octocat @github/js
|
||||
|
||||
# You can also use email addresses if you prefer.
|
||||
|
||||
# docs/* docs@example.com
|
||||
|
||||
# Begin dolt repository owners
|
||||
|
||||
integration-tests/mysql-client-tests/node/* @tbantle22
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,849 @@
|
||||
<img height="100" src="./images/Dolt-Logo@3x.svg"/>
|
||||
|
||||
# Dolt is Git for Data!
|
||||
|
||||
Dolt is a SQL database that you can fork, clone, branch, merge, push
|
||||
and pull just like a Git repository.
|
||||
|
||||
Connect to Dolt just like any MySQL database to read or modify schema
|
||||
and data. Version control functionality is exposed in SQL via system
|
||||
tables, functions, and procedures.
|
||||
|
||||
Or, use the Git-like command line interface to import CSV files, commit
|
||||
your changes, push them to a remote, or merge your teammate's changes.
|
||||
All the commands you know for Git work exactly the same for Dolt.
|
||||
|
||||
Git versions files. Dolt versions tables. It's like Git and MySQL had a
|
||||
baby.
|
||||
|
||||
We also built [DoltHub](https://www.dolthub.com), a place to share
|
||||
Dolt databases. We host public data for free. If you want to host
|
||||
your own version of DoltHub, we have [DoltLab](https://www.doltlab.com).
|
||||
If you want us to run a Dolt server for you, we have [Hosted Dolt](https://hosted.doltdb.com).
|
||||
|
||||
Prefer Postgres instead of MySQL? Try [Doltgres](https://github.com/dolthub/doltgresql), now
|
||||
in its Beta release.
|
||||
|
||||
[Join us on Discord](https://discord.com/invite/RFwfYpu) to say hi and
|
||||
ask questions, or [check out our roadmap](https://dolthub.com/docs/other/roadmap)
|
||||
to see what we're building next.
|
||||
|
||||
# Video Introduction
|
||||
|
||||
[](https://www.youtube.com/watch?v=H2iZy0Cme10)
|
||||
|
||||
# What's it for?
|
||||
|
||||
Lots of things! Dolt is a generally useful tool with countless
|
||||
applications. But if you want some ideas, [here's how people are using
|
||||
it so far](https://dolthub.com/blog/2024-10-15-dolt-use-cases/).
|
||||
|
||||
Dolt powers [Beads](https://github.com/gastownhall/beads) and
|
||||
[Gas Town](https://github.com/steveyegge/gastown). It's the best database
|
||||
for agent memory, especially as you move up the ladder to multi-agent and
|
||||
multi-machine workflows.
|
||||
|
||||
# Dolt CLI
|
||||
|
||||
The `dolt` CLI has the same commands as `git`, with some extras.
|
||||
|
||||
```
|
||||
$ dolt
|
||||
Valid commands for dolt are
|
||||
init - Create an empty Dolt data repository.
|
||||
status - Show the working tree status.
|
||||
add - Add table changes to the list of staged table changes.
|
||||
diff - Diff a table.
|
||||
reset - Remove table changes from the list of staged table changes.
|
||||
clean - Remove untracked tables from working set.
|
||||
commit - Record changes to the repository.
|
||||
sql - Run a SQL query against tables in repository.
|
||||
sql-server - Start a MySQL-compatible server.
|
||||
log - Show commit logs.
|
||||
branch - Create, list, edit, delete branches.
|
||||
checkout - Checkout a branch or overwrite a table from HEAD.
|
||||
merge - Merge a branch.
|
||||
conflicts - Commands for viewing and resolving merge conflicts.
|
||||
cherry-pick - Apply the changes introduced by an existing commit.
|
||||
revert - Undo the changes introduced in a commit.
|
||||
clone - Clone from a remote data repository.
|
||||
fetch - Update the database from a remote data repository.
|
||||
pull - Fetch from a dolt remote data repository and merge.
|
||||
push - Push to a dolt remote.
|
||||
config - Dolt configuration.
|
||||
remote - Manage set of tracked repositories.
|
||||
backup - Manage a set of server backups.
|
||||
login - Login to a dolt remote host.
|
||||
creds - Commands for managing credentials.
|
||||
ls - List tables in the working set.
|
||||
schema - Commands for showing and importing table schemas.
|
||||
table - Commands for copying, renaming, deleting, and exporting tables.
|
||||
tag - Create, list, delete tags.
|
||||
blame - Show what revision and author last modified each row of a table.
|
||||
constraints - Commands for handling constraints.
|
||||
migrate - Executes a database migration to use the latest Dolt data format.
|
||||
read-tables - Fetch table(s) at a specific commit into a new dolt repo
|
||||
gc - Cleans up unreferenced data from the repository.
|
||||
filter-branch - Edits the commit history using the provided query.
|
||||
merge-base - Find the common ancestor of two commits.
|
||||
version - Displays the current Dolt cli version.
|
||||
dump - Export all tables in the working set into a file.
|
||||
```
|
||||
|
||||
# Installation
|
||||
|
||||
Dolt is a single ~103 megabyte program.
|
||||
|
||||
```bash
|
||||
dolt $ du -h /Users/timsehn/go/bin/dolt
|
||||
103M /Users/timsehn/go/bin/dolt
|
||||
```
|
||||
|
||||
It's really easy to install. Download it and put it on your `PATH`.
|
||||
We have a bunch of ways to make this even easier for most platforms.
|
||||
|
||||
## From Latest Release
|
||||
|
||||
To install on Linux or Mac based systems run this command in your
|
||||
terminal:
|
||||
|
||||
```
|
||||
sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | bash'
|
||||
```
|
||||
|
||||
This will download the latest `dolt` release and put it in
|
||||
`/usr/local/bin/`, which is probably on your `$PATH`.
|
||||
|
||||
The install script needs sudo in order to put `dolt` in `/usr/local/bin`. If you don't have root
|
||||
privileges or aren't comfortable running a script with them, you can download the dolt binary
|
||||
for your platform from [the latest release](https://github.com/dolthub/dolt/releases), unzip it,
|
||||
and put the binary somewhere on your `$PATH`.
|
||||
|
||||
### Linux
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
Dolt is packaged in the official repositories for Arch Linux.
|
||||
|
||||
```
|
||||
pacman -S dolt
|
||||
```
|
||||
|
||||
### Mac
|
||||
|
||||
#### Homebrew
|
||||
|
||||
Dolt is on Homebrew, updated every release.
|
||||
|
||||
```
|
||||
brew install dolt
|
||||
```
|
||||
#### MacPorts
|
||||
|
||||
On macOS, Dolt can also be installed via a [community-managed port](https://ports.macports.org/port/dolt/) via [MacPorts](https://www.macports.org):
|
||||
|
||||
```sh
|
||||
sudo port install dolt
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
Download the latest Microsoft Installer (`.msi` file) in
|
||||
[releases](https://github.com/dolthub/dolt/releases) and run
|
||||
it.
|
||||
|
||||
For information on running on Windows, see [here](https://dolthub.com/docs/introduction/installation/windows).
|
||||
|
||||
#### Chocolatey
|
||||
|
||||
You can install `dolt` using [Chocolatey](https://chocolatey.org/):
|
||||
|
||||
```sh
|
||||
choco install dolt
|
||||
```
|
||||
|
||||
#### Docker
|
||||
|
||||
There are following official Docker images for Dolt:
|
||||
|
||||
* [`dolthub/dolt`](https://hub.docker.com/r/dolthub/dolt) for running Dolt
|
||||
as CLI tool.
|
||||
* [`dolthub/dolt-sql-server`](https://hub.docker.com/r/dolthub/dolt-sql-server) for running Dolt in server mode.
|
||||
|
||||
## From Source
|
||||
|
||||
Make sure you have Go installed, and that `go` is in your path. Dolt has a dependency on [cgo](https://pkg.go.dev/cmd/cgo), so you will need a working C compiler and toolchain as well.
|
||||
|
||||
Clone this repository and cd into the `go` directory. Then run:
|
||||
|
||||
```
|
||||
go install ./cmd/dolt
|
||||
```
|
||||
|
||||
The output will be in `$GOPATH/bin`, which defaults to `~/go/bin`. To test your build, try:
|
||||
|
||||
```
|
||||
~/go/bin/dolt version
|
||||
```
|
||||
|
||||
# Configuration
|
||||
|
||||
Verify that your installation has succeeded by running `dolt` in your
|
||||
terminal.
|
||||
|
||||
```
|
||||
$ dolt
|
||||
Valid commands for dolt are
|
||||
[...]
|
||||
```
|
||||
|
||||
Configure `dolt` with your user name and email, which you'll need to
|
||||
create commits. The commands work exactly the same as git.
|
||||
|
||||
```
|
||||
$ dolt config --global --add user.email YOU@DOMAIN.COM
|
||||
$ dolt config --global --add user.name "YOUR NAME"
|
||||
```
|
||||
|
||||
# Getting started
|
||||
|
||||
## Navigate to the directory where you would like your data stored
|
||||
|
||||
Dolt needs a place to store your databases. I'm going to put my databases in `~/dolt`.
|
||||
|
||||
```bash
|
||||
% cd ~
|
||||
% mkdir dolt
|
||||
% cd dolt
|
||||
```
|
||||
|
||||
Any databases you create will be stored in this directory. So, for this example, a directory named `getting_started` will be created here once you run `create database getting_started`. Navigating to `~/dolt/getting_started` will allow you to access this database using the Dolt command line.
|
||||
|
||||
NOTE: For this example, the `getting_started` directory will be created after you run `create database getting_started;` in a SQL shell in the [Create a schema section](#create-a-schema). Don't do anything except make the directory and navigate to it just yet.
|
||||
|
||||
## Start a MySQL-compatible database server
|
||||
|
||||
Dolt ships with a MySQL compatible database server built in. To start it you use the command `dolt sql-server`. Running this command starts the server on port 3306.
|
||||
|
||||
```bash
|
||||
dolt sql-server
|
||||
Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info"
|
||||
```
|
||||
|
||||
Your terminal will just hang there. This means the server is running. Any errors will be printed in this terminal. Just leave it there and open a new terminal.
|
||||
|
||||
## Connect with a MySQL client (up to version 8.4)
|
||||
|
||||
In the new terminal, we will now connect to the running database server using a client. Dolt also ships with a MySQL compatible client.
|
||||
|
||||
```bash
|
||||
% dolt -u root -p "" sql
|
||||
# Welcome to the Dolt MySQL client.
|
||||
# Statements must be terminated with ';'.
|
||||
# "exit" or "quit" (or Ctrl-D) to exit.
|
||||
mysql>
|
||||
```
|
||||
|
||||
In the other terminal where you ran `dolt sql-server`, you'll see the following log line.
|
||||
|
||||
```
|
||||
2022-06-06T13:14:32-07:00 INFO [conn 1] NewConnection {DisableClientMultiStatements=false}
|
||||
```
|
||||
|
||||
You are connected!
|
||||
|
||||
While we're here let's grab a copy of MySQL so we can connect with that client. Head over to the [MySQL Getting Started](https://dev.mysql.com/doc/mysql-getting-started/en/) documentation and install MySQL on your machine. I used [Homebrew](https://brew.sh/) to install MySQL on my Mac: `brew install mysql@8.4`. Alternatively, you can install only the client component by running `brew install mysql-client@8.4`.
|
||||
|
||||
NOTE: Make sure you install a MySQL 8.4 release. MySQL 8.4 is the current Long Term Support (LTS) release, meaning this is the stable and supported version of MySQL. MySQL 9.0 is also available, but is an "innovation" release, meaning it has more recent changes and features, but may not be as stable as the LTS release. The 9.0 release changes authentication support and isn't able to connect to a Dolt SQL server by default. You can install MySQL 8.4 with Homebrew by running `brew install mysql@8.4`. If you do want to use MySQL-9.0, read [our post on how to configure Dolt for `caching_sha2_password` authentication](https://www.dolthub.com/blog/2024-12-11-mysql9-and-caching-sha2-auth-support/).
|
||||
|
||||
MySQL comes with a MySQL server called `mysqld` and a MySQL client called `mysql`. You're only interested in the client. After following the instructions from MySQL's documentation, make sure you have a copy of the `mysql` client on your path:
|
||||
|
||||
```bash
|
||||
% mysql --version
|
||||
mysql Ver 8.0.29 for macos12.2 on x86_64 (Homebrew)
|
||||
```
|
||||
|
||||
Now, to connect the `mysql` client to Dolt, you are going to force the MySQL client through the TCP interface by passing in a host and port. The default is the socket interface which Dolt supports, but is only available on `localhost`. So, it's better to show off the TCP interface. The MySQL client also requires you specify a user, in this case `root`.
|
||||
|
||||
```bash
|
||||
% mysql --host 127.0.0.1 --port 3306 -uroot
|
||||
Welcome to the MySQL monitor. Commands end with ; or \g.
|
||||
Your MySQL connection id is 2
|
||||
Server version: 5.7.9-Vitess
|
||||
|
||||
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
|
||||
|
||||
Oracle is a registered trademark of Oracle Corporation and/or its
|
||||
affiliates. Other names may be trademarks of their respective
|
||||
owners.
|
||||
|
||||
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
|
||||
|
||||
mysql>
|
||||
```
|
||||
|
||||
Again, to ensure the client actually connected, you should see the following in the `dolt sql-server` terminal
|
||||
|
||||
```
|
||||
2022-06-06T13:26:55-07:00 INFO [conn 2] NewConnection {DisableClientMultiStatements=false}
|
||||
```
|
||||
|
||||
As you can see, Dolt supports any MySQL-compatible client. Dolt ships with a client but you can use any MySQL client, like the one that comes with MySQL.
|
||||
|
||||
## Create a schema
|
||||
|
||||
Now we're actually ready to do something interesting. I'll stay in the `mysql` client and execute the following SQL statements to create a database called `getting_started`. The `getting_started` database will have three tables: `employees`, `teams`, and `employees_teams`.
|
||||
|
||||
```
|
||||
mysql> create database getting_started;
|
||||
Query OK, 1 row affected (0.04 sec)
|
||||
|
||||
mysql> use getting_started;
|
||||
Database changed
|
||||
mysql> create table employees (
|
||||
id int,
|
||||
last_name varchar(255),
|
||||
first_name varchar(255),
|
||||
primary key(id));
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
mysql> create table teams (
|
||||
id int,
|
||||
team_name varchar(255),
|
||||
primary key(id));
|
||||
Query OK, 0 rows affected (0.00 sec)
|
||||
|
||||
mysql> create table employees_teams(
|
||||
team_id int,
|
||||
employee_id int,
|
||||
primary key(team_id, employee_id),
|
||||
foreign key (team_id) references teams(id),
|
||||
foreign key (employee_id) references employees(id));
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
mysql> show tables;
|
||||
+---------------------------+
|
||||
| Tables_in_getting_started |
|
||||
+---------------------------+
|
||||
| employees |
|
||||
| employees_teams |
|
||||
| teams |
|
||||
+---------------------------+
|
||||
3 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
Dolt supports foreign keys, secondary indexes, triggers, check constraints, and stored procedures. It's a modern, feature-rich SQL database.
|
||||
|
||||
## Make a Dolt commit
|
||||
|
||||
It's time to use your first Dolt feature. We're going to make a Dolt [commit](https://dolthub.com/docs/concepts/dolt/commits). A Dolt commit allows you to time travel and see lineage. Make a Dolt commit whenever you want to restore or compare to this point in time.
|
||||
|
||||
Dolt exposes version control functionality through a Git-style interface. On the command line, Dolt commands map exactly to their Git equivalent with the targets being tables instead of files. In SQL, Dolt exposes version control read operations as [system tables](https://dolthub.com/docs/sql-reference/version-control/dolt-system-tables) and version control write operations as [stored procedures](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures).
|
||||
|
||||
The naming of the system tables and stored procedures follows the `dolt_<command>` pattern. So `dolt add` on the CLI becomes `dolt_add` as a stored procedure. Passing options also follows the command line model. For instance, to specify tables to add, send the table names in as options to the `dolt_add` procedure. For named arguments like sending a message into the `dolt_commit` command use two arguments in sequence like `('-m', 'This is a message')`. If you know Git, the version control procedures and system tables should feel familiar.
|
||||
|
||||
So, we add and commit our new schema like so.
|
||||
|
||||
```
|
||||
mysql> call dolt_add('teams', 'employees', 'employees_teams');
|
||||
+--------+
|
||||
| status |
|
||||
+--------+
|
||||
| 0 |
|
||||
+--------+
|
||||
1 row in set (0.03 sec)
|
||||
|
||||
mysql> call dolt_commit('-m', 'Created initial schema');
|
||||
+----------------------------------+
|
||||
| hash |
|
||||
+----------------------------------+
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 |
|
||||
+----------------------------------+
|
||||
1 row in set (0.02 sec)
|
||||
|
||||
mysql> select * from dolt_log;
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
| commit_hash | committer | email | date | message |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema |
|
||||
| vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
2 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
There you have it. Your schema is created and you have a Dolt commit tracking the creation, as seen in the `dolt_log` system table.
|
||||
|
||||
Note, a Dolt commit is different than a standard SQL transaction `COMMIT`. In this case, I am running the database with [`AUTOCOMMIT`](https://dev.mysql.com/doc/refman/5.6/en/innodb-autocommit-commit-rollback.html) on, so each SQL statement is automatically generating a transaction `COMMIT`. If you want system to generate a Dolt commit for every transaction use the system variable, [`@@dolt_transaction_commit`](https://dolthub.com/docs/sql-reference/version-control/dolt-sysvars#dolt_transaction_commit).
|
||||
|
||||
## Insert some data
|
||||
|
||||
Now, I'm going to populate the database with a few employees here at DoltHub. Then, I'll assign the employees to two teams: engineering and sales. The CEO wears many hats at a start up so he'll be assigned to multiple teams.
|
||||
|
||||
```
|
||||
mysql> insert into employees values
|
||||
(0, 'Sehn', 'Tim'),
|
||||
(1, 'Hendriks', 'Brian'),
|
||||
(2, 'Son','Aaron'),
|
||||
(3, 'Fitzgerald', 'Brian');
|
||||
Query OK, 4 rows affected (0.01 sec)
|
||||
|
||||
mysql> select * from employees where first_name='Brian';
|
||||
+------+------------+------------+
|
||||
| id | last_name | first_name |
|
||||
+------+------------+------------+
|
||||
| 1 | Hendriks | Brian |
|
||||
| 3 | Fitzgerald | Brian |
|
||||
+------+------------+------------+
|
||||
2 rows in set (0.00 sec)
|
||||
|
||||
mysql> insert into teams values
|
||||
(0, 'Engineering'),
|
||||
(1, 'Sales');
|
||||
Query OK, 2 rows affected (0.00 sec)
|
||||
|
||||
mysql> insert into employees_teams values
|
||||
(0,0),
|
||||
(1,0),
|
||||
(2,0),
|
||||
(0,1),
|
||||
(3,1);
|
||||
ERROR 1452 (HY000): cannot add or update a child row - Foreign key violation on fk: `rv9ek7ft`, table: `employees_teams`, referenced table: `teams`, key: `[2]`
|
||||
```
|
||||
|
||||
Oops, I violated a constraint. It looks like I created the table with teams before employees. You should always specify your columns when you insert, not rely on natural ordering. Serves me right! Dolt comes with the full power of a modern SQL relational database to ensure data integrity.
|
||||
|
||||
```
|
||||
mysql> insert into employees_teams(employee_id, team_id) values
|
||||
(0,0),
|
||||
(1,0),
|
||||
(2,0),
|
||||
(0,1),
|
||||
(3,1);
|
||||
Query OK, 5 rows affected (0.01 sec)
|
||||
|
||||
mysql> select first_name, last_name, team_name from employees
|
||||
join employees_teams on (employees.id=employees_teams.employee_id)
|
||||
join teams on (teams.id=employees_teams.team_id)
|
||||
where team_name='Engineering';
|
||||
+------------+-----------+-------------+
|
||||
| first_name | last_name | team_name |
|
||||
+------------+-----------+-------------+
|
||||
| Tim | Sehn | Engineering |
|
||||
| Brian | Hendriks | Engineering |
|
||||
| Aaron | Son | Engineering |
|
||||
+------------+-----------+-------------+
|
||||
3 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
Looks like everything is inserted and correct. I was able to list the members of the engineering team using that three table `JOIN`. Dolt supports up to twelve table `JOIN`s. Again, Dolt is a modern SQL relational database paired with Git-style version control.
|
||||
|
||||
## Examine the diff
|
||||
|
||||
Now, what if you want to see what changed in your working set before you make a commit? You use the `dolt_status` and `dolt_diff_<tablename>` system tables.
|
||||
|
||||
```
|
||||
mysql> select * from dolt_status;
|
||||
+-----------------+--------+----------+
|
||||
| table_name | staged | status |
|
||||
+-----------------+--------+----------+
|
||||
| teams | 0 | modified |
|
||||
| employees | 0 | modified |
|
||||
| employees_teams | 0 | modified |
|
||||
+-----------------+--------+----------+
|
||||
3 rows in set (0.01 sec)
|
||||
|
||||
mysql> select * from dolt_diff_employees;
|
||||
+--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
|
||||
| to_last_name | to_first_name | to_id | to_commit | to_commit_date | from_last_name | from_first_name | from_id | from_commit | from_commit_date | diff_type |
|
||||
+--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
|
||||
| Sehn | Tim | 0 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added |
|
||||
| Hendriks | Brian | 1 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added |
|
||||
| Son | Aaron | 2 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added |
|
||||
| Fitzgerald | Brian | 3 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added |
|
||||
+--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
As you can see from the diff I've added the correct values to the `employees` table. The values were previously `NULL` and now they are populated.
|
||||
|
||||
Let's finish off with another Dolt commit this time adding all effected tables using `-am`.
|
||||
|
||||
```
|
||||
mysql> call dolt_commit('-am', 'Populated tables with data');
|
||||
+----------------------------------+
|
||||
| hash |
|
||||
+----------------------------------+
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 |
|
||||
+----------------------------------+
|
||||
1 row in set (0.02 sec)
|
||||
```
|
||||
|
||||
You can inspect the log using `dolt_log` and see which tables changed in each commit using an unscoped `dolt_diff`. Unscoped `dolt_diff` tells you whether schema, data, or both changed in that particular commit for the table.
|
||||
|
||||
```
|
||||
mysql> select * from dolt_log;
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
| commit_hash | committer | email | date | message |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data |
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema |
|
||||
| vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+----------------------------+
|
||||
3 rows in set (0.00 sec)
|
||||
|
||||
mysql> select * from dolt_diff;
|
||||
+----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
|
||||
| commit_hash | table_name | committer | email | date | message | data_change | schema_change |
|
||||
+----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 |
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 |
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees_teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 |
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 |
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees_teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 |
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 |
|
||||
+----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
|
||||
6 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
## Oh no! I made a mistake.
|
||||
|
||||
Dolt supports undoing changes via `call dolt_reset()`. Let's imagine I accidentally drop a table.
|
||||
|
||||
```
|
||||
mysql> drop table employees_teams;
|
||||
Query OK, 0 rows affected (0.01 sec)
|
||||
|
||||
mysql> show tables;
|
||||
+---------------------------+
|
||||
| Tables_in_getting_started |
|
||||
+---------------------------+
|
||||
| employees |
|
||||
| teams |
|
||||
+---------------------------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
In a traditional database, this could be disastrous. In Dolt, you're one command away from getting your table back.
|
||||
|
||||
```
|
||||
mysql> call dolt_reset('--hard');
|
||||
+--------+
|
||||
| status |
|
||||
+--------+
|
||||
| 0 |
|
||||
+--------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql> show tables;
|
||||
+---------------------------+
|
||||
| Tables_in_getting_started |
|
||||
+---------------------------+
|
||||
| employees |
|
||||
| employees_teams |
|
||||
| teams |
|
||||
+---------------------------+
|
||||
3 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
Dolt makes operating databases less error prone. You can always back out changes you have in progress or rewind to a known good state. You also have the ability to undo specific commits using [`dolt_revert()`](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures#dolt_revert). Even if you accidentally run `drop database` on the wrong database, Dolt lets you undo that by calling the [`dolt_undrop()` stored procedure](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures#dolt_undrop).
|
||||
|
||||
|
||||
## See the data in a SQL Workbench
|
||||
|
||||
Hate the command line? Let's use [Tableplus](https://tableplus.com/) to make some modifications. Tableplus is a free SQL Workbench. Follow the installation instructions from their website.
|
||||
|
||||
Now, to connect you must select MySQL as the connection type. Then enter a name for your connection, `getting_started` as your database, and `root` as your user.
|
||||
|
||||

|
||||
|
||||
Click connect and you'll be presented with a familiar database workbench GUI.
|
||||
|
||||

|
||||
|
||||
## Make changes on a branch
|
||||
|
||||
To make changes on a branch, I use the `dolt_checkout()` stored procedure. Using the `-b` option creates a branch, just like in Git.
|
||||
|
||||
Tableplus gives me the ability to enter a multiple line SQL script on the SQL tab. I entered the following SQL to checkout a branch, update, insert, delete, and finally Dolt commit my changes.
|
||||
|
||||
```SQL
|
||||
call dolt_checkout('-b','modifications');
|
||||
update employees SET first_name='Timothy' where first_name='Tim';
|
||||
insert INTO employees (id, first_name, last_name) values (4,'Daylon', 'Wilkins');
|
||||
insert into employees_teams(team_id, employee_id) values (0,4);
|
||||
delete from employees_teams where employee_id=0 and team_id=1;
|
||||
call dolt_commit('-am', 'Modifications on a branch');
|
||||
```
|
||||
|
||||
Here's the result in Tableplus.
|
||||
|
||||

|
||||
|
||||
Back in my terminal, I cannot see the table modifications made in Tableplus because they happened on a different branch than the one I have checked out in my session.
|
||||
|
||||
```
|
||||
mysql> select * from dolt_branches;
|
||||
+---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
|
||||
| name | hash | latest_committer | latest_committer_email | latest_commit_date | latest_commit_message |
|
||||
+---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
|
||||
| main | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data |
|
||||
| modifications | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:41:49.847 | Modifications on a branch |
|
||||
+---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
|
||||
2 rows in set (0.00 sec)
|
||||
|
||||
mysql> select active_branch();
|
||||
+-----------------+
|
||||
| active_branch() |
|
||||
+-----------------+
|
||||
| main |
|
||||
+-----------------+
|
||||
1 row in set (0.00 sec)
|
||||
|
||||
mysql> select * from employees;
|
||||
+------+------------+------------+
|
||||
| id | last_name | first_name |
|
||||
+------+------------+------------+
|
||||
| 0 | Sehn | Tim |
|
||||
| 1 | Hendriks | Brian |
|
||||
| 2 | Son | Aaron |
|
||||
| 3 | Fitzgerald | Brian |
|
||||
+------+------------+------------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
I can query the branch no matter what I have checked out using SQL `as of` syntax.
|
||||
|
||||
```
|
||||
mysql> select * from employees as of 'modifications';
|
||||
+------+------------+------------+
|
||||
| id | last_name | first_name |
|
||||
+------+------------+------------+
|
||||
| 0 | Sehn | Timothy |
|
||||
| 1 | Hendriks | Brian |
|
||||
| 2 | Son | Aaron |
|
||||
| 3 | Fitzgerald | Brian |
|
||||
| 4 | Wilkins | Daylon |
|
||||
+------+------------+------------+
|
||||
5 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
If I'd like to see the diff between the two branches, I can use the `dolt_diff()` table function. It takes two branches and the table name as arguments.
|
||||
|
||||
```
|
||||
mysql> select * from dolt_diff('main', 'modifications', 'employees');
|
||||
+--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
|
||||
| to_last_name | to_first_name | to_id | to_commit | to_commit_date | from_last_name | from_first_name | from_id | from_commit | from_commit_date | diff_type |
|
||||
+--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
|
||||
| Sehn | Timothy | 0 | modifications | 2022-06-07 16:41:49.847 | Sehn | Tim | 0 | main | 2022-06-07 16:39:32.066 | modified |
|
||||
| Wilkins | Daylon | 4 | modifications | 2022-06-07 16:41:49.847 | NULL | NULL | NULL | main | 2022-06-07 16:39:32.066 | added |
|
||||
+--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
As you can see, you have the full power of Git-style branches and diffs in a SQL database with Dolt.
|
||||
|
||||
## Make a schema change on another branch
|
||||
|
||||
I can also make schema changes on branches for isolated testing of new schema. I'm going to add a `start_date` column on a new branch and populate it.
|
||||
|
||||
```
|
||||
mysql> call dolt_checkout('-b', 'schema_changes');
|
||||
+--------+
|
||||
| status |
|
||||
+--------+
|
||||
| 0 |
|
||||
+--------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql> alter table employees add column start_date date;
|
||||
Query OK, 0 rows affected (0.02 sec)
|
||||
|
||||
mysql> update employees set start_date='2018-09-08';
|
||||
Query OK, 4 rows affected (0.01 sec)
|
||||
Rows matched: 4 Changed: 4 Warnings: 0
|
||||
|
||||
mysql> update employees set start_date='2021-04-19' where last_name='Fitzgerald';
|
||||
Query OK, 1 row affected (0.01 sec)
|
||||
Rows matched: 1 Changed: 1 Warnings: 0
|
||||
|
||||
mysql> select * from employees;
|
||||
+------+------------+------------+------------+
|
||||
| id | last_name | first_name | start_date |
|
||||
+------+------------+------------+------------+
|
||||
| 0 | Sehn | Tim | 2018-09-08 |
|
||||
| 1 | Hendriks | Brian | 2018-09-08 |
|
||||
| 2 | Son | Aaron | 2018-09-08 |
|
||||
| 3 | Fitzgerald | Brian | 2021-04-19 |
|
||||
+------+------------+------------+------------+
|
||||
4 rows in set (0.00 sec)
|
||||
|
||||
mysql> call dolt_commit('-am', 'Added start_date column to employees');
|
||||
+----------------------------------+
|
||||
| hash |
|
||||
+----------------------------------+
|
||||
| pg3nfi0j1dpc5pf1rfgckpmlteaufdrt |
|
||||
+----------------------------------+
|
||||
1 row in set (0.01 sec)
|
||||
```
|
||||
|
||||
Changing schema on a branch gives you a new method for doing isolated integration testing of new schema changes.
|
||||
|
||||
## Merge it all together
|
||||
|
||||
Let's assume all the testing of the new schema on the `schema_changes` branch and data on the `modifications` branch completed flawlessly. It's time to merge all our edits together onto `main`. This is done using the `dolt_merge` stored procedure.
|
||||
|
||||
```
|
||||
mysql> call dolt_checkout('main');
|
||||
+--------+
|
||||
| status |
|
||||
+--------+
|
||||
| 0 |
|
||||
+--------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql> select * from dolt_status;
|
||||
Empty set (0.00 sec)
|
||||
|
||||
mysql> call dolt_merge('schema_changes');
|
||||
+--------------+
|
||||
| no_conflicts |
|
||||
+--------------+
|
||||
| 1 |
|
||||
+--------------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql> select * from employees;
|
||||
+------+------------+------------+------------+
|
||||
| id | last_name | first_name | start_date |
|
||||
+------+------------+------------+------------+
|
||||
| 0 | Sehn | Tim | 2018-09-08 |
|
||||
| 1 | Hendriks | Brian | 2018-09-08 |
|
||||
| 2 | Son | Aaron | 2018-09-08 |
|
||||
| 3 | Fitzgerald | Brian | 2021-04-19 |
|
||||
+------+------------+------------+------------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
Schema change successful. We now have start dates. Data changes are next.
|
||||
|
||||
```
|
||||
mysql> call dolt_merge('modifications');
|
||||
+--------------+
|
||||
| no_conflicts |
|
||||
+--------------+
|
||||
| 1 |
|
||||
+--------------+
|
||||
1 row in set (0.02 sec)
|
||||
|
||||
mysql> select * from employees;
|
||||
+------+------------+------------+------------+
|
||||
| id | last_name | first_name | start_date |
|
||||
+------+------------+------------+------------+
|
||||
| 0 | Sehn | Timothy | 2018-09-08 |
|
||||
| 1 | Hendriks | Brian | 2018-09-08 |
|
||||
| 2 | Son | Aaron | 2018-09-08 |
|
||||
| 3 | Fitzgerald | Brian | 2021-04-19 |
|
||||
| 4 | Wilkins | Daylon | NULL |
|
||||
+------+------------+------------+------------+
|
||||
5 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
Data changes successful as well. As you can see, I am now "Timothy" instead of "Tim", Daylon is added, and we all have start dates except for Daylon who was added on a different branch.
|
||||
|
||||
```
|
||||
mysql> select first_name, last_name, team_name from employees
|
||||
join employees_teams on (employees.id=employees_teams.employee_id)
|
||||
join teams on (teams.id=employees_teams.team_id)
|
||||
where team_name='Sales';
|
||||
+------------+------------+-----------+
|
||||
| first_name | last_name | team_name |
|
||||
+------------+------------+-----------+
|
||||
| Brian | Fitzgerald | Sales |
|
||||
+------------+------------+-----------+
|
||||
1 row in set (0.01 sec)
|
||||
```
|
||||
|
||||
I'm also gone from the Sales Team. Engineering is life.
|
||||
|
||||
I have to commit all my changes because the last merge was not a fast-forward merge.
|
||||
|
||||
```
|
||||
mysql> call dolt_commit('-m', 'Merged all branches');
|
||||
+----------------------------------+
|
||||
| hash |
|
||||
+----------------------------------+
|
||||
| vn9b0qcematsj2f6ka0hfoflhr5s6p0b |
|
||||
+----------------------------------+
|
||||
1 row in set (0.01 sec)
|
||||
|
||||
mysql> select * from dolt_log;
|
||||
+----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+
|
||||
| commit_hash | committer | email | date | message |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+
|
||||
| vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn | tim@dolthub.com | 2022-06-07 17:10:02.07 | Merged all branches |
|
||||
| pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn | tim@dolthub.com | 2022-06-07 16:44:37.513 | Added start_date column to employees |
|
||||
| uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:41:49.847 | Modifications on a branch |
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data |
|
||||
| ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema |
|
||||
| vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository |
|
||||
+----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+
|
||||
6 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
Now, we have a database with all the schema and data changes merged and ready for use.
|
||||
|
||||
## Audit Cell Lineage
|
||||
|
||||
Which commit changed my first name? With Dolt you have lineage for every cell in your database. Let's use the `dolt_history_<tablename>` and `dolt_diff_<tablename>` to explore the lineage features in Dolt.
|
||||
|
||||
`dolt_history_<tablename>` shows you the state of the row at every commit.
|
||||
|
||||
```
|
||||
mysql> select * from dolt_history_employees where id=0 order by commit_date;
|
||||
+------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
|
||||
| id | last_name | first_name | start_date | commit_hash | committer | commit_date |
|
||||
+------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
|
||||
| 0 | Sehn | Tim | NULL | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | 2022-06-07 16:39:32.066 |
|
||||
| 0 | Sehn | Timothy | NULL | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | 2022-06-07 16:41:49.847 |
|
||||
| 0 | Sehn | Tim | 2018-09-08 | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn | 2022-06-07 16:44:37.513 |
|
||||
| 0 | Sehn | Timothy | 2018-09-08 | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn | 2022-06-07 17:10:02.07 |
|
||||
+------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
|
||||
4 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
`dolt_diff_<tablename>` allows you to filter the history down to only commits when the cell in question changed. In this case, I'm interested in the commits that are changing my first name. Note, there are two commits that changed my name because one is the original change and the second is the merge commit.
|
||||
|
||||
```
|
||||
mysql> select to_commit,from_first_name,to_first_name from dolt_diff_employees
|
||||
where (from_id=0 or to_id=0) and (from_first_name <> to_first_name or from_first_name is NULL)
|
||||
order by to_commit_date;
|
||||
+----------------------------------+-----------------+---------------+
|
||||
| to_commit | from_first_name | to_first_name |
|
||||
+----------------------------------+-----------------+---------------+
|
||||
| 13qfqa5rojq18j84d1n2htjkm6fletg4 | NULL | Tim |
|
||||
| uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim | Timothy |
|
||||
| vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim | Timothy |
|
||||
+----------------------------------+-----------------+---------------+
|
||||
3 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
Dolt provides powerful data audit capabilities down to individual cells. When, how, and why has each cell in your database changed over time?
|
||||
|
||||
# Additional Reading
|
||||
|
||||
Head over to [our documentation](https://dolthub.com/docs/introduction/what-is-dolt) now that you have a feel for Dolt. You can also read about what we've been working on in [our blog](https://www.dolthub.com/blog/).
|
||||
|
||||
# Security Policy
|
||||
|
||||
[Dolt's current security policy](https://github.com/dolthub/dolt/blob/main/SECURITY.md) is maintained in this repository. Please follow the disclosure instructions there. Please do not initially report security issues in this repository's public GitHub issues.
|
||||
|
||||
# Credits and License
|
||||
|
||||
Dolt relies heavily on open source code and ideas from the
|
||||
[Noms](https://github.com/attic-labs/noms) project. We are very
|
||||
thankful to the Noms team for making this code freely available,
|
||||
without which we would not have been able to build Dolt so rapidly.
|
||||
|
||||
Dolt is licensed under the Apache License, Version 2.0. See
|
||||
[LICENSE](https://github.com/dolthub/dolt/blob/master/LICENSE) for
|
||||
details.
|
||||
@@ -0,0 +1,7 @@
|
||||
# WeHub 来源说明
|
||||
|
||||
- 原始项目:`dolthub/dolt`
|
||||
- 原始仓库:https://github.com/dolthub/dolt
|
||||
- 导入方式:上游默认分支的最新快照
|
||||
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
|
||||
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
By default, the most recent release of Dolt is the version which is
|
||||
supported for all security updates. If you need ongoing security
|
||||
support for an older version of Dolt, please [contact us](https://www.dolthub.com/contact).
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Any security issues with Dolt can be reported to [security@dolthub.com](security@dolthub.com).
|
||||
|
||||
Reports will be responded to within one business day. The majority of
|
||||
our team operates on Pacific Time and on a US holiday schedule.
|
||||
|
||||
DoltHub does not currently run a security bounty program for Dolt.
|
||||
@@ -0,0 +1,21 @@
|
||||
# syntax=docker/dockerfile:1.3-labs
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DOLT_VERSION
|
||||
|
||||
RUN apt update -y && \
|
||||
apt install -y \
|
||||
curl \
|
||||
git \
|
||||
tini \
|
||||
ca-certificates && \
|
||||
apt clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# we install dolt with the install.sh script, which will determine the platform/arch of the container
|
||||
# and install the proper dolt binary
|
||||
RUN bash -c 'curl -L https://github.com/dolthub/dolt/releases/download/v${DOLT_VERSION}/install.sh | bash'
|
||||
RUN /usr/local/bin/dolt version
|
||||
|
||||
WORKDIR /var/lib/dolt
|
||||
ENTRYPOINT ["tini", "--", "/usr/local/bin/dolt"]
|
||||
@@ -0,0 +1,78 @@
|
||||
# Dolt is Git for Data!
|
||||
|
||||
[Dolt](https://doltdb.com) is a SQL database that you can fork, clone, branch, merge, push
|
||||
and pull just like a Git repository. Connect to Dolt just like any
|
||||
MySQL database to run queries or update the data using SQL
|
||||
commands. Use the command line interface to import CSV files, commit
|
||||
your changes, push them to a remote, or merge your teammate's changes.
|
||||
|
||||
All the commands you know for Git work exactly the same for Dolt. Git
|
||||
versions files, Dolt versions tables. It's like Git and MySQL had a
|
||||
baby.
|
||||
|
||||
We also built [DoltHub](https://www.dolthub.com), a place to share
|
||||
Dolt databases. We host public data for free. If you want to host
|
||||
your own version of DoltHub, we have [DoltLab](https://www.doltlab.com). If you want us to run a Dolt server for you, we have [Hosted Dolt](https://hosted.doltdb.com).
|
||||
|
||||
[Join us on Discord](https://discord.com/invite/RFwfYpu) to say hi and
|
||||
ask questions, or [check out our roadmap](https://dolthub.com/docs/other/roadmap)
|
||||
to see what we're building next.
|
||||
|
||||
## What's it for?
|
||||
|
||||
Lots of things! Dolt is a generally useful tool with countless
|
||||
applications. But if you want some ideas, [here's how people are using
|
||||
it so far](https://www.dolthub.com/blog/2022-07-11-dolt-case-studies/).
|
||||
|
||||
Learn more about Dolt use cases, configuration and guides to use dolt on our [documentation page](https://dolthub.com/docs/introduction/what-is-dolt).
|
||||
|
||||
# How to use this image
|
||||
|
||||
This image is for Dolt CLI, which has the same commands as `git`, with some extras. Running this image without any
|
||||
arguments is equivalent to running `dolt` command locally.
|
||||
|
||||
```shell
|
||||
$ docker run dolthub/dolt:latest
|
||||
Valid commands for dolt are
|
||||
init - Create an empty Dolt data repository.
|
||||
status - Show the working tree status.
|
||||
add - Add table changes to the list of staged table changes.
|
||||
diff - Diff a table.
|
||||
reset - Remove table changes from the list of staged table changes.
|
||||
clean - Remove untracked tables from working set.
|
||||
commit - Record changes to the repository.
|
||||
sql - Run a SQL query against tables in repository.
|
||||
sql-server - Start a MySQL-compatible server.
|
||||
sql-client - Starts a built-in MySQL client.
|
||||
log - Show commit logs.
|
||||
branch - Create, list, edit, delete branches.
|
||||
checkout - Checkout a branch or overwrite a table from HEAD.
|
||||
merge - Merge a branch.
|
||||
conflicts - Commands for viewing and resolving merge conflicts.
|
||||
cherry-pick - Apply the changes introduced by an existing commit.
|
||||
revert - Undo the changes introduced in a commit.
|
||||
clone - Clone from a remote data repository.
|
||||
fetch - Update the database from a remote data repository.
|
||||
pull - Fetch from a dolt remote data repository and merge.
|
||||
push - Push to a dolt remote.
|
||||
config - Dolt configuration.
|
||||
remote - Manage set of tracked repositories.
|
||||
backup - Manage a set of server backups.
|
||||
login - Login to a dolt remote host.
|
||||
creds - Commands for managing credentials.
|
||||
ls - List tables in the working set.
|
||||
schema - Commands for showing and importing table schemas.
|
||||
table - Commands for copying, renaming, deleting, and exporting tables.
|
||||
tag - Create, list, delete tags.
|
||||
blame - Show what revision and author last modified each row of a table.
|
||||
constraints - Commands for handling constraints.
|
||||
migrate - Executes a database migration to use the latest Dolt data format.
|
||||
read-tables - Fetch table(s) at a specific commit into a new dolt repo
|
||||
gc - Cleans up unreferenced data from the repository.
|
||||
filter-branch - Edits the commit history using the provided query.
|
||||
merge-base - Find the common ancestor of two commits.
|
||||
version - Displays the current Dolt cli version.
|
||||
dump - Export all tables in the working set into a file.
|
||||
```
|
||||
|
||||
This image is useful for creating custom Docker Image using this image as base image.
|
||||
Executable
+441
@@ -0,0 +1,441 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
# mysql_log prints a timestamped (ISO 8601), color-coded structured log message.
|
||||
# The message includes a log level and the message itself.
|
||||
# If <MESSAGE> is omitted, it reads from stdin, allowing multi-line input.
|
||||
#
|
||||
# Arguments:
|
||||
# $1 - <LEVEL> : Log level (e.g., Warn, Error, Debug)
|
||||
# $2 - <MESSAGE> : Message to log; if omitted, the function reads from stdin
|
||||
#
|
||||
# Usage:
|
||||
# mysql_log <LEVEL> [MESSAGE]
|
||||
# mysql_log Warn "Disk space low"
|
||||
# echo "Database connection lost" | mysql_log Error
|
||||
#
|
||||
# Output:
|
||||
# 2025-10-16T12:34:56+00:00 [Warn] [Entrypoint] Disk space low
|
||||
# 2025-10-16T12:35:01+00:00 [Error] [Entrypoint] Database connection lost
|
||||
_mysql_log() {
|
||||
local level="$1"; shift
|
||||
|
||||
local dt
|
||||
dt="$(date --rfc-3339=seconds)"
|
||||
|
||||
local color_reset="\033[0m"
|
||||
local color=""
|
||||
case "$level" in
|
||||
Warn) color="\033[1;33m" ;; # yellow
|
||||
Error) color="\033[1;31m" ;; # red
|
||||
Debug) color="\033[1;34m" ;; # blue
|
||||
esac
|
||||
|
||||
local msg="$*"
|
||||
if [ "$#" -eq 0 ]; then
|
||||
msg="$(cat)"
|
||||
fi
|
||||
|
||||
printf '%b%s [%s] [Entrypoint] %s%b\n' "$color" "$dt" "$level" "$msg" "$color_reset"
|
||||
}
|
||||
|
||||
|
||||
# _dbg logs a message of type 'Debug' using mysql_log.
|
||||
_dbg() {
|
||||
_mysql_log Debug "$@"
|
||||
}
|
||||
|
||||
# mysql_note logs a message of type 'Note' using mysql_log.
|
||||
mysql_note() {
|
||||
_mysql_log Note "$@"
|
||||
}
|
||||
|
||||
# mysql_warn logs a message of type 'Warning' using mysql_log and writes to stderr.
|
||||
mysql_warn() {
|
||||
_mysql_log Warn "$@" >&2
|
||||
}
|
||||
|
||||
# mysql_error logs a message of type 'ERROR' using mysql_log, writes to stderr, prints a container removal hint, and
|
||||
# exits with status 1.
|
||||
mysql_error() {
|
||||
_mysql_log Error "$@" >&2
|
||||
mysql_note "Remove this container with 'docker rm -f <container_name>' before retrying"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# exec_mysql executes a SQL query using Dolt, retrying until success or timeout. Ensures reliability during slow
|
||||
# container or resource startup. On timeout, it prints the provided error prefix followed by filtered Dolt output.
|
||||
# Errors are parsed to remove blank lines and extract only relevant error text. Use --show-result to display successful
|
||||
# query results.
|
||||
#
|
||||
# Usage:
|
||||
# exec_mysql [--show-result] "<ERROR_MESSAGE>" "<QUERY>"
|
||||
# exec_mysql [--show-result] "<ERROR_MESSAGE>" < /docker-entrypoint-initdb.d/init.sql
|
||||
# cat /docker-entrypoint-initdb.d/init.sql | exec_mysql [--show-result] "<ERROR_MESSAGE>"
|
||||
#
|
||||
# Output:
|
||||
# Prints query output only if --show-result is specified.
|
||||
exec_mysql() {
|
||||
local show_result=0
|
||||
if [ "$1" = "--show-result" ]; then
|
||||
show_result=1
|
||||
shift
|
||||
fi
|
||||
|
||||
local error_message="$1"
|
||||
local query="${2:-}"
|
||||
local timeout="${DOLT_SERVER_TIMEOUT:-300}"
|
||||
local start_time now output status
|
||||
|
||||
start_time=$(date +%s)
|
||||
|
||||
while true; do
|
||||
if [ -n "$query" ]; then
|
||||
output=$(dolt sql -q "$query" 2>&1)
|
||||
status=$?
|
||||
else
|
||||
set +e # tmp disabled to initdb.d/ file err
|
||||
output=$(dolt sql < /dev/stdin 2>&1)
|
||||
status=$?
|
||||
set -e
|
||||
fi
|
||||
|
||||
if [ "$status" -eq 0 ]; then
|
||||
[ "$show_result" -eq 1 ] && echo "$output" | grep -v "^$" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
if echo "$output" | grep -qiE "Error [0-9]+ \([A-Z0-9]+\)"; then
|
||||
mysql_error "$error_message$(echo "$output" | grep -iE "Error|error")"
|
||||
fi
|
||||
|
||||
if [ "$timeout" -ne 0 ]; then
|
||||
now=$(date +%s)
|
||||
if [ $((now - start_time)) -ge "$timeout" ]; then
|
||||
mysql_error "$error_message$(echo "$output" | grep -iE "Error|error" || true)"
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
CONTAINER_DATA_DIR="/var/lib/dolt"
|
||||
INIT_COMPLETED="$CONTAINER_DATA_DIR/.init_completed"
|
||||
DOLT_CONFIG_DIR="/etc/dolt/doltcfg.d"
|
||||
SERVER_CONFIG_DIR="/etc/dolt/servercfg.d"
|
||||
DOLT_ROOT_PATH="/.dolt"
|
||||
SERVER_PID=-1
|
||||
|
||||
# check_for_dolt_binary verifies that the dolt binary is present and executable in the system PATH.
|
||||
# If not found or not executable, it logs an error and exits.
|
||||
check_for_dolt_binary() {
|
||||
local dolt_bin
|
||||
dolt_bin=$(which dolt)
|
||||
if [ ! -x "$dolt_bin" ]; then
|
||||
mysql_error "dolt binary executable not found"
|
||||
fi
|
||||
}
|
||||
|
||||
# get_env_var returns the value of an environment variable, preferring DOLT_* over MYSQL_*.
|
||||
# Arguments:
|
||||
# $1 - The base variable name (e.g., "USER" for MYSQL_USER or DOLT_USER)
|
||||
# Output:
|
||||
# Prints the value of the first set variable, or an empty string if neither is set.
|
||||
get_env_var() {
|
||||
local var_name="$1"
|
||||
local dolt_var="DOLT_${var_name}"
|
||||
local mysql_var="MYSQL_${var_name}"
|
||||
|
||||
if [ -n "${!dolt_var}" ]; then
|
||||
echo "${!dolt_var}"
|
||||
elif [ -n "${!mysql_var}" ]; then
|
||||
echo "${!mysql_var}"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# get_env_var_name returns the name of the environment variable that is set, preferring DOLT_* over MYSQL_*.
|
||||
# Arguments:
|
||||
# $1 - The base variable name (e.g., "USER" for MYSQL_USER or DOLT_USER)
|
||||
# Output:
|
||||
# Prints the name of the first set variable, or both names if neither is set.
|
||||
get_env_var_name() {
|
||||
local var_name="$1"
|
||||
local dolt_var="DOLT_${var_name}"
|
||||
local mysql_var="MYSQL_${var_name}"
|
||||
|
||||
if [ -n "${!dolt_var}" ]; then
|
||||
echo "DOLT_${var_name}"
|
||||
elif [ -n "${!mysql_var}" ]; then
|
||||
echo "MYSQL_${var_name}"
|
||||
else
|
||||
echo "MYSQL_${var_name}/DOLT_${var_name}"
|
||||
fi
|
||||
}
|
||||
|
||||
# get_config_file_path_if_exists checks for config files of a given type in a directory.
|
||||
# Arguments:
|
||||
# $1 - Directory to search in
|
||||
# $2 - File type/extension to search for (e.g., 'json', 'yaml')
|
||||
# Output:
|
||||
# Sets CONFIG_PROVIDED to the path of the config file if exactly one is found, or empty otherwise.
|
||||
# Logs a warning if multiple config files are found and uses the default config.
|
||||
get_config_file_path_if_exists() {
|
||||
CONFIG_PROVIDED=
|
||||
local CONFIG_DIR=$1
|
||||
local FILE_TYPE=$2
|
||||
if [ -d "$CONFIG_DIR" ]; then
|
||||
mysql_note "Checking for config provided in $CONFIG_DIR"
|
||||
local number_of_files_found
|
||||
number_of_files_found=$(find "$CONFIG_DIR" -type f -name "*.$FILE_TYPE" | wc -l)
|
||||
if [ "$number_of_files_found" -gt 1 ]; then
|
||||
CONFIG_PROVIDED=
|
||||
mysql_warn "Multiple config files found in $CONFIG_DIR, using default config"
|
||||
elif [ "$number_of_files_found" -eq 1 ]; then
|
||||
local files_found
|
||||
files_found=$(ls "$CONFIG_DIR"/*."$FILE_TYPE")
|
||||
mysql_note "$files_found file is found"
|
||||
CONFIG_PROVIDED=$files_found
|
||||
else
|
||||
CONFIG_PROVIDED=
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# docker_process_init_files Runs files found in /docker-entrypoint-initdb.d before the server is started.
|
||||
# Taken from https://github.com/docker-library/mysql/blob/master/8.0/docker-entrypoint.sh
|
||||
# Usage:
|
||||
# docker_process_init_files [file [file ...]]
|
||||
# e.g., docker_process_init_files /always-initdb.d/*
|
||||
# Processes initializer files based on file extensions.
|
||||
docker_process_init_files() {
|
||||
local f
|
||||
echo
|
||||
for f; do
|
||||
case "$f" in
|
||||
*.sh)
|
||||
if [ -x "$f" ]; then
|
||||
mysql_note "$0: running $f"
|
||||
if ! "$f"; then
|
||||
mysql_error "Failed to execute $f: "
|
||||
fi
|
||||
else
|
||||
mysql_note "$0: sourcing $f"
|
||||
if ! . "$f"; then
|
||||
mysql_error "Failed to execute $f: "
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*.sql)
|
||||
mysql_note "$0: running $f"
|
||||
exec_mysql --show-result "Failed to execute $f: " < "$f"
|
||||
;;
|
||||
*.sql.bz2)
|
||||
mysql_note "$0: running $f"
|
||||
bunzip2 -c "$f" | exec_mysql --show-result "Failed to execute $f: "
|
||||
;;
|
||||
*.sql.gz)
|
||||
mysql_note "$0: running $f"
|
||||
gunzip -c "$f" | exec_mysql --show-result "Failed to execute $f: "
|
||||
;;
|
||||
*.sql.xz)
|
||||
mysql_note "$0: running $f"
|
||||
xzcat "$f" | exec_mysql --show-result "Failed to execute $f: "
|
||||
;;
|
||||
*.sql.zst)
|
||||
mysql_note "$0: running $f"
|
||||
zstd -dc "$f" | exec_mysql --show-result "Failed to execute $f: "
|
||||
;;
|
||||
*)
|
||||
mysql_warn "$0: ignoring $f"
|
||||
;;
|
||||
esac
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
# set_dolt_config_if_defined checks for a user-provided Dolt config file in $DOLT_CONFIG_DIR.
|
||||
# If a single JSON config file is found, it copies it to $HOME/$DOLT_ROOT_PATH/config_global.json,
|
||||
# overwriting the default config. Logs an error and exits if the copy fails.
|
||||
set_dolt_config_if_defined() {
|
||||
get_config_file_path_if_exists "$DOLT_CONFIG_DIR" "json"
|
||||
if [ ! -z "$CONFIG_PROVIDED" ]; then
|
||||
if ! /bin/cp -rf "$CONFIG_PROVIDED" "$HOME/$DOLT_ROOT_PATH/config_global.json" 2>&1; then
|
||||
mysql_error "Failed to copy config file from '$CONFIG_PROVIDED' to '$HOME/$DOLT_ROOT_PATH/config_global.json'. Check file permissions and paths."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# create_database_from_env creates a database if the DATABASE environment variable is set.
|
||||
# It retrieves the database name from environment variables (preferring DOLT_DATABASE over MYSQL_DATABASE)
|
||||
# and attempts to create the database using exec_mysql.
|
||||
create_database_from_env() {
|
||||
local database
|
||||
database=$(get_env_var "DATABASE")
|
||||
|
||||
if [ -n "$database" ]; then
|
||||
mysql_note "Creating database '${database}'"
|
||||
exec_mysql "Failed to create database '$database': " "CREATE DATABASE IF NOT EXISTS \`$database\`;"
|
||||
fi
|
||||
}
|
||||
|
||||
# create_user_from_env creates a new database user from environment variables.
|
||||
# It prefers DOLT_USER/PASSWORD over MYSQL_USER/PASSWORD, and optionally grants access to a database.
|
||||
# Requires both USER and PASSWORD to be set; if only the password is set, it logs a warning and does nothing.
|
||||
# It does not allow creating a 'root' user via these environment variables.
|
||||
create_user_from_env() {
|
||||
local user
|
||||
local password
|
||||
local database
|
||||
|
||||
user=$(get_env_var "USER")
|
||||
password=$(get_env_var "PASSWORD")
|
||||
database=$(get_env_var "DATABASE")
|
||||
|
||||
if [ "$user" = 'root' ]; then
|
||||
mysql_error "$(get_env_var_name "USER")="root", $(get_env_var_name "USER") and $(get_env_var_name "PASSWORD") are for configuring the regular user and cannot be used for the root user."
|
||||
fi
|
||||
|
||||
if [ -n "$user" ] && [ -z "$password" ]; then
|
||||
mysql_error "$(get_env_var_name "USER") specified, but missing $(get_env_var_name "PASSWORD"); user creation requires a password."
|
||||
elif [ -z "$user" ] && [ -n "$password" ]; then
|
||||
mysql_warn "$(get_env_var_name "PASSWORD") specified, but missing $(get_env_var_name "USER"); password will be ignored"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -n "$user" ]; then
|
||||
local user_host
|
||||
user_host=$(get_env_var "USER_HOST")
|
||||
user_host="${user_host:-${DOLT_ROOT_HOST:-localhost}}"
|
||||
|
||||
mysql_note "Creating user '${user}@${user_host}'"
|
||||
exec_mysql "Failed to create user '$user': " "CREATE USER IF NOT EXISTS '$user'@'$user_host' IDENTIFIED BY '$password';"
|
||||
exec_mysql "Failed to grant server access to user '$user': " "GRANT USAGE ON *.* TO '$user'@'$user_host';"
|
||||
|
||||
if [ -n "$database" ]; then
|
||||
exec_mysql "Failed to grant permissions to user '$user' on database '$database': " "GRANT ALL ON \`$database\`.* TO '$user'@'$user_host';"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# is_port_open checks if a TCP port is open on a given host.
|
||||
# Arguments:
|
||||
# $1 - Host (IP or hostname)
|
||||
# $2 - Port number
|
||||
# Returns:
|
||||
# 0 if the port is open, non-zero otherwise.
|
||||
is_port_open() {
|
||||
local host="$1"
|
||||
local port="$2"
|
||||
timeout 1 bash -c "cat < /dev/null > /dev/tcp/$host/$port" &>/dev/null
|
||||
return $?
|
||||
}
|
||||
|
||||
# dolt_server_initializer starts the Dolt SQL server in the background and waits until it is ready to accept connections.
|
||||
# It manages the server process, restarts it if necessary, and checks for readiness by probing the configured port.
|
||||
# The function retries until the server is available or a timeout is reached, handling process management and logging.
|
||||
# Arguments:
|
||||
# $@ - Additional arguments to pass to `dolt sql-server`
|
||||
# Returns:
|
||||
# 0 if the server starts successfully and is ready to accept connections; exits with error otherwise.
|
||||
dolt_server_initializer() {
|
||||
local timeout="${DOLT_SERVER_TIMEOUT:-300}"
|
||||
local start_time
|
||||
start_time=$(date +%s)
|
||||
|
||||
SERVER_PID=-1
|
||||
|
||||
trap 'mysql_note "Caught Ctrl+C, shutting down Dolt server..."; [ $SERVER_PID -ne -1 ] && kill "$SERVER_PID"; exit 1' INT TERM
|
||||
|
||||
while true; do
|
||||
if [ "$SERVER_PID" -eq -1 ] || ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
[ "$SERVER_PID" -ne -1 ] && wait "$SERVER_PID" 2>/dev/null || true
|
||||
SERVER_PID=-1
|
||||
dolt sql-server --host=0.0.0.0 --port=3306 "$@" 2>&1 &
|
||||
SERVER_PID=$!
|
||||
|
||||
fi
|
||||
|
||||
if is_port_open "0.0.0.0" 3306; then
|
||||
mysql_note "Dolt server started."
|
||||
return 0
|
||||
fi
|
||||
|
||||
local now elapsed
|
||||
now=$(date +%s)
|
||||
elapsed=$((now - start_time))
|
||||
if [ "$elapsed" -ge "$timeout" ]; then
|
||||
kill "$SERVER_PID" 2>/dev/null || true
|
||||
wait "$SERVER_PID" 2>/dev/null || true
|
||||
SERVER_PID=-1
|
||||
mysql_error "Dolt server failed to start within $timeout seconds"
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# _main is the main entrypoint for the Dolt Docker container initialization.
|
||||
_main() {
|
||||
check_for_dolt_binary
|
||||
|
||||
local dolt_version
|
||||
dolt_version=$(dolt version | grep 'dolt version' | cut -f3 -d " ")
|
||||
mysql_note "Entrypoint script for Dolt Server $dolt_version starting..."
|
||||
|
||||
declare -g CONFIG_PROVIDED
|
||||
|
||||
# dolt config will be set if user provided a single json file in /etc/dolt/doltcfg.d directory.
|
||||
# It will overwrite config_global.json file in $HOME/.dolt
|
||||
set_dolt_config_if_defined
|
||||
CONFIG_PROVIDED=
|
||||
|
||||
# if there is a single yaml provided in /etc/dolt/servercfg.d directory,
|
||||
# it will be used to start the server with --config flag.
|
||||
get_config_file_path_if_exists "$SERVER_CONFIG_DIR" "yaml"
|
||||
if [ -n "$CONFIG_PROVIDED" ]; then
|
||||
set -- "$@" --config="$CONFIG_PROVIDED"
|
||||
fi
|
||||
|
||||
mysql_note "Starting Dolt server"
|
||||
# Attempt to configure the root user directly through the sql-server using built-in environment variable support
|
||||
# The user creation queries with `dolt sql` can interfere with this process so we run them after the server is started
|
||||
DOLT_ROOT_HOST="${DOLT_ROOT_HOST:-localhost}"
|
||||
|
||||
# `dolt sql` can hold locks that prevent the server from starting during system hangs without this func
|
||||
dolt_server_initializer "$@"
|
||||
# Ran in a subshell to avoid exiting the main script, and so, we can use fallback below
|
||||
local has_correct_host
|
||||
has_correct_host=$(exec_mysql --show-result "Could not check root host: " \
|
||||
"SELECT User, Host FROM mysql.user WHERE User='root' AND Host='${DOLT_ROOT_HOST}' LIMIT 1;" | \
|
||||
grep -c "$DOLT_ROOT_HOST" || true)
|
||||
|
||||
# args or system hangs may conflict with sql-server root env vars support
|
||||
if [ "$has_correct_host" -eq 0 ]; then
|
||||
mysql_warn "Environment variables failed to initialize 'root@${DOLT_ROOT_HOST}'; docker-entrypoint-initdb.d scripts queries may have conflicted. Overriding root user..."
|
||||
exec_mysql "Could not create root user: " "CREATE USER IF NOT EXISTS 'root'@'${DOLT_ROOT_HOST}' IDENTIFIED BY '${DOLT_ROOT_PASSWORD}';" # override password
|
||||
exec_mysql "Could not set root privileges: " "GRANT ALL PRIVILEGES ON *.* TO 'root'@'${DOLT_ROOT_HOST}' WITH GRANT OPTION;"
|
||||
fi
|
||||
|
||||
create_database_from_env
|
||||
|
||||
create_user_from_env
|
||||
|
||||
exec_mysql --show-result "Could not list users: " "SELECT User, Host FROM mysql.user;"
|
||||
|
||||
if [[ ! -f $INIT_COMPLETED ]]; then
|
||||
if ls /docker-entrypoint-initdb.d/* >/dev/null 2>&1; then
|
||||
docker_process_init_files /docker-entrypoint-initdb.d/*
|
||||
else
|
||||
mysql_warn "No files found in /docker-entrypoint-initdb.d/ to process"
|
||||
fi
|
||||
touch "$INIT_COMPLETED"
|
||||
fi
|
||||
|
||||
mysql_note "Dolt init process done. Ready for connections."
|
||||
wait "$SERVER_PID"
|
||||
}
|
||||
|
||||
_main "$@"
|
||||
@@ -0,0 +1,85 @@
|
||||
# syntax=docker/dockerfile:1.3-labs
|
||||
|
||||
FROM debian:bookworm-slim AS base
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl git tini ca-certificates && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# We use bookworm since the icu dependency ver. between the base and golang images is the same
|
||||
FROM golang:1.26.2-bookworm AS build-from-source
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ARG DOLT_VERSION
|
||||
|
||||
# COPY doesn't support conditionals, so we rely on the path context to maybe have a dolt/ directory
|
||||
# to distinguish between source and binary builds using DOLT_VERSION=source too.
|
||||
COPY dolt*/go*/go.mod* /tmp/dolt/go/
|
||||
WORKDIR /tmp/dolt/go/
|
||||
|
||||
# Check for source to avoid unnecessary installation of build dependencies
|
||||
RUN if [ "$DOLT_VERSION" = "source" ]; then \
|
||||
cd /tmp/dolt/go || { echo "Make sure the `dolt/` directory exists in your workspace to build from source."; exit 1; }; \
|
||||
apt-get update -y && \
|
||||
apt-get install -y libicu-dev && \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
fi
|
||||
|
||||
# Separate layers to avoid redundant downloads
|
||||
RUN if [ "$DOLT_VERSION" = "source" ]; then \
|
||||
go mod download; \
|
||||
fi
|
||||
|
||||
COPY dolt*/go/ /tmp/dolt/go/
|
||||
|
||||
RUN if [ "$DOLT_VERSION" = "source" ]; then \
|
||||
go build -o /usr/local/bin/dolt ./cmd/dolt && \
|
||||
chmod +x /usr/local/bin/dolt; \
|
||||
fi
|
||||
|
||||
|
||||
FROM base AS download-binary
|
||||
ARG DOLT_VERSION
|
||||
RUN if [ "$DOLT_VERSION" = "latest" ]; then \
|
||||
# Fetch latest version number from GitHub API
|
||||
DOLT_VERSION=$(curl -s https://api.github.com/repos/dolthub/dolt/releases/latest \
|
||||
| grep '"tag_name"' \
|
||||
| cut -d'"' -f4 \
|
||||
| sed 's/^v//'); \
|
||||
fi && \
|
||||
if [ "$DOLT_VERSION" != "source" ]; then \
|
||||
curl -L "https://github.com/dolthub/dolt/releases/download/v${DOLT_VERSION}/install.sh" | bash; \
|
||||
fi
|
||||
|
||||
|
||||
FROM base AS runtime
|
||||
ARG DOLT_VERSION
|
||||
|
||||
RUN apt-get update -y && apt-get install -y --no-install-recommends bzip2 gzip xz-utils zstd \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# icu dependency for source builds
|
||||
RUN if [ "$DOLT_VERSION" = "source" ]; then \
|
||||
apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libicu-dev && \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
fi
|
||||
|
||||
# Only one binary is possible due to DOLT_VERSION, so we optionally copy from either stage
|
||||
COPY --from=download-binary /usr/local/bin/dolt* /usr/local/bin/
|
||||
COPY --from=build-from-source /usr/local/bin/dolt* /usr/local/bin/
|
||||
|
||||
RUN /usr/local/bin/dolt version
|
||||
|
||||
RUN mkdir /docker-entrypoint-initdb.d && \
|
||||
mkdir -p /var/lib/dolt && \
|
||||
chmod 755 /var/lib/dolt
|
||||
|
||||
COPY docker*/docker-entrypoint*.sh /usr/local/bin/
|
||||
COPY dolt*/docker*/docker-entrypoint*.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
VOLUME /var/lib/dolt
|
||||
EXPOSE 3306 33060 7007
|
||||
WORKDIR /var/lib/dolt
|
||||
ENTRYPOINT ["tini", "--", "docker-entrypoint.sh"]
|
||||
@@ -0,0 +1,184 @@
|
||||
# Dolt is Git for Data!
|
||||
|
||||
[Dolt](https://doltdb.com) is a SQL database that you can fork, clone, branch, merge, push
|
||||
and pull just like a Git repository. Connect to Dolt just like any
|
||||
MySQL database to run queries or update the data using SQL
|
||||
commands. Use the command line interface to import CSV files, commit
|
||||
your changes, push them to a remote, or merge your teammate's changes.
|
||||
|
||||
All the commands you know for Git work exactly the same for Dolt. Git
|
||||
versions files, Dolt versions tables. It's like Git and MySQL had a
|
||||
baby.
|
||||
|
||||
We also built [DoltHub](https://www.dolthub.com), a place to share
|
||||
Dolt databases. We host public data for free. If you want to host
|
||||
your own version of DoltHub, we have [DoltLab](https://www.doltlab.com). If you want us to run a Dolt server for you, we have [Hosted Dolt](https://hosted.doltdb.com).
|
||||
|
||||
[Join us on Discord](https://discord.com/invite/RFwfYpu) to say hi and
|
||||
ask questions, or [check out our roadmap](https://dolthub.com/docs/other/roadmap)
|
||||
to see what we're building next.
|
||||
|
||||
## What's it for?
|
||||
|
||||
Lots of things! Dolt is a generally useful tool with countless
|
||||
applications. But if you want some ideas, [here's how people are using
|
||||
it so far](https://www.dolthub.com/blog/2022-07-11-dolt-case-studies/).
|
||||
|
||||
# Dolt CLI
|
||||
|
||||
The `dolt` CLI has the same commands as `git`, with some extras.
|
||||
|
||||
```
|
||||
$ dolt
|
||||
Valid commands for dolt are
|
||||
init - Create an empty Dolt data repository.
|
||||
status - Show the working tree status.
|
||||
add - Add table changes to the list of staged table changes.
|
||||
diff - Diff a table.
|
||||
reset - Remove table changes from the list of staged table changes.
|
||||
clean - Remove untracked tables from working set.
|
||||
commit - Record changes to the repository.
|
||||
sql - Run a SQL query against tables in repository.
|
||||
sql-server - Start a MySQL-compatible server.
|
||||
sql-client - Starts a built-in MySQL client.
|
||||
log - Show commit logs.
|
||||
branch - Create, list, edit, delete branches.
|
||||
checkout - Checkout a branch or overwrite a table from HEAD.
|
||||
merge - Merge a branch.
|
||||
conflicts - Commands for viewing and resolving merge conflicts.
|
||||
cherry-pick - Apply the changes introduced by an existing commit.
|
||||
revert - Undo the changes introduced in a commit.
|
||||
clone - Clone from a remote data repository.
|
||||
fetch - Update the database from a remote data repository.
|
||||
pull - Fetch from a dolt remote data repository and merge.
|
||||
push - Push to a dolt remote.
|
||||
config - Dolt configuration.
|
||||
remote - Manage set of tracked repositories.
|
||||
backup - Manage a set of server backups.
|
||||
login - Login to a dolt remote host.
|
||||
creds - Commands for managing credentials.
|
||||
ls - List tables in the working set.
|
||||
schema - Commands for showing and importing table schemas.
|
||||
table - Commands for copying, renaming, deleting, and exporting tables.
|
||||
tag - Create, list, delete tags.
|
||||
blame - Show what revision and author last modified each row of a table.
|
||||
constraints - Commands for handling constraints.
|
||||
migrate - Executes a database migration to use the latest Dolt data format.
|
||||
read-tables - Fetch table(s) at a specific commit into a new dolt repo
|
||||
gc - Cleans up unreferenced data from the repository.
|
||||
filter-branch - Edits the commit history using the provided query.
|
||||
merge-base - Find the common ancestor of two commits.
|
||||
version - Displays the current Dolt cli version.
|
||||
dump - Export all tables in the working set into a file.
|
||||
```
|
||||
|
||||
Learn more about Dolt use cases, configuration and guides to use dolt on our [documentation page](https://dolthub.com/docs/introduction/what-is-dolt).
|
||||
|
||||
# How to use this image
|
||||
|
||||
This image is for Dolt SQL Server, which is similar to the MySQL Docker image. Running this image without any arguments
|
||||
is equivalent to running `dolt sql-server --host 0.0.0.0 --port 3306` command inside a Docker container.
|
||||
|
||||
To see all supported options for `dolt sql-server`, you can run the image with `--help` flag.
|
||||
|
||||
```shell
|
||||
$ docker run dolthub/dolt-sql-server:latest --help
|
||||
```
|
||||
|
||||
## Building the image
|
||||
|
||||
To build this image from source, use the `serverDockerfile`:
|
||||
|
||||
*WARNING* When building from source you cannot have any other folders that start with dolt in the same directory as
|
||||
your workspace folder. This is because we use a wildcard to conditionally copy the dolt source folder into
|
||||
the image. Other folders starting with dolt could cause the build to fail.
|
||||
|
||||
```shell
|
||||
# Build with the latest Dolt version (automatically fetches the latest release)
|
||||
$ docker build -f docker/serverDockerfile --build-arg DOLT_VERSION=latest -t dolt-sql-server:latest .
|
||||
|
||||
# Build with a specific Dolt version
|
||||
$ docker build -f docker/serverDockerfile --build-arg DOLT_VERSION=1.59.7 -t dolt-sql-server:1.59.7 .
|
||||
# Note: To run the local build replace `dolthub/dolt-sql-server:latest` with `dolt-sql-server:latest`
|
||||
```
|
||||
|
||||
## Building from Source
|
||||
|
||||
To build from your local source code instead of downloading a pre-built binary:
|
||||
|
||||
```shell
|
||||
# Build from local source code (requires workspace directory with source dependencies, e.g., dolt_workspace/)
|
||||
$ docker build -f dolt/docker/serverDockerfile --build-arg DOLT_VERSION=source -t dolt-sql-server:source .
|
||||
# Note: This should contain dolt/ at the minimum, any other repos need to be
|
||||
# added via COPY in serverDockerfile.
|
||||
|
||||
$ docker run -e DOLT_ROOT_PASSWORD=secret2 -e DOLT_ROOT_HOST=% -p 3307:3306 dolt-sql-server:source
|
||||
```
|
||||
|
||||
### Connect to the server in the container from the host system
|
||||
|
||||
From the host system, to connect to a server running in a container, we need to map a port on the host system to the port our sql-server is running on in the container.
|
||||
|
||||
We also need a user account that has permission to connect to the server
|
||||
from the host system's address. By default, as of Dolt version 1.46.0, the `root` superuser is configured to only allow connections from localhost. This is a security feature to prevent unauthorized access to the server. If you don't want to log in to the container and then connect to your sql-server, you can use the `DOLT_ROOT_HOST` and `DOLT_ROOT_PASSWORD` environment variables to control how the `root` superuser is initialized. When the Docker container is started, it will ensure the `root` superuser is configured according to those environment variables.
|
||||
|
||||
In our example below, we're using `DOLT_ROOT_HOST` to override the host of the `root` superuser account to `%` in order to allow any host to connect to our server and log in as `root`. We're also using `DOLT_ROOT_PASSWORD` to override the default, empty password and specify a password for the `root` account. Setting a password is strongly advised for security when allowing the `root` account to connect from any host.
|
||||
|
||||
```bash
|
||||
> docker run -e DOLT_ROOT_PASSWORD=secret2 -e DOLT_ROOT_HOST=% -p 3307:3306 dolthub/dolt-sql-server:latest
|
||||
```
|
||||
|
||||
If we run the command above with -d or switch to a separate window we can connect with MySQL:
|
||||
|
||||
```bash
|
||||
> mysql --host 0.0.0.0 -P 3307 -u root -p secret2
|
||||
```
|
||||
|
||||
### Define configuration for the server
|
||||
|
||||
You can specify server configuration with commandline arguments, or you can use a YAML configuration file.
|
||||
For commandline arguments, you can simply add arguments at the end of the docker command, as shown below.
|
||||
|
||||
```shell
|
||||
$ docker run -p 3307:3306 dolthub/dolt-sql-server:latest -l debug --no-auto-commit
|
||||
```
|
||||
|
||||
To use a configuration file, you can map a local directory to location in the container.
|
||||
The special directory for server configuration is `/etc/dolt/servercfg.d/`. You can only have one `.yaml` configuration
|
||||
file in this directory. If there are multiple, the default configuration will be used. If the location of
|
||||
configuration file was `/Users/jennifer/docker/server/config.yaml`, this is how to use `-v` flag which mounts
|
||||
`/Users/jennifer/docker/server/` local directory to `/etc/dolt/servercfg.d/` directory in the container.
|
||||
|
||||
```shell
|
||||
$ docker run -p 3307:3306 -v /Users/jennifer/docker/server/:/etc/dolt/servercfg.d/ dolthub/dolt-sql-server:latest
|
||||
```
|
||||
|
||||
The Dolt configuration and data directories can be configured similarly:
|
||||
|
||||
- The dolt configuration directory is `/etc/dolt/doltcfg.d/`
|
||||
There should be one `.json` Dolt configuration file. It will replace the global Dolt configuration file in the
|
||||
container.
|
||||
|
||||
- We set the location of where data to be stored to default location at `/var/lib/dolt/` in the container.
|
||||
The data directory does not need to be defined in server configuration for container, but to store the data
|
||||
on the host system, it can also be mounted to this default location.
|
||||
|
||||
```shell
|
||||
$ docker run -p 3307:3306 -v /Users/jennifer/docker/databases/:/var/lib/dolt/ dolthub/dolt-sql-server:latest
|
||||
```
|
||||
|
||||
If the run command errors out during the entrypoint process, you'll have to remove the created container from the last run.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The Dolt SQL Server image supports the following environment variables:
|
||||
|
||||
- `DOLT_ROOT_PASSWORD`: Sets the password for root (default: empty)
|
||||
- `DOLT_ROOT_HOST`: Specifies a host for the root (default: localhost)
|
||||
- `DOLT_DATABASE` / `MYSQL_DATABASE`: Creates a database with this name if it doesn't exist
|
||||
- `DOLT_USER` / `MYSQL_USER`: Creates a user with this name if it doesn't exist
|
||||
- `DOLT_PASSWORD` / `MYSQL_PASSWORD`: Sets the password for the user specified in `DOLT_USER`/`MYSQL_USER`
|
||||
- `DOLT_USER_HOST` / `MYSQL_USER_HOST`: Specifies a host for the custom user (default: falls back to `DOLT_ROOT_HOST`, then localhost)
|
||||
- `DOLT_SERVER_TIMEOUT`: Sets the server startup timeout in seconds (default: 300). A value of 0 means no timeout.
|
||||
|
||||
The user will be granted all privileges on the database specified by `DOLT_DATABASE`/`MYSQL_DATABASE` if provided.
|
||||
@@ -0,0 +1,13 @@
|
||||
if (( $+commands[dolt] )); then
|
||||
# gen-zsh writes a file to the command line, and does not output the completion script like
|
||||
# most other cli tools. For this reason, we write the file to the local directory and source it
|
||||
local completion_path=${0:h}/_dolt
|
||||
|
||||
if [[ ! -e "$completion_path" ]]; then
|
||||
# creates a completion file in the current directory
|
||||
dolt gen-zsh --file="$completion_path"
|
||||
fi
|
||||
|
||||
source "$completion_path"
|
||||
compdef _dolt dolt
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
out
|
||||
Generated
+22294
File diff suppressed because it is too large
Load Diff
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
script_dir=$(dirname "$0")
|
||||
cd $script_dir/..
|
||||
|
||||
( GOOS=linux GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=linux GOARCH=386 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=linux GOARCH=arm64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=windows GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=windows GOARCH=arm64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=darwin GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=darwin GOARCH=arm64 go list -deps -json ./cmd/dolt/.
|
||||
) \
|
||||
| go run ./utils/3pdeps/. > ./Godeps/LICENSES
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
script_dir=$(dirname "$0")
|
||||
cd $script_dir/..
|
||||
|
||||
( GOOS=linux GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=linux GOARCH=386 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=linux GOARCH=arm64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=windows GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=windows GOARCH=arm64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=darwin GOARCH=amd64 go list -deps -json ./cmd/dolt/. &&
|
||||
GOOS=darwin GOARCH=arm64 go list -deps -json ./cmd/dolt/.
|
||||
) \
|
||||
| go run ./utils/3pdeps/. -verify ./Godeps/LICENSES
|
||||
@@ -0,0 +1,79 @@
|
||||
// Copyright 2019 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
var ErrEmptyDefTuple = errors.New("empty definition tuple")
|
||||
|
||||
type UsagePrinter func()
|
||||
|
||||
// ParseArgs is used for Dolt SQL functions that are run on the server and should not exit
|
||||
func ParseArgs(ap *argparser.ArgParser, args []string, usagePrinter UsagePrinter) (*argparser.ArgParseResults, error) {
|
||||
apr, err := ap.Parse(args)
|
||||
|
||||
if err != nil {
|
||||
// --help param
|
||||
if usagePrinter != nil {
|
||||
usagePrinter()
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return apr, nil
|
||||
}
|
||||
|
||||
// ParseArgsOrDie is used for CLI command that should exit after erroring.
|
||||
func ParseArgsOrDie(ap *argparser.ArgParser, args []string, usagePrinter UsagePrinter) *argparser.ArgParseResults {
|
||||
apr, err := ap.Parse(args)
|
||||
|
||||
if err != nil {
|
||||
if err != argparser.ErrHelp {
|
||||
PrintErrln(err.Error())
|
||||
|
||||
if usagePrinter != nil {
|
||||
usagePrinter()
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// --help param
|
||||
if usagePrinter != nil {
|
||||
usagePrinter()
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return apr
|
||||
}
|
||||
|
||||
func HelpAndUsagePrinters(cmdDoc *CommandDocumentation) (UsagePrinter, UsagePrinter) {
|
||||
// TODO handle error states
|
||||
longDesc, _ := cmdDoc.GetLongDesc(CliFormat)
|
||||
synopsis, _ := cmdDoc.GetSynopsis(CliFormat)
|
||||
|
||||
return func() {
|
||||
PrintHelpText(cmdDoc.CommandStr, cmdDoc.GetShortDesc(), longDesc, synopsis, cmdDoc.ArgParser)
|
||||
}, func() {
|
||||
PrintUsage(cmdDoc.CommandStr, synopsis, cmdDoc.ArgParser)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dconfig"
|
||||
)
|
||||
|
||||
func TestParseDate(t *testing.T) {
|
||||
tests := []struct {
|
||||
dateStr string
|
||||
expTime time.Time
|
||||
expErr bool
|
||||
}{
|
||||
{"1901/09/30", time.Date(1901, 9, 30, 0, 0, 0, 0, time.UTC), false},
|
||||
{"2019/01/20", time.Date(2019, 1, 20, 0, 0, 0, 0, time.UTC), false},
|
||||
{"2019-1-20", time.Date(2019, 1, 20, 0, 0, 0, 0, time.UTC), true},
|
||||
{"2019.01.20", time.Date(2019, 1, 20, 0, 0, 0, 0, time.UTC), false},
|
||||
{"2019/01/20T13:49:59", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), false},
|
||||
{"2019-01-20T13:49:59", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), false},
|
||||
{"2019.01.20T13:49:59", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), false},
|
||||
{"2019.01.20T13:49", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), true},
|
||||
{"2019.01.20T13", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), true},
|
||||
{"2019.01", time.Date(2019, 1, 20, 13, 49, 59, 0, time.UTC), true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.dateStr, func(t *testing.T) {
|
||||
result, err := dconfig.ParseDate(test.dateStr)
|
||||
|
||||
if test.expErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, result, test.expTime)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAuthor(t *testing.T) {
|
||||
tests := []struct {
|
||||
authorStr string
|
||||
expName string
|
||||
expEmail string
|
||||
expErr bool
|
||||
}{
|
||||
{"Hi <hi@hi.com>", "Hi", "hi@hi.com", false},
|
||||
{"John Doe <hi@hi.com>", "John Doe", "hi@hi.com", false},
|
||||
{"John Doe <hi@hi.com", "John Doe", "hi@hi.com", false},
|
||||
{"John Doe", "", "", true},
|
||||
{"<hi@hi.com>", "", "", true},
|
||||
{"", "", "", true},
|
||||
{"John Doe hi@hi.com", "", "", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.authorStr, func(t *testing.T) {
|
||||
author, email, err := ParseAuthor(test.authorStr)
|
||||
|
||||
if test.expErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, author, test.expName)
|
||||
assert.Equal(t, email, test.expEmail)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
// Copyright 2020 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/dbfactory"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/argparser"
|
||||
)
|
||||
|
||||
const VerboseFlag = "verbose"
|
||||
|
||||
// Parses the author flag for the commit method.
|
||||
func ParseAuthor(authorStr string) (string, string, error) {
|
||||
if len(authorStr) == 0 {
|
||||
return "", "", errors.New("Option 'author' requires a value")
|
||||
}
|
||||
|
||||
reg := regexp.MustCompile("(?m)([^)]+) \\<([^)]+)") // Regex matches Name <email
|
||||
matches := reg.FindStringSubmatch(authorStr) // This function places the original string at the beginning of matches
|
||||
|
||||
// If name and email are provided
|
||||
if len(matches) != 3 {
|
||||
return "", "", errors.New("Author not formatted correctly. Use 'Name <author@example.com>' format")
|
||||
}
|
||||
|
||||
name := matches[1]
|
||||
email := strings.ReplaceAll(matches[2], ">", "")
|
||||
|
||||
return name, email, nil
|
||||
}
|
||||
|
||||
var branchForceFlagDesc = "Reset {{.LessThan}}branchname{{.GreaterThan}} to {{.LessThan}}startpoint{{.GreaterThan}}, even if {{.LessThan}}branchname{{.GreaterThan}} exists already. Without {{.EmphasisLeft}}-f{{.EmphasisRight}}, {{.EmphasisLeft}}dolt branch{{.EmphasisRight}} refuses to change an existing branch. In combination with {{.EmphasisLeft}}-d{{.EmphasisRight}} (or {{.EmphasisLeft}}--delete{{.EmphasisRight}}), allow deleting the branch irrespective of its merged status. In combination with -m (or {{.EmphasisLeft}}--move{{.EmphasisRight}}), allow renaming the branch even if the new branch name already exists, the same applies for {{.EmphasisLeft}}-c{{.EmphasisRight}} (or {{.EmphasisLeft}}--copy{{.EmphasisRight}})."
|
||||
|
||||
// CreateCommitArgParser creates the argparser shared dolt commit cli and DOLT_COMMIT.
|
||||
func CreateCommitArgParser(supportsBranchFlag bool) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("commit", 0)
|
||||
ap.SupportsString(MessageArg, "m", "msg", "Use the given {{.LessThan}}msg{{.GreaterThan}} as the commit message.")
|
||||
ap.SupportsFlag(AllowEmptyFlag, "", "Allow recording a commit that has the exact same data as its sole parent. This is usually a mistake, so it is disabled by default. This option bypasses that safety. Cannot be used with --skip-empty.")
|
||||
ap.SupportsFlag(SkipEmptyFlag, "", "Only create a commit if there are staged changes. If no changes are staged, the call to commit is a no-op. Cannot be used with --allow-empty.")
|
||||
ap.SupportsString(DateParam, "", "date", "Specify the date used in the commit. If not specified the current system time is used.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "Ignores any foreign key warnings and proceeds with the commit.")
|
||||
ap.SupportsString(AuthorParam, "", "author", "Specify an explicit author using the standard A U Thor {{.LessThan}}author@example.com{{.GreaterThan}} format.")
|
||||
ap.SupportsFlag(AllFlag, "a", "Adds all existing, changed tables (but not new tables) in the working set to the staged set.")
|
||||
ap.SupportsFlag(UpperCaseAllFlag, "A", "Adds all tables and databases (including new tables) in the working set to the staged set.")
|
||||
ap.SupportsFlag(AmendFlag, "", "Amend previous commit")
|
||||
ap.SupportsOptionalString(SignFlag, "S", "key-id", "Sign the commit using GPG. If no key-id is provided the key-id is taken from 'user.signingkey' the in the configuration")
|
||||
ap.SupportsFlag(SkipVerificationFlag, "", "Skip commit verification")
|
||||
if supportsBranchFlag {
|
||||
ap.SupportsString(BranchParam, "", "branch", "Commit to the specified branch instead of the current branch.")
|
||||
}
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateConflictsResolveArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("conflicts resolve")
|
||||
ap.SupportsFlag(OursFlag, "", "For all conflicts, take the version from our branch and resolve the conflict")
|
||||
ap.SupportsFlag(TheirsFlag, "", "For all conflicts, take the version from their branch and resolve the conflict")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateUpdateTagArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("update-tag", 3)
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"table", "The name of the table"})
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"column", "The name of the column"})
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"tag", "The new tag value"})
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateMergeArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("merge", 1)
|
||||
ap.TooManyArgsErrorFunc = func(receivedArgs []string) error {
|
||||
return errors.New("Error: Dolt does not support merging from multiple commits. You probably meant to checkout one and then merge from the other.")
|
||||
}
|
||||
ap.SupportsFlag(NoFFParam, "", "Create a merge commit even when the merge resolves as a fast-forward.")
|
||||
ap.SupportsFlag(FFOnlyParam, "", "Refuse to merge unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.")
|
||||
ap.SupportsFlag(SquashParam, "", "Merge changes to the working set without updating the commit history")
|
||||
ap.SupportsString(MessageArg, "m", "msg", "Use the given {{.LessThan}}msg{{.GreaterThan}} as the commit message.")
|
||||
ap.SupportsFlag(AbortParam, "", "Abort the in-progress merge and return the working set to the state before the merge started.")
|
||||
ap.SupportsFlag(CommitFlag, "", "Perform the merge and commit the result. This is the default option, but can be overridden with the --no-commit flag. Note that this option does not affect fast-forward merges, which don't create a new merge commit, and if any merge conflicts or constraint violations are detected, no commit will be attempted.")
|
||||
ap.SupportsFlag(NoCommitFlag, "", "Perform the merge and stop just before creating a merge commit. Note this will not prevent a fast-forward merge; use the --no-ff arg together with the --no-commit arg to prevent both fast-forwards and merge commits.")
|
||||
ap.SupportsFlag(NoEditFlag, "", "Use an auto-generated commit message when creating a merge commit. The default for interactive CLI sessions is to open an editor.")
|
||||
ap.SupportsString(AuthorParam, "", "author", "Specify an explicit author using the standard A U Thor {{.LessThan}}author@example.com{{.GreaterThan}} format.")
|
||||
ap.SupportsFlag(SkipVerificationFlag, "", "Skip commit verification before merge")
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateStashArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("stash", 3)
|
||||
ap.SupportsFlag(IncludeUntrackedFlag, "u", "Untracked tables are also stashed.")
|
||||
ap.SupportsFlag(AllFlag, "a", "All tables are stashed, including untracked and ignored tables.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateRebaseArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("rebase", 1)
|
||||
ap.TooManyArgsErrorFunc = func(receivedArgs []string) error {
|
||||
return errors.New("rebase takes at most one positional argument.")
|
||||
}
|
||||
ap.SupportsString(EmptyParam, "", "empty", "How to handle commits that are not empty to start, but which become empty after rebasing. Valid values are: drop (default) or keep")
|
||||
ap.SupportsFlag(AbortParam, "", "Abort an interactive rebase and return the working set to the pre-rebase state")
|
||||
ap.SupportsFlag(ContinueFlag, "", "Continue an interactive rebase after adjusting the rebase plan")
|
||||
ap.SupportsFlag(InteractiveFlag, "i", "Start an interactive rebase")
|
||||
ap.SupportsFlag(SkipVerificationFlag, "", "Skip commit verification before rebase")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreatePushArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("push")
|
||||
ap.SupportsString(UserFlag, "", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.")
|
||||
ap.SupportsFlag(SetUpstreamFlag, "u", "For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less {{.EmphasisLeft}}dolt pull{{.EmphasisRight}} and other commands.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "Update the remote with local history, overwriting any conflicting history in the remote.")
|
||||
ap.SupportsFlag(AllFlag, "", "Push all branches.")
|
||||
ap.SupportsFlag(SilentFlag, "", "Suppress progress information.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateAddArgParser(supportsBranchFlag bool) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("add")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"table", "Working table(s) to add to the list tables staged to be committed. The abbreviation '.' can be used to add all tables."})
|
||||
ap.SupportsFlag(AllFlag, "A", "Stages any and all changes (adds, deletes, and modifications) except for ignored tables.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "Allow adding otherwise ignored tables.")
|
||||
if supportsBranchFlag {
|
||||
ap.SupportsString(BranchParam, "", "branch", "Add to the specified branch instead of the current branch.")
|
||||
}
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCloneArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("clone", 2)
|
||||
ap.SupportsString(RemoteParam, "", "name", "Name of the remote to be added to the cloned database. The default is 'origin'.")
|
||||
ap.SupportsString(BranchParam, "b", "branch", "The branch to be cloned. If not specified all branches will be cloned.")
|
||||
ap.SupportsString(DepthFlag, "", "depth", "Clone a single branch and limit history to the given commit depth.")
|
||||
ap.SupportsString("ref", "", "ref", "Git ref to use as the Dolt data ref for git remotes (default: refs/dolt/data).")
|
||||
ap.SupportsString(dbfactory.AWSRegionParam, "", "region", "")
|
||||
ap.SupportsValidatedString(dbfactory.AWSCredsTypeParam, "", "creds-type", "", argparser.ValidatorFromStrList(dbfactory.AWSCredsTypeParam, dbfactory.AWSCredTypes))
|
||||
ap.SupportsString(dbfactory.AWSCredsFileParam, "", "file", "AWS credentials file.")
|
||||
ap.SupportsString(dbfactory.AWSCredsProfile, "", "profile", "AWS profile to use.")
|
||||
ap.SupportsString(dbfactory.OSSCredsFileParam, "", "file", "OSS credentials file.")
|
||||
ap.SupportsString(dbfactory.OSSCredsProfile, "", "profile", "OSS profile to use.")
|
||||
ap.SupportsString(UserFlag, "u", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.")
|
||||
ap.SupportsFlag(SingleBranchFlag, "", "Clone only the history leading to the tip of a single branch, either specified by --branch or the remote's HEAD (default).")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateResetArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("reset")
|
||||
ap.SupportsFlag(HardResetParam, "", "Resets the working tables and staged tables. Any changes to tracked tables in the working tree since {{.LessThan}}commit{{.GreaterThan}} are discarded.")
|
||||
ap.SupportsFlag(SoftResetParam, "", "Resets HEAD to the specified revision without touching the index or the working tables.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateRemoteArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("remote")
|
||||
ap.SupportsString("ref", "", "ref", "Git ref to use as the Dolt data ref for git remotes (default: refs/dolt/data).")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCleanArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("clean")
|
||||
ap.SupportsFlag(DryRunFlag, "", "Tests removing untracked tables without modifying the working set.")
|
||||
ap.SupportsFlag(ExcludeIgnoreRulesFlag, "x", "Do not respect dolt_ignore; remove untracked tables that match dolt_ignore. dolt_nonlocal_tables is always respected.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCheckoutArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("checkout")
|
||||
ap.SupportsString(CheckoutCreateBranch, "", "branch", "Create a new branch named {{.LessThan}}new_branch{{.GreaterThan}} and start it at {{.LessThan}}start_point{{.GreaterThan}}.")
|
||||
ap.SupportsString(CreateResetBranch, "", "branch", "Similar to '-b'. Forcibly resets the branch to {{.LessThan}}start_point{{.GreaterThan}} if it exists.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "If there is any changes in working set, the force flag will wipe out the current changes and checkout the new branch.")
|
||||
ap.SupportsString(TrackFlag, "t", "", "When creating a new branch, set up 'upstream' configuration.")
|
||||
ap.SupportsFlag(OverwriteIgnoreFlag, "", "Silently overwrite ignored tables when switching branches (default behavior).")
|
||||
ap.SupportsFlag(NoOverwriteIgnoreFlag, "", "Abort the operation when ignored tables in the working set would be overwritten by the checkout.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCherryPickArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("cherrypick", 1)
|
||||
ap.SupportsFlag(AbortParam, "", "Abort the current conflict resolution process, and revert all changes from the in-process cherry-pick operation.")
|
||||
ap.SupportsFlag(ContinueFlag, "", "Continue the current cherry-pick operation after conflicts have been resolved.")
|
||||
ap.SupportsFlag(AllowEmptyFlag, "", "Allow empty commits to be cherry-picked. "+
|
||||
"Note that use of this option only keeps commits that were initially empty. "+
|
||||
"Commits which become empty, due to a previous commit, will cause cherry-pick to fail.")
|
||||
ap.SupportsFlag(SkipVerificationFlag, "", "Skip commit verification before cherry-pick")
|
||||
ap.TooManyArgsErrorFunc = func(receivedArgs []string) error {
|
||||
return errors.New("cherry-picking multiple commits is not supported yet.")
|
||||
}
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateFetchArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("fetch")
|
||||
ap.SupportsString(UserFlag, "", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.")
|
||||
ap.SupportsFlag(PruneFlag, "p", "After fetching, remove any remote-tracking references that don't exist on the remote.")
|
||||
ap.SupportsFlag(SilentFlag, "", "Suppress progress information.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateRevertArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("revert")
|
||||
ap.SupportsString(AuthorParam, "", "author", "Specify an explicit author using the standard A U Thor {{.LessThan}}author@example.com{{.GreaterThan}} format.")
|
||||
ap.SupportsFlag(AbortParam, "", "Abort the current revert operation and return the working set to the pre-revert state.")
|
||||
ap.SupportsFlag(ContinueFlag, "", "Continue the current revert operation after resolving conflicts.")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"revision",
|
||||
"The commit revisions. If multiple revisions are given, they're applied in the order given."})
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreatePullArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("pull", 2)
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"remote", "The name of the remote to pull from."})
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"remoteBranch", "The name of a branch on the specified remote to be merged into the current working set."})
|
||||
ap.SupportsFlag(SquashParam, "", "Merge changes to the working set without updating the commit history")
|
||||
ap.SupportsFlag(NoFFParam, "", "Create a merge commit even when the merge resolves as a fast-forward.")
|
||||
ap.SupportsFlag(FFOnlyParam, "", "Refuse to merge unless the current HEAD is already up to date or the merge can be resolved as a fast-forward.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "Update from the remote HEAD even if there are errors.")
|
||||
ap.SupportsFlag(CommitFlag, "", "Perform the merge and commit the result. This is the default option, but can be overridden with the --no-commit flag. Note that this option does not affect fast-forward merges, which don't create a new merge commit, and if any merge conflicts or constraint violations are detected, no commit will be attempted.")
|
||||
ap.SupportsFlag(NoCommitFlag, "", "Perform the merge and stop just before creating a merge commit. Note this will not prevent a fast-forward merge; use the --no-ff arg together with the --no-commit arg to prevent both fast-forwards and merge commits.")
|
||||
ap.SupportsFlag(NoEditFlag, "", "Use an auto-generated commit message when creating a merge commit. The default for interactive CLI sessions is to open an editor.")
|
||||
ap.SupportsString(UserFlag, "", "user", "User name to use when authenticating with the remote. Gets password from the environment variable {{.EmphasisLeft}}DOLT_REMOTE_PASSWORD{{.EmphasisRight}}.")
|
||||
ap.SupportsFlag(PruneFlag, "p", "After fetching, remove any remote-tracking references that don't exist on the remote.")
|
||||
ap.SupportsFlag(RebaseParam, "r", "After fetching, rebase the current branch on top of the upstream branch instead of merging.")
|
||||
ap.SupportsFlag(SilentFlag, "", "Suppress progress information.")
|
||||
ap.SupportsFlag(SkipVerificationFlag, "", "Skip commit verification before merge")
|
||||
return ap
|
||||
}
|
||||
|
||||
func createTracklessBranchArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("branch")
|
||||
ap.SupportsFlag(ForceFlag, "f", branchForceFlagDesc)
|
||||
ap.SupportsFlag(CopyFlag, "c", "Create a copy of a branch.")
|
||||
ap.SupportsFlag(MoveFlag, "m", "Move/rename a branch")
|
||||
ap.SupportsFlag(DeleteFlag, "d", "Delete a branch. The branch must be fully merged in its upstream branch.")
|
||||
ap.SupportsFlag(DeleteForceFlag, "", "Shortcut for {{.EmphasisLeft}}--delete --force{{.EmphasisRight}}.")
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateBranchArgParser() *argparser.ArgParser {
|
||||
ap := createTracklessBranchArgParser()
|
||||
ap.SupportsFlag(TrackFlag, "t", "Set up upstream configuration for a branch. Uses current branch as default")
|
||||
ap.SupportsString(SetUpstreamToFlag, "u", "", "Set upstream configuration for a branch.")
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateTagArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("tag")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"ref", "A commit ref that the tag should point at."})
|
||||
ap.SupportsString(MessageArg, "m", "msg", "Use the given {{.LessThan}}msg{{.GreaterThan}} as the tag message.")
|
||||
ap.SupportsFlag(VerboseFlag, "v", "list tags along with their metadata.")
|
||||
ap.SupportsFlag(DeleteFlag, "d", "Delete a tag.")
|
||||
ap.SupportsString(AuthorParam, "", "author", "Specify an explicit author using the standard A U Thor {{.LessThan}}author@example.com{{.GreaterThan}} format.")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateBackupArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("backup")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"region", "cloud provider region associated with this backup."})
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"creds-type", "credential type. Valid options are role, env, and file. See the help section for additional details."})
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"profile", "AWS profile to use."})
|
||||
ap.SupportsFlag(VerboseFlag, "v", "When printing the list of backups adds additional details.")
|
||||
ap.SupportsFlag(ForceFlag, "f", "When restoring a backup, overwrite the contents of the existing database with the same name.")
|
||||
ap.SupportsString("ref", "", "ref", "Git ref to use as the Dolt data ref for git remotes (default: refs/dolt/data).")
|
||||
ap.SupportsString(dbfactory.AWSRegionParam, "", "region", "")
|
||||
ap.SupportsValidatedString(dbfactory.AWSCredsTypeParam, "", "creds-type", "", argparser.ValidatorFromStrList(dbfactory.AWSCredsTypeParam, dbfactory.AWSCredTypes))
|
||||
ap.SupportsString(dbfactory.AWSCredsFileParam, "", "file", "AWS credentials file")
|
||||
ap.SupportsString(dbfactory.AWSCredsProfile, "", "profile", "AWS profile to use")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateVerifyConstraintsArgParser(name string) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs(name)
|
||||
ap.SupportsFlag(AllFlag, "a", "Verifies that all rows in the database do not violate constraints instead of just rows modified or inserted in the working set.")
|
||||
ap.SupportsFlag(OutputOnlyFlag, "o", "Disables writing violated constraints to the constraint violations table.")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"table", "The table(s) to check constraints on. If omitted, checks all tables."})
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateLogArgParser(isTableFunction bool) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("log")
|
||||
ap.SupportsInt(NumberFlag, "n", "num_commits", "Limit the number of commits to output.")
|
||||
ap.SupportsInt(MinParentsFlag, "", "parent_count", "The minimum number of parents a commit must have to be included in the log.")
|
||||
ap.SupportsFlag(MergesFlag, "", "Equivalent to min-parents == 2, this will limit the log to commits with 2 or more parents.")
|
||||
ap.SupportsFlag(ParentsFlag, "", "Shows all parents of each commit in the log.")
|
||||
ap.SupportsString(DecorateFlag, "", "decorate_fmt", "Shows refs next to commits. Valid options are short, full, no, and auto")
|
||||
ap.SupportsStringList(NotFlag, "", "revision", "Excludes commits from revision.")
|
||||
ap.SupportsFlag(AllFlag, "", "Automatically select every branch in database")
|
||||
ap.SupportsFlag(ShowSignatureFlag, "", "Shows the signature of each commit.")
|
||||
if isTableFunction {
|
||||
ap.SupportsStringList(TablesFlag, "t", "table", "Restricts the log to commits that modified the specified tables.")
|
||||
} else {
|
||||
ap.SupportsFlag(OneLineFlag, "", "Shows logs in a compact format.")
|
||||
ap.SupportsFlag(StatFlag, "", "Shows the diffstat for each commit.")
|
||||
ap.SupportsFlag(GraphFlag, "", "Shows the commit graph.")
|
||||
}
|
||||
return ap
|
||||
}
|
||||
|
||||
// Values accepted by the --decorate flag. DecorateShort trims ref prefixes,
|
||||
// DecorateFull keeps refs/heads/, refs/remotes/, and refs/tags/, DecorateNo
|
||||
// produces an empty refs column, and DecorateAuto resolves to DecorateShort
|
||||
// on a tty and DecorateNo otherwise.
|
||||
const (
|
||||
DecorateAuto = "auto"
|
||||
DecorateShort = "short"
|
||||
DecorateFull = "full"
|
||||
DecorateNo = "no"
|
||||
)
|
||||
|
||||
// ValidateDecorateOption returns nil when |value| is accepted by the --decorate flag.
|
||||
func ValidateDecorateOption(value string) error {
|
||||
switch value {
|
||||
case DecorateShort, DecorateFull, DecorateAuto, DecorateNo:
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid --%s option: %q", DecorateFlag, value)
|
||||
}
|
||||
|
||||
func CreateDiffArgParser(isTableFunction bool) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("diff")
|
||||
ap.SupportsFlag(SkinnyFlag, "sk", "Shows only primary key columns and any columns with data changes.")
|
||||
ap.SupportsStringList(IncludeCols, "ic", "columns", "A list of columns to include in the diff.")
|
||||
if !isTableFunction { // TODO: support for table function
|
||||
ap.SupportsFlag(DataFlag, "d", "Show only the data changes, do not show the schema changes (Both shown by default).")
|
||||
ap.SupportsFlag(SchemaFlag, "s", "Show only the schema changes, do not show the data changes (Both shown by default).")
|
||||
ap.SupportsFlag(StatFlag, "", "Show stats of data changes")
|
||||
ap.SupportsFlag(SummaryFlag, "", "Show summary of data and schema changes")
|
||||
ap.SupportsString(FormatFlag, "r", "result output format", "How to format diff output. Valid values are tabular, sql, json. Defaults to tabular.")
|
||||
ap.SupportsString(WhereParam, "", "column", "filters columns based on values in the diff. See {{.EmphasisLeft}}dolt diff --help{{.EmphasisRight}} for details.")
|
||||
ap.SupportsInt(LimitParam, "", "record_count", "limits to the first N diffs.")
|
||||
ap.SupportsString(FilterParam, "", "diff_type", "filters results based on the type of change (added, modified, renamed, dropped). 'removed' is accepted as an alias for 'dropped'.")
|
||||
ap.SupportsFlag(StagedFlag, "", "Show only the staged data changes.")
|
||||
ap.SupportsFlag(CachedFlag, "c", "Synonym for --staged")
|
||||
ap.SupportsFlag(MergeBase, "", "Uses merge base of the first commit and second commit (or HEAD if not supplied) as the first commit")
|
||||
ap.SupportsString(DiffMode, "", "diff mode", "Determines how to display modified rows with tabular output. Valid values are row, line, in-place, context. Defaults to context.")
|
||||
ap.SupportsFlag(ReverseFlag, "R", "Reverses the direction of the diff.")
|
||||
ap.SupportsFlag(NameOnlyFlag, "", "Only shows table names.")
|
||||
ap.SupportsFlag(SystemFlag, "", "Show system tables in addition to user tables")
|
||||
}
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateGCArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("gc", 0)
|
||||
ap.SupportsFlag(ShallowFlag, "s", "perform a fast, but incomplete garbage collection pass")
|
||||
ap.SupportsFlag(FullFlag, "f", "perform a full garbage collection, including the old generation")
|
||||
ap.SupportsInt(ArchiveLevelParam, "", "archive compression level", "Specify the archive compression level garbage collection results. Default is 1, Disable with 0")
|
||||
ap.SupportsUint(IncrementalGCFileSize, "", "", "max size in bytes of incremental GC table files")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCountCommitsArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("gc", 0)
|
||||
ap.SupportsString("from", "f", "commit id", "commit to start counting from")
|
||||
ap.SupportsString("to", "t", "commit id", "commit to stop counting at")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateReflogArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("reflog", 1)
|
||||
ap.SupportsFlag(AllFlag, "", "Show all refs, including hidden refs, such as DoltHub workspace refs")
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateRmArgParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs("rm")
|
||||
ap.ArgListHelp = append(ap.ArgListHelp, [2]string{"table", "table(s) to remove from the list of tables staged to be committed."})
|
||||
ap.SupportsFlag(CachedFlag, "", "Use this option to unstage and remove tables only from the index. Working tree tables, whether modified or not, will be left alone.") //TODO
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateCreateCommitParser() *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithMaxArgs("createchunk commit", 0)
|
||||
ap.SupportsString(AuthorParam, "", "author", "Specify an explicit author using the standard A U Thor {{.LessThan}}author@example.com{{.GreaterThan}} format.")
|
||||
ap.SupportsString("desc", "", "commit description", "the description in the commit")
|
||||
|
||||
ap.SupportsFlag(ForceFlag, "", "when used alongside --branch, allows overwriting an existing branch")
|
||||
ap.SupportsRequiredString("root", "", "database root", "the root hash of the database at this commit")
|
||||
ap.SupportsStringList("parents", "", "parent commits", "a list of the commit hashes of the parent commit")
|
||||
ap.SupportsString(BranchParam, "", "ref to assign to", "if set, the new commit will be reachable at this ref")
|
||||
|
||||
return ap
|
||||
}
|
||||
|
||||
func CreateGlobalArgParser(name string) *argparser.ArgParser {
|
||||
ap := argparser.NewArgParserWithVariableArgs(name)
|
||||
if name == "dolt" {
|
||||
ap.SupportsString("profile", "", "profile", "The name of the profile to use when executing SQL queries. Run `dolt profile --help` for more information.")
|
||||
}
|
||||
ap.SupportsString("user", "u", "user", "Defines the local superuser (defaults to `root`). If the specified user exists, will take on permissions of that user.")
|
||||
ap.SupportsString("password", "p", "password", "Defines the password for the user. Defaults to empty string when the user is `root`.")
|
||||
ap.SupportsString("host", "", "host", "Defines the host to connect to.")
|
||||
ap.SupportsString("port", "", "port", "Defines the port to connect to.")
|
||||
ap.SupportsFlag("no-tls", "", "Disables TLS for the connection to remote databases.")
|
||||
ap.SupportsString("data-dir", "", "data-dir", "Defines a data directory whose subdirectories should all be dolt data repositories accessible as independent databases. Defaults to the current directory.")
|
||||
ap.SupportsString("doltcfg-dir", "", "doltcfg-dir", "Defines a directory that contains configuration files for dolt. Defaults to `$data-dir/.doltcfg`. Will only be created if there is a change to configuration settings.")
|
||||
ap.SupportsString("privilege-file", "", "privilege-file", "Path to a file to load and store users and grants. Defaults to `$doltcfg-dir/privileges.db`. Will only be created if there is a change to privileges.")
|
||||
ap.SupportsString("branch-control-file", "", "branch-control-file", "Path to a file to load and store branch control permissions. Defaults to `$doltcfg-dir/branch_control.db`. Will only be created if there is a change to branch control permissions.")
|
||||
ap.SupportsString("use-db", "", "use-db", "The name of the database to use when executing SQL queries. Defaults the database of the root directory, if it exists, and the first alphabetically if not.")
|
||||
ap.SupportsString("branch", "", "branch", "Name of the branch to be selected")
|
||||
return ap
|
||||
}
|
||||
|
||||
var AwsParams = []string{dbfactory.AWSRegionParam, dbfactory.AWSCredsTypeParam, dbfactory.AWSCredsFileParam, dbfactory.AWSCredsProfile}
|
||||
var ossParams = []string{dbfactory.OSSCredsFileParam, dbfactory.OSSCredsProfile}
|
||||
|
||||
func AddAWSParams(remoteUrl string, apr *argparser.ArgParseResults, params map[string]string) error {
|
||||
isAWS := strings.HasPrefix(remoteUrl, "aws")
|
||||
|
||||
if !isAWS {
|
||||
for _, p := range AwsParams {
|
||||
if _, ok := apr.GetValue(p); ok {
|
||||
return fmt.Errorf("%s param is only valid for aws cloud remotes in the format aws://dynamo-table:s3-bucket/database", p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range AwsParams {
|
||||
if val, ok := apr.GetValue(p); ok {
|
||||
params[p] = val
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddOSSParams(remoteUrl string, apr *argparser.ArgParseResults, params map[string]string) error {
|
||||
isOSS := strings.HasPrefix(remoteUrl, "oss")
|
||||
|
||||
if !isOSS {
|
||||
for _, p := range ossParams {
|
||||
if _, ok := apr.GetValue(p); ok {
|
||||
return fmt.Errorf("%s param is only valid for oss cloud remotes in the format oss://oss-bucket/database", p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range ossParams {
|
||||
if val, ok := apr.GetValue(p); ok {
|
||||
params[p] = val
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyNoAwsParams(apr *argparser.ArgParseResults) error {
|
||||
if awsParams := apr.GetValues(AwsParams...); len(awsParams) > 0 {
|
||||
awsParamKeys := make([]string, 0, len(awsParams))
|
||||
for k := range awsParams {
|
||||
awsParamKeys = append(awsParamKeys, k)
|
||||
}
|
||||
|
||||
keysStr := strings.Join(awsParamKeys, ",")
|
||||
return fmt.Errorf("The parameters %s, are only valid for aws remotes", keysStr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyCommitArgs validates the arguments in |apr| for `dolt commit` and returns an error
|
||||
// if any validation problems were encountered.
|
||||
func VerifyCommitArgs(apr *argparser.ArgParseResults) error {
|
||||
if apr.Contains(AllowEmptyFlag) && apr.Contains(SkipEmptyFlag) {
|
||||
return errors.New("error: cannot use both --allow-empty and --skip-empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright 2023 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/errhand"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/argparser"
|
||||
"github.com/dolthub/dolt/go/libraries/utils/filesys"
|
||||
)
|
||||
|
||||
type LateBindQueryistResult struct {
|
||||
Queryist Queryist
|
||||
Context *sql.Context
|
||||
IsRemote bool
|
||||
Closer func()
|
||||
}
|
||||
|
||||
type LateBindQueryistConfig struct {
|
||||
EnableAutoGC bool
|
||||
}
|
||||
|
||||
type LateBindQueryistOption func(*LateBindQueryistConfig)
|
||||
|
||||
// LateBindQueryist is a function that will be called the first time Queryist is needed for use. Input is a context which
|
||||
// is appropriate for the call to commence. Output is a LateBindQueryistResult, which includes a Queryist, a sql.Context, and
|
||||
// a closer function. It can also result in an error.
|
||||
//
|
||||
// The Closer function should be called when the Queryist is no longer needed. If the result is cached and returned to
|
||||
// multiple callers, it should be called after the cached result itself is no longer needed.
|
||||
//
|
||||
// A LateBindqueryistResult includes enough information for a caller to know if it is connecting to a remote Dolt instance
|
||||
// or if it running the SqlEngine locally in-process. The CliContext uses this, in addition to its own local state, to
|
||||
// let a caller know if they are connected to a remote and if this is the first QueryEngine fetch of the process lifecycle.
|
||||
// This is reflected in |IsRemote| and, in the case of QueryEngineResult, |IsFirstUse|.
|
||||
//
|
||||
// This state is useful for determining whether a command making use of the CliContext is being run within the context of
|
||||
// another command. This is particularly interesting when running a \checkout in a dolt sql session. It makes sense to do
|
||||
// so in the context of `dolt sql`, but not in the context of `dolt checkout` when connected to a remote server.
|
||||
type LateBindQueryist func(ctx context.Context, opts ...LateBindQueryistOption) (LateBindQueryistResult, error)
|
||||
|
||||
// CliContexct is used to pass top level command information down to subcommands.
|
||||
type CliContext interface {
|
||||
// GlobalArgs returns the arguments passed before the subcommand.
|
||||
GlobalArgs() *argparser.ArgParseResults
|
||||
WorkingDir() filesys.Filesys
|
||||
Config() *env.DoltCliConfig
|
||||
QueryEngine(ctx context.Context, opts ...LateBindQueryistOption) (QueryEngineResult, error)
|
||||
// Release resources associated with the CliContext, including
|
||||
// any QueryEngines which were provisioned over the lifetime
|
||||
// of the CliContext.
|
||||
Close()
|
||||
}
|
||||
|
||||
// NewCliContext creates a new CliContext instance. Arguments must not be nil.
|
||||
func NewCliContext(args *argparser.ArgParseResults, config *env.DoltCliConfig, cwd filesys.Filesys, latebind LateBindQueryist) (CliContext, errhand.VerboseError) {
|
||||
if args == nil || config == nil || cwd == nil || latebind == nil {
|
||||
return nil, errhand.VerboseErrorFromError(errors.New("Invariant violated. args, config, cwd, and latebind must be non nil."))
|
||||
}
|
||||
|
||||
return LateBindCliContext{
|
||||
globalArgs: args,
|
||||
config: config,
|
||||
cwd: cwd,
|
||||
activeContext: &QueryistContext{},
|
||||
bind: latebind,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type QueryistContext struct {
|
||||
sqlCtx *sql.Context
|
||||
qryist *Queryist
|
||||
isRemote bool
|
||||
close func()
|
||||
}
|
||||
|
||||
// LateBindCliContext is a struct that implements CliContext. Its primary purpose is to wrap the global arguments and
|
||||
// provide an implementation of the QueryEngine function. This instance is stateful to ensure that the Queryist is only
|
||||
// created once.
|
||||
type LateBindCliContext struct {
|
||||
globalArgs *argparser.ArgParseResults
|
||||
cwd filesys.Filesys
|
||||
config *env.DoltCliConfig
|
||||
activeContext *QueryistContext
|
||||
|
||||
bind LateBindQueryist
|
||||
}
|
||||
|
||||
type QueryEngineResult struct {
|
||||
Queryist Queryist
|
||||
Context *sql.Context
|
||||
// |true| if this is the first time the CliContext is returning a QueryEngineResult.
|
||||
// Otherwise it will be |false|, which means this CliContext has already been used
|
||||
// to retrieve a Queryist, and the Queryist coming back is the cached result.
|
||||
IsFirstResult bool
|
||||
IsRemote bool
|
||||
}
|
||||
|
||||
// GlobalArgs returns the arguments passed before the subcommand.
|
||||
func (lbc LateBindCliContext) GlobalArgs() *argparser.ArgParseResults {
|
||||
return lbc.globalArgs
|
||||
}
|
||||
|
||||
// QueryEngine returns a Queryist, a sql.Context, a closer function, and an error. It ensures that only one call to the
|
||||
// LateBindQueryist is made, and caches the result. Note that if this is called twice, the closer function returns will
|
||||
// be nil, callers should check if is nil.
|
||||
func (lbc LateBindCliContext) QueryEngine(ctx context.Context, opts ...LateBindQueryistOption) (res QueryEngineResult, err error) {
|
||||
if lbc.activeContext != nil && lbc.activeContext.qryist != nil && lbc.activeContext.sqlCtx != nil {
|
||||
res.Queryist = *lbc.activeContext.qryist
|
||||
res.Context = lbc.activeContext.sqlCtx
|
||||
res.IsRemote = lbc.activeContext.isRemote
|
||||
// Returning a cached result.
|
||||
res.IsFirstResult = false
|
||||
return res, nil
|
||||
}
|
||||
|
||||
bindRes, err := lbc.bind(ctx, opts...)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
lbc.activeContext.qryist = &bindRes.Queryist
|
||||
lbc.activeContext.sqlCtx = bindRes.Context
|
||||
lbc.activeContext.close = bindRes.Closer
|
||||
lbc.activeContext.isRemote = bindRes.IsRemote
|
||||
|
||||
res.Queryist = bindRes.Queryist
|
||||
res.Context = bindRes.Context
|
||||
res.IsRemote = bindRes.IsRemote
|
||||
res.IsFirstResult = true
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (lbc LateBindCliContext) Close() {
|
||||
if lbc.activeContext != nil && lbc.activeContext.close != nil {
|
||||
lbc.activeContext.close()
|
||||
}
|
||||
}
|
||||
|
||||
func (lbc LateBindCliContext) WorkingDir() filesys.Filesys {
|
||||
return lbc.cwd
|
||||
}
|
||||
|
||||
// Config returns the dolt config stored in CliContext
|
||||
func (lbc LateBindCliContext) Config() *env.DoltCliConfig {
|
||||
return lbc.config
|
||||
}
|
||||
|
||||
var _ CliContext = LateBindCliContext{}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user