Skip to content

Test for sync-status-across-projects GH action #37

Test for sync-status-across-projects GH action

Test for sync-status-across-projects GH action #37

name: Sync Status, Labels, and State Across Projects
on:
issues:
types: [edited, labeled, unlabeled, closed, reopened]
jobs:
sync-status-labels-state:
runs-on: ubuntu-latest
steps:
- name: Sync Issue Fields
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
const orgName = process.env.GITHUB_REPOSITORY_OWNER;
const sourceProjectNumber = 1314;
const sourceProjectId = 'PVT_kwDOAFK5-84Ak8oz';
const targetProjectNumber = 1514;
const targetProjectId = 'PVT_kwDOAFK5-84Ar1s4';
// Function to fetch fields for a project
const fetchProjectFields = async (projectNumber, orgName) => {
const query = `
query($orgName: String!, $projectNumber: Int!) {
organization(login: $orgName) {
projectV2(number: $projectNumber) {
id
fields(first: 20) {
nodes {
... on ProjectV2SingleSelectField {
id
name
options {
id
name
}
}
}
}
}
}
}
`;
console.log("Running GraphQL Query with orgName:", orgName, "and projectNumber:", projectNumber);
try {
const response = await github.graphql(query, {
orgName: orgName,
projectNumber: projectNumber
});
console.log("GraphQL Response:", response);
if (!response) {
console.log("No response received from GitHub GraphQL API.");
return null;
}
return response;
} catch (error) {
console.error("Error executing GraphQL query:", error);
return null;
}
};
// Fetch fields for the source project
const sourceProjectData = await fetchProjectFields(sourceProjectNumber, orgName);
console.log("Source Project Fields:", sourceProjectData);
// Fetch fields for the target project
const targetProjectData = await fetchProjectFields(targetProjectNumber, orgName);
console.log("Target Project Fields:", targetProjectData);
// Find the 'Status' field ID from the source project
const statusField = sourceProjectData.organization.projectV2.fields.nodes.find(field => field.name === 'Status');
if (!statusField) {
console.log("No 'Status' field found in source project.");
return;
}
const statusFieldId = statusField.id;
console.log(`Found 'Status' field ID in source project: ${statusFieldId}`);
// Fetch the current issue data (including labels, status, and state)
const issueNodeId = context.payload.issue.node_id;
const labels = context.payload.issue.labels.map(label => label.name);
const issueState = context.payload.issue.state;
// Fetch the status field value for the current issue in the source project
const { resource } = await github.graphql(`
query($projectId: ID!, $issueId: ID!) {
node(id: $issueId) {
... on Issue {
projectV2Items(first: 10) {
nodes {
fieldValues(first: 10) {
nodes {
projectV2Field {
id
}
value
}
}
}
}
}
}
}
`, {
projectId: sourceProjectId,
issueId: issueNodeId
});
// Extract the current status from the source project
const currentStatus = resource.node.projectV2Items.nodes.find(item => item.fieldValues.nodes.some(field => field.projectV2Field.id === statusFieldId))?.fieldValues.nodes.find(field => field.projectV2Field.id === statusFieldId)?.value;
if (!currentStatus) {
console.log("No status field found or status has not changed.");
return;
}
console.log(`Current status in source project: ${currentStatus}`);
// Now sync the status field, labels, and state in the target project
// Sync Status Field
await github.graphql(`
mutation($projectId: ID!, $contentId: ID!, $status: String!, $statusFieldId: ID!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId,
itemId: $contentId,
fieldId: $statusFieldId,
value: $status
}) {
projectV2Item {
id
}
}
}
`, {
projectId: targetProjectId,
contentId: issueNodeId,
status: currentStatus,
statusFieldId: statusFieldId
});
console.log(`Status synced successfully to target project for issue ID: ${issueNodeId}`);
// Sync Labels
await github.issues.addLabels({
owner: orgName,
repo: context.payload.repository.name,
issue_number: context.payload.issue.number,
labels: labels
});
console.log(`Labels synced successfully to target project for issue ID: ${issueNodeId}`);
// Sync Issue State (Closed/Reopened)
if (issueState === 'closed') {
await github.issues.update({
owner: orgName,
repo: context.payload.repository.name,
issue_number: context.payload.issue.number,
state: 'closed'
});
console.log(`Issue state updated to 'closed' for issue ID: ${issueNodeId}`);
} else if (issueState === 'reopened') {
await github.issues.update({
owner: orgName,
repo: context.payload.repository.name,
issue_number: context.payload.issue.number,
state: 'open'
});
console.log(`Issue state updated to 'open' for issue ID: ${issueNodeId}`);
}
console.log(`Issue state synced successfully to target project for issue ID: ${issueNodeId}`);