@atomist/sdm
Version:
Atomist Software Delivery Machine SDK
133 lines • 5.66 kB
JavaScript
;
/*
* Copyright © 2020 Atomist, 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.K8sSync = exports.syncGoals = exports.isSyncRepoCommit = void 0;
const child_process_1 = require("@atomist/automation-client/lib/util/child_process");
const logger_1 = require("@atomist/automation-client/lib/util/logger");
const stringify = require("json-stringify-safe");
const _ = require("lodash");
const minimalClone_1 = require("../../../api-helper/goal/minimalClone");
const logInterpreters_1 = require("../../../api-helper/log/logInterpreters");
const goalDsl_1 = require("../../../api/dsl/goalDsl");
const Goals_1 = require("../../../api/goal/Goals");
const GoalWithFulfillment_1 = require("../../../api/goal/GoalWithFulfillment");
const environment_1 = require("../../../api/goal/support/environment");
const PushTest_1 = require("../../../api/mapping/PushTest");
const modes_1 = require("../../../core/machine/modes");
const error_1 = require("../support/error");
const change_1 = require("./change");
const diff_1 = require("./diff");
const repo_1 = require("./repo");
const tag_1 = require("./tag");
function isSyncRepoCommit(sdm) {
const syncOptions = _.get(sdm, "configuration.sdm.k8s.options.sync");
if (!syncOptions || !syncOptions.repo) {
logger_1.logger.debug(`SDM configuration contains no sync repo, will not create sync repo push test`);
return undefined;
}
return PushTest_1.pushTest("IsSyncRepoCommit", async (p) => {
const repo = _.get(sdm, "configuration.sdm.k8s.options.sync.repo");
if (!repo_1.isRemoteRepo(repo) && !modes_1.isInLocalMode()) {
throw new Error(`SyncRepoRef did not get converted to proper RemoteRepoRef at startup: ${stringify(repo)}`);
}
if (modes_1.isInLocalMode() || (p.id.providerType === repo.providerType) &&
p.id.owner === repo.owner &&
p.id.repo === repo.repo && p.id.branch === repo.branch) {
const tag = tag_1.commitTag(sdm.configuration);
return p.push.commits.some(c => !c.message.includes(tag));
}
return false;
});
}
exports.isSyncRepoCommit = isSyncRepoCommit;
/**
* Add goals for pushes on the sync repo.
*/
function syncGoals(sdm) {
const syncRepoPushTest = isSyncRepoCommit(sdm);
if (!syncRepoPushTest) {
logger_1.logger.debug(`No sync repo push test, not adding sync repo goals`);
return sdm;
}
const sync = new GoalWithFulfillment_1.GoalWithFulfillment({
uniqueName: "sync",
environment: environment_1.IndependentOfEnvironment,
displayName: "sync",
workingDescription: "Syncing",
completedDescription: "Synced",
failedDescription: "Sync failed",
isolated: true,
}).with({
name: "K8sSyncRepo",
goalExecutor: exports.K8sSync,
logInterpreter: logInterpreters_1.LogSuppressor,
});
const syncGoalSet = Goals_1.goals("Sync Kubernetes Resources").plan(sync);
sdm.addGoalContributions(goalDsl_1.whenPushSatisfies(syncRepoPushTest).setGoals(syncGoalSet));
return sdm;
}
exports.syncGoals = syncGoals;
/**
* Create resources of added specs, update resources of changed specs,
* and remove resources of deleted specs.
*/
const K8sSync = async (gi) => {
const push = gi.goalEvent.push;
const log = gi.progressLog;
const params = {
cloneOptions: minimalClone_1.minimalClone(push),
context: gi.context,
credentials: gi.credentials,
id: gi.id,
log,
readOnly: true,
};
const tag = tag_1.commitTag(gi.configuration);
return gi.configuration.sdm.projectLoader.doWithProject(params, async (p) => {
if (params.cloneOptions.depth > 1) {
// work around https://github.com/atomist/sdm/issues/729
try {
await child_process_1.execPromise("git", ["fetch", `--depth=${params.cloneOptions.depth}`], { cwd: p.baseDir });
}
catch (e) {
logger_1.logger.warn(`Failed to undo shallow clone, proceeding anyway: ${e.message}`);
}
}
const changes = await diff_1.diffPush(p, push, tag, log);
const errs = [];
for (const change of changes) {
const verb = (change.change === "delete") ? "Deleting" : "Applying";
log.write(`${verb} '${change.path}' from commit ${change.sha}`);
try {
await change_1.changeResource(p, change);
}
catch (e) {
e.message = `Failed to ${change.change} '${change.path}' resource for commit ${change.sha}: ${error_1.k8sErrMsg(e)}`;
log.write(e.message);
errs.push(e);
}
}
if (errs.length > 0) {
return { code: errs.length, message: errs.map(e => e.message).join("; ") };
}
const message = `Changed ${changes.length} resources`;
log.write(message);
return { code: 0, message };
});
};
exports.K8sSync = K8sSync;
//# sourceMappingURL=goals.js.map