* Update a GitHub Project v2 * @param {any} output - Safe output configuration * @param {Map } temporaryIdMap - Map of temporary IDs to resolved issue numbers * @param {Object} githubClient - GitHub client (Octokit instance) to use for GraphQL queries * @returns {Promise<void|{tempor
(output, temporaryIdMap = new Map(), githubClient = null)
| 697 | * @returns {Promise<void|{temporaryId?: string, draftItemId?: string}>} Returns undefined for most operations, or an object with temporary ID mapping for draft issue creation |
| 698 | */ |
| 699 | async function updateProject(output, temporaryIdMap = new Map(), githubClient = null) { |
| 700 | output = normalizeUpdateProjectOutput(output); |
| 701 | |
| 702 | // Use the provided github client, or fall back to the global github object |
| 703 | // @ts-ignore - global.github is set by setupGlobals() from github-script context |
| 704 | const github = githubClient || global.github; |
| 705 | if (!github) { |
| 706 | throw new Error(`${ERR_CONFIG}: GitHub client is required but not provided. Either pass a github client to updateProject() or ensure global.github is set.`); |
| 707 | } |
| 708 | const { owner, repo } = context.repo; |
| 709 | |
| 710 | // Determine the effective owner/repo for content resolution. |
| 711 | // When target_repo is provided, use it instead of the workflow's host repo. |
| 712 | // This enables org-level project workflows to resolve issues from other repos. |
| 713 | let contentOwner = owner; |
| 714 | let targetRepo = repo; |
| 715 | if (output.target_repo && typeof output.target_repo === "string") { |
| 716 | const targetRepoSlug = output.target_repo.trim(); |
| 717 | const parsed = parseRepoSlug(targetRepoSlug); |
| 718 | if (!parsed) { |
| 719 | throw new Error(`${ERR_VALIDATION}: Invalid target_repo format "${targetRepoSlug}". Use "owner/repo" format (e.g., "github/docs").`); |
| 720 | } |
| 721 | contentOwner = parsed.owner; |
| 722 | targetRepo = parsed.repo; |
| 723 | core.info(`Using target_repo ${targetRepoSlug} for content resolution`); |
| 724 | } |
| 725 | |
| 726 | const projectInfo = parseProjectUrl(output.project); |
| 727 | const projectNumberFromUrl = projectInfo.projectNumber; |
| 728 | |
| 729 | const wantsCreateView = |
| 730 | output?.operation === "create_view" || |
| 731 | (output?.view && |
| 732 | output?.content_type === undefined && |
| 733 | output?.content_number === undefined && |
| 734 | output?.issue === undefined && |
| 735 | output?.pull_request === undefined && |
| 736 | output?.fields === undefined && |
| 737 | output?.draft_title === undefined && |
| 738 | output?.draft_body === undefined); |
| 739 | |
| 740 | const wantsCreateFields = output?.operation === "create_fields"; |
| 741 | |
| 742 | try { |
| 743 | core.info(`Looking up project #${projectNumberFromUrl} from URL: ${output.project}`); |
| 744 | core.info("[1/4] Fetching repository information..."); |
| 745 | |
| 746 | let repoResult; |
| 747 | try { |
| 748 | repoResult = await github.graphql( |
| 749 | `query($owner: String!, $repo: String!) { |
| 750 | repository(owner: $owner, name: $repo) { |
| 751 | id |
| 752 | owner { |
| 753 | id |
| 754 | __typename |
| 755 | } |
| 756 | } |
no test coverage detected