Conversation
Prepare tests for isTransientError, classifyError, calculateDelay, and withRetry. TDD Red phase.
- Add isTransientError for 404, 5xx, 429, 403 rate-limit - Add classifyError for human-readable logging - Add calculateDelay with exponential backoff + jitter - Add withRetry wrapper (transient-only, bounded attempts) - TDD Green: all retry tests pass
TDD Red: tests for bounded retry on getRef, getCommit, createTree, createCommit, updateRef. commitViaAPI does not yet use withRetry.
- Add maxAttempts, logger, baseDelayMs, maxDelayMs to CommitOptions - Wrap getBranchInfo, getCommit, createTree, createCommit, updateBranch in withRetry - Default maxAttempts=1 (no retries) for backward compatibility - TDD Green: all commit retry tests pass
TDD Red: tests for parsing MAX_ATTEMPTS and clamping invalid values. Runner does not yet read MAX_ATTEMPTS.
- Read MAX_ATTEMPTS env var (default 1 = no retries) - Clamp invalid values to 1 with info log - Pass maxAttempts to commitViaAPI - TDD Green: all commit-runner MAX_ATTEMPTS tests pass
- Add MAX_ATTEMPTS to Action and CLI usage - Document transient error types and backoff behavior - Document CommitOptions.maxAttempts and logger
- Require typeof status === 'number' in hasStatus type guard - Clamp maxAttempts to >= 1 (and non-finite to 1) in withRetry - Add tests for non-numeric status and zero/negative maxAttempts
Delegate base64 blob creation to createBlob for consistency with binary path.
Use @v0.1.5 in the primary workflow example; unreleased features remain documented in the note below.
## Description Adds bounded retry with exponential backoff for transient GitHub API failures. When the API returns transient errors (404, 5xx, 429, or 403 with rate-limit/abuse message), the action can automatically retry with configurable attempts instead of failing immediately. **Key additions:** - `src/retry.ts` — `isTransientError`, `classifyError`, `calculateDelay`, and `withRetry` utilities - `MAX_ATTEMPTS` env var — controls retry count (default 1 = no retries for backward compatibility) - All GitHub API calls in `commitViaAPI` (`getBranchInfo`, `getCommit`, `createTree`, `createCommit`, `updateBranch`) wrapped in `withRetry` - Exponential backoff with jitter to avoid thundering herd ## Related Issue(s) Closes #20 ## Type of Change - [x] New feature (non-breaking change which adds functionality) - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [ ] Refactoring (no functional changes) - [ ] Test updates ## Changes Made - Added `src/retry.ts` with `RetryConfig`, `isTransientError`, `classifyError`, `calculateDelay`, and `withRetry` - Extended `CommitOptions` with `maxAttempts`, `logger`, `baseDelayMs`, `maxDelayMs` - Wrapped `getBranchInfo`, `getCommit`, `createTree`, `createCommit`, `updateBranch` in `withRetry` - Added `MAX_ATTEMPTS` env parsing in `commit-runner.ts` (invalid values clamped to 1) - Unit tests for retry logic, commit retry behavior, and MAX_ATTEMPTS parsing - README documentation for `MAX_ATTEMPTS` and `CommitOptions` retry options - Rebuilt dist artifacts ## Testing - [x] Tests pass locally (`npm test`) - [ ] Manual testing performed (describe below) ### Manual Testing Details Unit tests cover: `isTransientError` (404, 5xx, 429, 403 rate-limit message), `classifyError`, `calculateDelay` (backoff, jitter, max cap), `withRetry` (success, exhaust, non-transient no-retry, logger), commit retry behavior (maxAttempts 1/2/3), and MAX_ATTEMPTS env parsing. ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have updated the documentation accordingly (README.md, CONTRIBUTE.md, etc.) - [ ] I have updated the CHANGELOG.md in the `[Unreleased]` section - [x] My changes generate no new warnings or errors - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published ## Additional Notes - Default `maxAttempts: 1` preserves existing behavior (no retries) so this is backward compatible - Transient errors: 404, 5xx, 429, and 403 when the error message indicates rate limit / abuse (Octokit `RequestError` exposes this in the message string) - CHANGELOG.md should be updated before or after merge (as noted in COMMIT_PLAN.md)
# Release v0.2.0 ## Changes ### Added - Bounded retry with exponential backoff for transient GitHub API failures (`404`, `5xx`, `429`, and `403` when the error message indicates rate limit or abuse), configurable via **`MAX_ATTEMPTS`** and **`CommitOptions`** (`maxAttempts`, `logger`, optional `baseDelayMs` / `maxDelayMs`); new retry module helpers `isTransientError`, `classifyError`, `calculateDelay`, and `withRetry` (issue #20). - Efficient multi-file commits via GitHub `createTree` **inline `content`** for text files (blobs created server-side), **`createBlob`** only for binary files (NUL detected in the first 8 KiB), and **chained `createTree`** requests in chunks of **`TREE_ENTRY_CHUNK_SIZE` (100)** entries for very large change sets and payload limits (issue #19). ### Changed - README Action example uses a tagged release (`@v0.1.5`) instead of `@main` for reproducibility; unreleased behavior remains documented in the same section. - Exported helpers for library use: `isBinaryFile`, `getFileMode`, and `TREE_ENTRY_CHUNK_SIZE` from `commit.ts`. - Binary blob creation is now sequential instead of concurrent to avoid secondary rate-limit bursts. ### Fixed - `withRetry` could surface `undefined` when `maxAttempts` was non-positive or non-finite; values are now normalized to at least one attempt. - HTTP-like error detection for retries now requires `status` to be a number (avoids misclassifying odd error shapes). - Non-UTF-8 text fallback in `createTree` delegates to `createBlob()` so blob behavior stays consistent. - `isBinaryFile` false positives when `readSync` returns fewer bytes than requested (zero-filled buffer tail). - Silent data corruption for non-UTF-8 text files by validating with `TextDecoder({ fatal: true })` and falling back to `createBlob`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.