@jira-deploy/core 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jira-deploy/core",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "repository": {
@@ -132,7 +132,7 @@ async function findTransitionByName(issueKey, transitionName, jira) {
132
132
  ));
133
133
  }
134
134
 
135
- async function waitForGrayReleaseResult(issueKey, fieldId, label, jira, onProgress = () => {}) {
135
+ async function waitForGrayReleaseResult(issueKey, fieldId, label, jira, onProgress = () => { }) {
136
136
  const intervalMs = getPollIntervalMs();
137
137
  const timeoutMs = getPollTimeoutMs();
138
138
  const startedAt = Date.now();
@@ -740,6 +740,9 @@ async function executeGrayReleaseDeployFlow(issueKey, ctx) {
740
740
  }
741
741
 
742
742
  log.push(`🚀 開始執行 GrayRelease Deploy - 環境: ${environment.toUpperCase()}`);
743
+ log.push(' 確保每次都會從 build 開始,先執行: Planning');
744
+ await jira.transitionByName(issueKey, 'Planning');
745
+ await notifier.notify(issueKey, '確保每次都會從 Planning 開始,準備進入部署流程');
743
746
 
744
747
  while (true) {
745
748
  const issue = await jira.getIssue(issueKey);
@@ -983,7 +986,7 @@ async function executeAutoGrayReleaseFlow(issueKey, options, ctx) {
983
986
 
984
987
  async function runGrayReleaseDeployStep(issueKey, systemCode, ctx, log) {
985
988
  const { jira, notifier } = ctx;
986
- const needSwitch = await needSwitchExecutionNode(issueKey, systemCode, jira);
989
+ const needSwitch = await needSwitchExecutionNode(issueKey, systemCode, jira, log);
987
990
 
988
991
  if (needSwitch) {
989
992
  log.push(' 執行: Switch Execution Node');
@@ -1011,7 +1014,7 @@ async function runGrayReleaseDeployStep(issueKey, systemCode, ctx, log) {
1011
1014
  // 若超時則回傳「部署中」訊息,請使用者稍後繼續。
1012
1015
  // 每 3 分鐘 輪詢一次
1013
1016
  const DEPLOY_WAIT_MS = Math.min(getPollTimeoutMs(), 10 * 60 * 1000);
1014
- const DEPLOY_POLL_MS = Math.min(getPollIntervalMs(), 3 * 60 * 1000);
1017
+ const DEPLOY_POLL_MS = Math.min(getPollIntervalMs(), 3 * 60 * 1000);
1015
1018
  const deployDeadline = Date.now() + DEPLOY_WAIT_MS;
1016
1019
  let deployCompleted = false;
1017
1020
  let attempts = 0;
@@ -1048,21 +1051,6 @@ async function runGrayReleaseDeployStep(issueKey, systemCode, ctx, log) {
1048
1051
  throw new Error(`GrayRelease Deploy 失敗,${GRAY_RELEASE_FIELD_IDS.deployResult}: ${deployResult}`);
1049
1052
  }
1050
1053
 
1051
- const transitions = await jira.getTransitions?.(issueKey) ?? [];
1052
- const toVerifyTrans = transitions.find(
1053
- (t) => t.name.toLowerCase() === 'to verify',
1054
- );
1055
- if (isPassingResult(deployResult) || toVerifyTrans) {
1056
- log.push(' ✅ Deploy 完成,執行: To Verify');
1057
- if (toVerifyTrans?.id && jira.transitionById) {
1058
- await jira.transitionById(issueKey, toVerifyTrans.id);
1059
- } else {
1060
- await jira.transitionByName(issueKey, 'To Verify');
1061
- }
1062
- await notifier.notify(issueKey, 'Deploy 完成,進入驗證階段');
1063
- deployCompleted = true;
1064
- break;
1065
- }
1066
1054
 
1067
1055
  if (Date.now() >= deployDeadline) {
1068
1056
  break;
@@ -1132,7 +1120,7 @@ async function handleGrayReleaseApproval(issueKey, environment, systemCode, ctx)
1132
1120
  await handleSendJabberMessage(
1133
1121
  {
1134
1122
  to: jabberTo,
1135
- message: `[GrayRelease 簽核通知] ${issueKey} 需要您的簽核。環境: STG\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1123
+ message: `[GrayRelease 簽核通知] ${issueKey} 需要您的簽核。環境: STG,系統: ${systemCode}\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1136
1124
  },
1137
1125
  {},
1138
1126
  );
@@ -1176,7 +1164,7 @@ async function handleGrayReleaseApproval(issueKey, environment, systemCode, ctx)
1176
1164
  await handleSendJabberMessage(
1177
1165
  {
1178
1166
  to: jamesJabber,
1179
- message: `[GrayRelease 簽核通知] ${issueKey} 需要您的簽核並留言確認。環境: UAT\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1167
+ message: `[GrayRelease 簽核通知] ${issueKey} 需要您的簽核並留言確認。環境: UAT,系統: ${systemCode}\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1180
1168
  },
1181
1169
  {},
1182
1170
  );
@@ -1226,7 +1214,7 @@ async function handleGrayReleaseApproval(issueKey, environment, systemCode, ctx)
1226
1214
  await handleSendJabberMessage(
1227
1215
  {
1228
1216
  to: solarJabber,
1229
- message: `[GrayRelease 簽核通知] ${issueKey} 已由 James Yu 確認,需要您的最終簽核。環境: UAT\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1217
+ message: `[GrayRelease 簽核通知] ${issueKey} 已由 James Yu 確認,需要您的最終簽核。環境: UAT,系統: ${systemCode}\n${process.env.JIRA_BASE_URL}/browse/${issueKey}`,
1230
1218
  },
1231
1219
  {},
1232
1220
  );
@@ -1249,7 +1237,7 @@ async function handleGrayReleaseApproval(issueKey, environment, systemCode, ctx)
1249
1237
  * 判斷是否需要執行 Switch Execution Node
1250
1238
  * 規則:查詢同系統上次 CD or GrayRelease 部署的環境群組,若與本次不同則需切換
1251
1239
  */
1252
- async function needSwitchExecutionNode(issueKey, systemCode, jira) {
1240
+ async function needSwitchExecutionNode(issueKey, systemCode, jira, log) {
1253
1241
  if (await hasRecentSwitchExecutionNodeComment(issueKey, systemCode, jira)) {
1254
1242
  return false;
1255
1243
  }
@@ -1263,10 +1251,11 @@ async function needSwitchExecutionNode(issueKey, systemCode, jira) {
1263
1251
  const jql_cd = `project = CID AND (issuetype = CD OR issuetype = GrayRelease) AND text ~ "${systemCode}" AND status = Done AND issueKey != "${issueKey}" ORDER BY updated DESC`;
1264
1252
 
1265
1253
  try {
1254
+ log.push(` before 查詢歷史 CD/GrayRelease 單,判斷是否需要切換 Execution Node`);
1266
1255
  const cdResults = await jira.searchIssues(jql_cd, ['customfield_13436', 'updated'], 1);
1256
+ log.push(` after 查詢歷史 CD/GrayRelease 單,判斷是否需要切換 Execution Node`, cdResults);
1267
1257
  const cdIssue = cdResults[0] ?? null;
1268
1258
 
1269
-
1270
1259
  // 查不到歷史 → 保守執行 Switch
1271
1260
  if (!cdIssue) {
1272
1261
  return true;
@@ -1290,9 +1279,6 @@ async function waitForSwitchExecutionNode(issueKey, systemCode, jira) {
1290
1279
  const deadline = Date.now() + waitMs;
1291
1280
 
1292
1281
  while (true) {
1293
- if (await hasRecentSwitchExecutionNodeComment(issueKey, systemCode, jira)) {
1294
- return;
1295
- }
1296
1282
 
1297
1283
  if (Date.now() >= deadline) {
1298
1284
  return;
package/tools.test.js CHANGED
@@ -1634,7 +1634,7 @@ describe('auto_grayrelease — approval payload handling', () => {
1634
1634
  searchIssues: async () => [{ fields: { customfield_13436: { value: 'stg' } } }],
1635
1635
  transitionByName: async (issueKey, transitionName) => {
1636
1636
  calls.transitionByName.push({ issueKey, transitionName });
1637
- if (transitionName === 'To Verify') {
1637
+ if (transitionName === 'GrayRelease Deploy') {
1638
1638
  status = 'VERIFY';
1639
1639
  }
1640
1640
  return { transitioned: transitionName, toStatus: status };
@@ -1810,7 +1810,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1810
1810
  assert.deepEqual(output.nextSteps, ['GrayRelease Build']);
1811
1811
  });
1812
1812
 
1813
- test('deploy_grayrelease advances Wait for Build via approval without rebuilding', async () => {
1813
+ test('deploy_grayrelease restarts from Planning and advances via approval without rebuilding', async () => {
1814
1814
  useFastPolling();
1815
1815
  let status = 'Wait for Build';
1816
1816
  const transitions = [];
@@ -1837,9 +1837,11 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1837
1837
  searchIssues: async () => [{ fields: { customfield_13436: { value: 'stg' } } }],
1838
1838
  transitionByName: async (_issueKey, transitionName) => {
1839
1839
  transitions.push(transitionName);
1840
+ if (transitionName === 'Planning') status = 'Planning';
1841
+ if (transitionName === 'Accept') status = 'Wait for Build';
1840
1842
  if (transitionName === 'Apply to approval') status = 'Wait Approval';
1841
1843
  if (transitionName === 'Approve') status = 'Wait Deploy';
1842
- if (transitionName === 'To Verify') status = 'VERIFY';
1844
+ if (transitionName === 'GrayRelease Deploy') status = 'VERIFY';
1843
1845
  },
1844
1846
  };
1845
1847
 
@@ -1854,17 +1856,18 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1854
1856
  const output = JSON.parse(result.content[0].text);
1855
1857
  assert.equal(output.finalStatus, 'VERIFY');
1856
1858
  assert.deepEqual(transitions, [
1859
+ 'Planning',
1860
+ 'Accept',
1857
1861
  'Apply to approval',
1858
1862
  'Approve',
1859
1863
  'GrayRelease Deploy',
1860
- 'To Verify',
1861
1864
  ]);
1862
1865
  } finally {
1863
1866
  restoreEnv();
1864
1867
  }
1865
1868
  });
1866
1869
 
1867
- test('deploy_grayrelease stops in VERIFY without rebuilding', async () => {
1870
+ test('deploy_grayrelease keeps rc deploy behavior by resetting from VERIFY to Planning first', async () => {
1868
1871
  const transitions = [];
1869
1872
  const jira = {
1870
1873
  getIssueFields: async () => ({
@@ -1886,8 +1889,8 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1886
1889
  assert.ok(!result.isError, result.content[0].text);
1887
1890
  const output = JSON.parse(result.content[0].text);
1888
1891
  assert.equal(output.finalStatus, 'VERIFY');
1889
- assert.deepEqual(transitions, []);
1890
- assert.match(output.log.join('\n'), /若需重 build 請明確執行 build\/rebuild/);
1892
+ assert.deepEqual(transitions, ['Planning']);
1893
+ assert.match(output.log.join('\n'), /確保每次都會從 build 開始/);
1891
1894
  });
1892
1895
 
1893
1896
  test('Build waits until customfield_13432 becomes pass before Apply to approval', async () => {
@@ -1936,7 +1939,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1936
1939
  }
1937
1940
  });
1938
1941
 
1939
- test('Deploy waits until customfield_13433 becomes pass before To Verify', async () => {
1942
+ test('Deploy waits until cid jira worker moves status to VERIFY with pass result', async () => {
1940
1943
  useFastPolling();
1941
1944
  let status = 'WAIT DEPLOY';
1942
1945
  let deployResultCalls = 0;
@@ -1952,13 +1955,15 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1952
1955
  customfield_13443: { value: 'CWA' },
1953
1956
  };
1954
1957
  },
1955
- getIssue: async () => ({ fields: { status: { name: status }, summary: 'GrayRelease' } }),
1958
+ getIssue: async () => ({
1959
+ fields: {
1960
+ status: { name: deployResultCalls >= 2 ? 'VERIFY' : status },
1961
+ summary: 'GrayRelease',
1962
+ },
1963
+ }),
1956
1964
  searchIssues: async () => [{ fields: { customfield_13436: { value: 'stg' } } }],
1957
1965
  transitionByName: async (_issueKey, transitionName) => {
1958
1966
  transitions.push(transitionName);
1959
- if (transitionName === 'To Verify') {
1960
- status = 'VERIFY';
1961
- }
1962
1967
  },
1963
1968
  };
1964
1969
 
@@ -1971,7 +1976,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
1971
1976
 
1972
1977
  assert.ok(!result.content[0].text.startsWith('❌'), 'Deploy flow should succeed');
1973
1978
  assert.equal(deployResultCalls, 3);
1974
- assert.deepEqual(transitions, ['GrayRelease Deploy', 'To Verify']);
1979
+ assert.deepEqual(transitions, ['GrayRelease Deploy']);
1975
1980
  } finally {
1976
1981
  restoreEnv();
1977
1982
  }
@@ -2002,7 +2007,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
2002
2007
  searchIssues: async () => [{ fields: { customfield_13436: { value: 'prd' } } }],
2003
2008
  transitionByName: async (_issueKey, transitionName) => {
2004
2009
  transitions.push(transitionName);
2005
- if (transitionName === 'To Verify') {
2010
+ if (transitionName === 'GrayRelease Deploy') {
2006
2011
  status = 'VERIFY';
2007
2012
  }
2008
2013
  },
@@ -2016,7 +2021,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
2016
2021
  );
2017
2022
 
2018
2023
  assert.ok(!result.content[0].text.startsWith('❌'), 'Deploy flow should succeed');
2019
- assert.deepEqual(transitions, ['GrayRelease Deploy', 'To Verify']);
2024
+ assert.deepEqual(transitions, ['GrayRelease Deploy']);
2020
2025
  } finally {
2021
2026
  restoreEnv();
2022
2027
  }
@@ -2058,7 +2063,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
2058
2063
  },
2059
2064
  transitionByName: async (_issueKey, transitionName) => {
2060
2065
  transitions.push(transitionName);
2061
- if (transitionName === 'To Verify') {
2066
+ if (transitionName === 'GrayRelease Deploy') {
2062
2067
  status = 'VERIFY';
2063
2068
  }
2064
2069
  },
@@ -2073,7 +2078,7 @@ describe('auto_grayrelease — build/deploy result fields', () => {
2073
2078
 
2074
2079
  assert.ok(!result.content[0].text.startsWith('❌'), 'Deploy flow should succeed');
2075
2080
  assert.equal(searchIssuesCalls, 1);
2076
- assert.deepEqual(transitions, ['Switch Execution Node', 'GrayRelease Deploy', 'To Verify']);
2081
+ assert.deepEqual(transitions, ['Switch Execution Node', 'GrayRelease Deploy']);
2077
2082
  } finally {
2078
2083
  restoreEnv();
2079
2084
  }