Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
// @ts-ignore
import { schedule } from "danger"
import spellcheck from "danger-plugin-spellcheck"
schedule(spellcheck())
// Warn if there are library changes, but not tests
const modifiedAppFiles = modified.filter(p => p.includes('src/'))
const hasAppChanges = modifiedAppFiles.length > 0
const testChanges = modifiedAppFiles.filter(filepath => /test/i.test(filepath))
const hasTestChanges = testChanges.length > 0
if (hasAppChanges && !hasTestChanges) {
warn(
'There are library changes, but not tests. That\'s OK as long as you\'re refactoring existing code',
)
}
// Warn if someone wants to change peril settings
if (modified.filter(p => p.includes('peril')).length) {
fail('Peril settings are being changed')
}
// TODO: fs won't work in peril
// // Be careful of leaving testing shortcuts in the codebase
// const onlyTestFiles = testChanges.filter(x => {
// const content = fs.readFileSync(x).toString();
// return (
// content.includes('it.only') ||
// content.includes('describe.only') ||
// content.includes('fdescribe') ||
// content.includes('fit(')
// );
// });
// raiseIssueAboutPaths(fail, onlyTestFiles, 'an `only` was left in the test');
return configFilePattern.test(filePath);
});
const modifiedGenerateConfigScriptFiles = danger.git.modified_files.filter((filePath) => {
const srcFilePattern = /\/scripts\/generate-app-config/i;
return srcFilePattern.test(filePath);
});
const hasCHANGELOGChanges = modifiedChangelog.length > 0 || newChangelog.length > 0;
const hasModifiedSrcFiles = modifiedSrcFiles.length > 0;
const hasModifiedConfigFiles = modifiedConfigFiles.length > 0;
const hasModifiedGenerateConfigScriptFiles = modifiedGenerateConfigScriptFiles.length > 0;
// Fail if there are src code changes without a CHANGELOG update
if ((hasModifiedSrcFiles || hasModifiedConfigFiles || hasModifiedGenerateConfigScriptFiles) && !hasCHANGELOGChanges) {
fail('Please include a CHANGELOG entry with this PR.');
}
)
}
if (logos.created) {
message(
[
':art: Thanks for submitting a logo. <br>',
'Please ensure your contribution follows our ',
'[guidance](https://github.com/badges/shields/blob/master/doc/logos.md#contributing-logos) ',
'for logo submissions.',
].join('')
)
}
if (capitals.created || underscores.created) {
fail(
[
'JavaScript source files should be named with `kebab-case` ',
'(dash-separated lowercase).',
].join('')
)
}
const allFiles = danger.git.created_files.concat(danger.git.modified_files)
if (allFiles.length > 100) {
warn("Lots 'o changes. Skipping diff-based checks.")
} else {
allFiles.forEach(file => {
// eslint-disable-next-line promise/prefer-await-to-then
danger.git.diffForFile(file).then(({ diff }) => {
if (/serverSecrets/.test(diff) && !secretsDocs.modified) {
async function run() {
// Use git locally to grab the commit which represents the place
// where the branches differ
const upstreamRepo = danger.github.pr.base.repo.full_name;
const upstreamRef = danger.github.pr.base.ref;
try {
await git(`remote add ${UPSTREAM_REMOTE} https://github.com/${upstreamRepo}.git`);
} catch (err) {
// ignore if it already exist for local testing
}
await git(`fetch ${UPSTREAM_REMOTE}`);
const mergeBaseCommit = await git(`merge-base HEAD ${UPSTREAM_REMOTE}/${upstreamRef}`);
const commitRange = `${mergeBaseCommit}...${danger.github.pr.head.sha}`;
const comparison = await loadComparison(mergeBaseCommit, upstreamRef);
const results = Object.entries(comparison.bundles);
const anyResultsChanges = results.filter(createComparisonFilter(1, 1));
if (anyResultsChanges.length > 0) {
const modifiedSrcFiles = danger.git.modified_files.filter((filePath) => {
const srcFilePattern = /^packages\/([a-z-])*\/src/i;
return srcFilePattern.test(filePath);
});
const hasCHANGELOGChanges = modifiedChangelog.length > 0 || newChangelog.length > 0;
const hasModifiedSrcFiles = modifiedSrcFiles.length > 0;
// Fail if there are src code changes without a CHANGELOG update
if (hasModifiedSrcFiles && !hasCHANGELOGChanges) {
fail('Please include a CHANGELOG entry with this PR.');
}
// Warn when there is a big PR
const bigPRThreshold = 1000;
if (danger.github.pr.additions + danger.github.pr.deletions > bigPRThreshold) {
warn(':exclamation: Big PR. Consider breaking this into smaller PRs if applicaple');
}
upstreamSchema
)
// Create a new copy of the service, with the breaking changes added
if (breakingChanges.length) {
servicesWithBreakingChanges[serviceName] = {
...service,
breakingChanges,
}
}
}
// Reporting back to the PR - offer a single message for all of the potentially
// failed services,
const failedServiceNames = Object.keys(servicesWithBreakingChanges)
const failedServicesSentence = danger.utils.sentence(failedServiceNames)
if (failedServiceNames.length === 0) {
console.log(`No breaking changes for ${failedServicesSentence}`)
return
}
const version = isProductionDeployPR ? "staging" : "production"
const message = isProductionDeployPR ? fail : warn
const s = failedServiceNames.length === 1 ? "" : "s"
const are = failedServiceNames.length === 1 ? "is" : "are"
message(`
There ${are} a breaking difference${s} between the **${version}** deployed
schema${s} for **${failedServiceNames}**.
The changes you have made to the local schema${s} in metaphysics are
const [owner, repo] = repoSlug.split("/")
try {
const response = await api.repos.getContents({ repo, owner, path, ref })
if (response && response.data && response.data.type === "file") {
const buffer = Buffer.from(response.data.content, response.data.encoding)
return buffer.toString()
} else {
return ""
}
} catch {
return ""
}
},
createUpdatedIssueWithID: createUpdatedIssueWithIDGenerator(api),
// TODO: Is this right?
// Do I need to move the PR object into here if needed?
createOrAddLabel: createOrAddLabel(undefined as any, api),
createOrUpdatePR: createOrUpdatePR(undefined as any, api),
})
import { danger, fail, warn } from "danger"
import * as fs from "fs"
// Setup
const pr = danger.github.pr
const modified = danger.git.modified_files
const bodyAndTitle = (pr.body + pr.title).toLowerCase()
// Custom modifiers for people submitting PRs to be able to say "skip this"
const trivialPR = bodyAndTitle.includes("trivial")
const filesOnly = (file: string) => fs.existsSync(file) && fs.lstatSync(file).isFile()
// Custom subsets of known files
const modifiedAppFiles = modified.filter(p => p.includes("src/")).filter(p => filesOnly(p))
// When there are app-changes and it's not a PR marked as trivial, expect
// there to be CHANGELOG changes.
const changelogChanges = modified.includes("CHANGELOG.md")
if (modifiedAppFiles.length > 0 && !trivialPR && !changelogChanges) {
fail("No CHANGELOG added.")
}
const includesSummary =
danger.github.pr.body &&
danger.github.pr.body.toLowerCase().includes('## summary');
if (!danger.github.pr.body || danger.github.pr.body.length < 50) {
fail(':grey_question: This pull request needs a description.');
} else if (!includesSummary) {
const title = ':clipboard: Missing Summary';
const idea =
'Can you add a Summary? ' +
'To do so, add a "## Summary" section to your PR description. ' +
'This is a good place to explain the motivation for making this change.';
message(`${title} - <i>${idea}</i>`);
}
// Warns if there are changes to package.json, and tags the team.
const packageChanged = includes(danger.git.modified_files, 'package.json');
if (packageChanged) {
const title = ':lock: package.json';
const idea =
'Changes were made to package.json. ' +
'This will require a manual import by a Facebook employee.';
warn(`${title} - <i>${idea}</i>`);
}
// Provides advice if a test plan is missing.
const includesTestPlan =
danger.github.pr.body &&
danger.github.pr.body.toLowerCase().includes('## test plan');
if (!includesTestPlan) {
const title = ':clipboard: Missing Test Plan';
const idea =
'Can you add a Test Plan? ' +