* Creates a handler factory function with common update logic * This factory encapsulates the shared control flow: * - Configuration defaults (target, max count) * - Max count enforcement * - Target resolution * - Empty update validation * - Success/error response shaping * * @param {UpdateH
(handlerConfig)
| 116 | * @returns {HandlerFactoryFunction} Handler factory function |
| 117 | */ |
| 118 | function createUpdateHandlerFactory(handlerConfig) { |
| 119 | const { itemType, itemTypeName, supportsPR, resolveItemNumber, buildUpdateData, executeUpdate, formatSuccessResult, additionalConfig = {}, itemFilter = null, captureExecutionMetadata = null } = handlerConfig; |
| 120 | |
| 121 | /** |
| 122 | * Main handler factory |
| 123 | * @type {HandlerFactoryFunction} |
| 124 | */ |
| 125 | return async function main(config = {}) { |
| 126 | // Extract configuration with defaults |
| 127 | const updateTarget = config.target || "triggering"; |
| 128 | const maxCount = config.max || 10; |
| 129 | |
| 130 | // Create an authenticated GitHub client. Uses config["github-token"] when set |
| 131 | // (for cross-repository operations), otherwise falls back to the step-level github. |
| 132 | const githubClient = await createAuthenticatedGitHubClient(config); |
| 133 | |
| 134 | // Resolve default target repo and allowed repos for cross-repository routing. |
| 135 | // If no target-repo is configured, defaults to the current repository. |
| 136 | const { defaultTargetRepo, allowedRepos } = resolveTargetRepoConfig(config); |
| 137 | |
| 138 | // Check if we're in staged mode |
| 139 | const isStaged = isStagedMode(config); |
| 140 | |
| 141 | const configParts = [ |
| 142 | `max=${maxCount}`, |
| 143 | `target=${updateTarget}`, |
| 144 | ...Object.entries(additionalConfig) |
| 145 | .filter(([key]) => config[key] !== undefined) |
| 146 | .map(([key]) => `${key}=${config[key]}`), |
| 147 | ]; |
| 148 | |
| 149 | core.info(`Update ${itemTypeName} configuration: ${configParts.join(", ")}`); |
| 150 | |
| 151 | // Track state |
| 152 | let processedCount = 0; |
| 153 | |
| 154 | /** |
| 155 | * Message handler function |
| 156 | * @param {Object} message - The update message |
| 157 | * @param {Object} resolvedTemporaryIds - Resolved temporary IDs |
| 158 | * @returns {Promise<Object>} Result |
| 159 | */ |
| 160 | return async function handleUpdate(message, resolvedTemporaryIds) { |
| 161 | // Check max limit |
| 162 | if (processedCount >= maxCount) { |
| 163 | core.warning(`Skipping ${itemType}: max count of ${maxCount} reached`); |
| 164 | return { |
| 165 | success: false, |
| 166 | error: `Max count of ${maxCount} reached`, |
| 167 | }; |
| 168 | } |
| 169 | |
| 170 | processedCount++; |
| 171 | |
| 172 | const item = message; |
| 173 | |
| 174 | // Resolve cross-repo target: always validate the target repository against the |
| 175 | // allowed repos and use it as the effective context. When item.repo is set it |
no test coverage detected