@@ -53,8 +53,83 @@ permissions:
5353 contents : read
5454
5555jobs :
56+ check-sprint :
57+ name : Check sprint
58+ runs-on : ubuntu-latest
59+ outputs :
60+ continue : ${{ steps.check.outputs.continue }}
61+ steps :
62+ - name : Generate a token
63+ id : generate_token
64+ uses : actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
65+ with :
66+ client-id : ${{ secrets.GH_BOT_APP_ID }}
67+ private-key : ${{ secrets.GH_BOT_APP_KEY }}
68+ owner : ${{ github.repository_owner }}
69+ repositories : ${{ github.event.repository.name }}
70+
71+ - name : Compare current and next sprint
72+ id : check
73+ uses : actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
74+ env :
75+ PROJECT_NUMBER : ${{ inputs.project_number }}
76+ SPRINT_FIELD_NAME : ${{ inputs.sprint_field_name }}
77+ with :
78+ github-token : ${{ steps.generate_token.outputs.token }}
79+ script : |
80+ const owner = context.repo.owner;
81+ const projectNumber = Number(process.env.PROJECT_NUMBER);
82+ const sprintFieldName = process.env.SPRINT_FIELD_NAME;
83+
84+ const today = new Date();
85+ // Next weekly run is 7 days from today, at the same time of day (UTC).
86+ const nextRun = new Date(today);
87+ nextRun.setUTCDate(nextRun.getUTCDate() + 7);
88+
89+ let currentSprint = null;
90+ let nextSprint = null;
91+ try {
92+ const data = await github.graphql(`
93+ query($org: String!, $number: Int!, $field: String!) {
94+ organization(login: $org) {
95+ projectV2(number: $number) {
96+ field(name: $field) {
97+ ... on ProjectV2IterationField {
98+ configuration {
99+ iterations { id title startDate duration }
100+ }
101+ }
102+ }
103+ }
104+ }
105+ }
106+ `, { org: owner, number: projectNumber, field: sprintFieldName });
107+
108+ const iterations = data.organization.projectV2.field?.configuration?.iterations || [];
109+ const contains = (it, when) => {
110+ const start = new Date(it.startDate);
111+ const end = new Date(start);
112+ end.setUTCDate(end.getUTCDate() + it.duration);
113+ return when >= start && when < end;
114+ };
115+ currentSprint = iterations.find((it) => contains(it, today));
116+ nextSprint = iterations.find((it) => contains(it, nextRun));
117+ } catch (e) {
118+ core.warning(`Could not resolve sprints: ${e.message}`);
119+ }
120+
121+ // Only a positively-detected identical pair blocks the run; any
122+ // other outcome (gap, missing config, API error) proceeds as before.
123+ const shouldContinue = !(currentSprint && nextSprint && currentSprint.id === nextSprint.id);
124+ if (!shouldContinue) {
125+ core.info(`Sprint "${currentSprint.title}" has not advanced; open/close will be skipped.`);
126+ }
127+ core.setOutput("continue", shouldContinue ? "true" : "false");
128+
56129 open-issue :
57130 name : Open sprint rotation issue
131+ needs : check-sprint
132+ if : needs.check-sprint.outputs.continue == 'true'
58133 runs-on : ubuntu-latest
59134 steps :
60135 - name : Check out the repository
@@ -231,7 +306,8 @@ jobs:
231306
232307 close-previous-issue :
233308 name : Close current sprint's issue
234- needs : open-issue
309+ needs : [check-sprint, open-issue]
310+ if : needs.check-sprint.outputs.continue == 'true'
235311 runs-on : ubuntu-latest
236312 steps :
237313 - name : Generate a token
0 commit comments