state.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const { readPreState } = require('@changesets/pre');
  2. const { default: readChangesets } = require('@changesets/read');
  3. const { join } = require('path');
  4. const { fetch } = require('undici');
  5. const { version, name: packageName } = require(join(__dirname, '../../../contracts/package.json'));
  6. module.exports = async ({ github, context, core }) => {
  7. const state = await getState({ github, context, core });
  8. function setOutput(key, value) {
  9. core.info(`State ${key} = ${value}`);
  10. core.setOutput(key, value);
  11. }
  12. // Jobs to trigger
  13. setOutput('start', shouldRunStart(state));
  14. setOutput('promote', shouldRunPromote(state));
  15. setOutput('changesets', shouldRunChangesets(state));
  16. setOutput('publish', shouldRunPublish(state));
  17. setOutput('merge', shouldRunMerge(state));
  18. // Global Variables
  19. setOutput('is_prerelease', state.prerelease);
  20. };
  21. function shouldRunStart({ isMaster, isWorkflowDispatch, botRun }) {
  22. return isMaster && isWorkflowDispatch && !botRun;
  23. }
  24. function shouldRunPromote({ isReleaseBranch, isWorkflowDispatch, botRun }) {
  25. return isReleaseBranch && isWorkflowDispatch && !botRun;
  26. }
  27. function shouldRunChangesets({ isReleaseBranch, isPush, isWorkflowDispatch, botRun }) {
  28. return (isReleaseBranch && isPush) || (isReleaseBranch && isWorkflowDispatch && botRun);
  29. }
  30. function shouldRunPublish({ isReleaseBranch, isPush, hasPendingChangesets, isPublishedOnNpm }) {
  31. return isReleaseBranch && isPush && !hasPendingChangesets && !isPublishedOnNpm;
  32. }
  33. function shouldRunMerge({
  34. isReleaseBranch,
  35. isPush,
  36. prerelease,
  37. isCurrentFinalVersion,
  38. hasPendingChangesets,
  39. prBackExists,
  40. }) {
  41. return isReleaseBranch && isPush && !prerelease && isCurrentFinalVersion && !hasPendingChangesets && !prBackExists;
  42. }
  43. async function getState({ github, context, core }) {
  44. // Variables not in the context
  45. const refName = process.env.GITHUB_REF_NAME;
  46. const botRun = process.env.TRIGGERING_ACTOR === 'github-actions[bot]';
  47. const { changesets, preState } = await readChangesetState();
  48. // Static vars
  49. const state = {
  50. refName,
  51. hasPendingChangesets: changesets.length > 0,
  52. prerelease: preState?.mode === 'pre',
  53. isMaster: refName === 'master',
  54. isReleaseBranch: refName.startsWith('release-v'),
  55. isWorkflowDispatch: context.eventName === 'workflow_dispatch',
  56. isPush: context.eventName === 'push',
  57. isCurrentFinalVersion: !version.includes('-rc.'),
  58. botRun,
  59. };
  60. // Async vars
  61. const { data: prs } = await github.rest.pulls.list({
  62. owner: context.repo.owner,
  63. repo: context.repo.repo,
  64. head: `${context.repo.owner}:merge/${state.refName}`,
  65. base: 'master',
  66. state: 'open',
  67. });
  68. state.prBackExists = prs.length !== 0;
  69. state.isPublishedOnNpm = await isPublishedOnNpm(packageName, version);
  70. // Log every state value in debug mode
  71. if (core.isDebug()) for (const [key, value] of Object.entries(state)) core.debug(`${key}: ${value}`);
  72. return state;
  73. }
  74. // From https://github.com/changesets/action/blob/v1.4.1/src/readChangesetState.ts
  75. async function readChangesetState(cwd = process.cwd()) {
  76. const preState = await readPreState(cwd);
  77. const isInPreMode = preState !== undefined && preState.mode === 'pre';
  78. let changesets = await readChangesets(cwd);
  79. if (isInPreMode) {
  80. changesets = changesets.filter(x => !preState.changesets.includes(x.id));
  81. }
  82. return {
  83. preState: isInPreMode ? preState : undefined,
  84. changesets,
  85. };
  86. }
  87. async function isPublishedOnNpm(packageName, version) {
  88. const res = await fetch(`https://registry.npmjs.com/${packageName}/${version}`);
  89. return res.ok;
  90. }