@atomist/sdm-pack-aspect
Version:
an Atomist SDM Extension Pack for visualizing drift across an organization
158 lines • 8.71 kB
JavaScript
"use strict";
/*
* Copyright © 2019 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 });
const sdm_1 = require("@atomist/sdm");
const sdm_core_1 = require("@atomist/sdm-core");
const array_1 = require("@atomist/sdm-core/lib/util/misc/array");
const sdm_pack_fingerprint_1 = require("@atomist/sdm-pack-fingerprint");
const _ = require("lodash");
const pgClientFactory_1 = require("../analysis/offline/persist/pgClientFactory");
const analyzeCommand_1 = require("../analysis/offline/spider/analyzeCommand");
const analysisTracker_1 = require("../analysis/tracking/analysisTracker");
const classificationAspect_1 = require("../aspect/compose/classificationAspect");
const DefaultAspectRegistry_1 = require("../aspect/DefaultAspectRegistry");
const DeliveryAspect_1 = require("../aspect/delivery/DeliveryAspect");
const ScoredAspect_1 = require("../aspect/score/ScoredAspect");
const fingerprintTask_1 = require("../job/fingerprintTask");
const registerAspect_1 = require("../job/registerAspect");
const api_1 = require("../routes/api");
const webAppRoutes_1 = require("../routes/web-app/webAppRoutes");
const exposeFingerprintScore_1 = require("../scorer/support/exposeFingerprintScore");
const commonTaggers_1 = require("../tagger/commonTaggers");
const machine_1 = require("./machine");
/**
* Default VirtualProjectFinder, which recognizes Maven, npm,
* and Gradle projects and Python projects using requirements.txt.
*/
exports.DefaultVirtualProjectFinder =
// Consider directories containing any of these files to be virtual projects
sdm_pack_fingerprint_1.cachingVirtualProjectFinder(sdm_pack_fingerprint_1.fileNamesVirtualProjectFinder("package.json", "pom.xml", "build.gradle", "requirements.txt"));
exports.DefaultScoreWeightings = {
// Weight this to penalize projects with few other scorers
anchor: 3,
};
/**
* Return an extension pack to add aspect support with the given aspects to an SDM.
* If we're in local mode, expose analyzer commands and HTTP endpoints.
*/
function aspectSupport(options) {
const scoringAspects = _.flatten(Object.getOwnPropertyNames(options.scorers || {})
.map(name => ScoredAspect_1.emitScoringAspect(name, array_1.toArray(options.scorers[name] || []), options.weightings)))
.filter(a => !!a);
const tagAspect = classificationAspect_1.projectClassificationAspect({
name: "tagger",
displayName: "tagger",
}, ...array_1.toArray(options.taggers) || []);
const aspects = [...array_1.toArray(options.aspects || []), ...scoringAspects, tagAspect];
// Default the two display methods with some sensible defaults
aspects.forEach(a => {
if (!a.toDisplayableFingerprint) {
a.toDisplayableFingerprint = fp => JSON.stringify(fp.data);
}
if (!a.toDisplayableFingerprintName) {
a.toDisplayableFingerprintName = fn => fn;
}
});
return Object.assign(Object.assign({}, sdm_1.metadata()), { configure: sdm => {
const cfg = sdm.configuration;
const analysisTracking = new analysisTracker_1.AnalysisTracker();
if (sdm_core_1.isInLocalMode()) {
// If we're in local mode, expose analyzer commands and
// HTTP endpoints
const analyzer = machine_1.createAnalyzer(aspects, options.virtualProjectFinder || exports.DefaultVirtualProjectFinder);
sdm.addCommand(analyzeCommand_1.analyzeGitHubByQueryCommandRegistration(analyzer, analysisTracking));
sdm.addCommand(analyzeCommand_1.analyzeGitHubOrganizationCommandRegistration(analyzer, analysisTracking));
sdm.addCommand(analyzeCommand_1.analyzeLocalCommandRegistration(analyzer, analysisTracking));
}
else {
// Add command to calculate fingerprints as part of the initial onboarding
// job and on subsequent runs of "analyze org"
sdm.addCommand(fingerprintTask_1.calculateFingerprintTask(sdm, aspects));
// Register all aspects on startup
sdm.addStartupListener(registerAspect_1.registerAspects(sdm, aspects));
}
// Add support for calculating aspects on push and computing delivery aspects
// This is only possible in local mode if we have a fingerprint publisher,
// as we can't send to Atomist (the default)
if (!!options.goals && (!sdm_core_1.isInLocalMode() || !!options.publishFingerprints)) {
if (!!options.goals.pushImpact) {
// Add supporting for calculating fingerprints on every push
sdm.addExtensionPacks(sdm_pack_fingerprint_1.fingerprintSupport({
pushImpactGoal: options.goals.pushImpact,
aspects,
aspectsFactory: options.aspectsFactory,
rebase: options.rebase,
publishFingerprints: options.publishFingerprints,
}));
}
aspects
.filter(DeliveryAspect_1.isDeliveryAspect)
.filter(a => a.canRegister(sdm, options.goals))
.forEach(da => da.register(sdm, options.goals, options.publishFingerprints));
}
const exposeWeb = options.exposeWeb !== undefined ? options.exposeWeb : sdm_core_1.isInLocalMode();
if (exposeWeb) {
const { customizers, routesToSuggestOnStartup } = orgVisualizationEndpoints(pgClientFactory_1.sdmConfigClientFactory(cfg), cfg, analysisTracking, options, aspects);
cfg.http.customizers.push(...customizers);
routesToSuggestOnStartup.forEach(rtsos => {
cfg.logging.banner.contributors.push(suggestRoute(rtsos));
});
}
} });
}
exports.aspectSupport = aspectSupport;
function suggestRoute({ title, route }) {
return cfg => ({
title,
body: `http://localhost:${cfg.http.port}${route}`,
});
}
function orgVisualizationEndpoints(dbClientFactory, configuration, analysisTracking, options, aspects) {
const resultStore = machine_1.analysisResultStore(dbClientFactory);
const fingerprintClassificationsFound = _.flatten(aspects.filter(classificationAspect_1.isClassificationAspect).map(ca => ca.classifierMetadata));
const scorerNames = Object.getOwnPropertyNames((options.scorers || {}));
const aspectRegistry = new DefaultAspectRegistry_1.DefaultAspectRegistry({
idealStore: resultStore,
problemStore: resultStore,
aspects,
undesirableUsageChecker: options.undesirableUsageChecker,
scorers: array_1.toArray(options.inMemoryScorers || []).concat(scorerNames.map(exposeFingerprintScore_1.exposeFingerprintScore)),
workspaceScorers: options.workspaceScorers,
scoreWeightings: options.weightings || exports.DefaultScoreWeightings,
configuration,
})
.withTaggers(...array_1.toArray(options.inMemoryTaggers || []))
// Add in memory taggers for all classification fingerprints
.withTaggers(...commonTaggers_1.tagsFromClassificationFingerprints(...fingerprintClassificationsFound));
if (options.secureWeb === undefined) {
options.secureWeb = !sdm_core_1.isInLocalMode();
}
const aboutTheApi = api_1.api(resultStore, aspectRegistry, options.secureWeb);
if (!sdm_core_1.isInLocalMode() && !options.exposeWeb) {
return {
routesToSuggestOnStartup: aboutTheApi.routesToSuggestOnStartup,
customizers: [aboutTheApi.customizer],
};
}
const aboutStaticPages = webAppRoutes_1.addWebAppRoutes(aspectRegistry, resultStore, analysisTracking, configuration.http.client.factory, options.instanceMetadata || sdm_1.metadata());
return {
routesToSuggestOnStartup: [...aboutStaticPages.routesToSuggestOnStartup,
...aboutTheApi.routesToSuggestOnStartup],
customizers: [aboutStaticPages.customizer, aboutTheApi.customizer],
};
}
//# sourceMappingURL=aspectSupport.js.map