Skip to content

Add repository revert endpoint and UI#1254

Open
ikhoon wants to merge 5 commits intoline:mainfrom
ikhoon:revert-commit-ui
Open

Add repository revert endpoint and UI#1254
ikhoon wants to merge 5 commits intoline:mainfrom
ikhoon:revert-commit-ui

Conversation

@ikhoon
Copy link
Contributor

@ikhoon ikhoon commented Feb 4, 2026

Motivation:

Rolling back a repository is currently manual and error-prone, and the history view has no direct revert action. If a wrong configuration is deployed, users may want a single-click rollback to recover quickly.

Modifications:

  • Add a revert API that rebuilds the target snapshot via upserts/removals using raw content comparison.
  • Expose a root-only Revert action with a modal and API wiring in the web UI.
  • Add server, unit, and e2e coverage for the revert flow.

Result:

Motivation:

Rolling back a repository is currently manual and error-prone, and the
history view has no direct revert action. If a wrong configuration is
deployed, users may want a single-click rollback to recover quickly.

Modifications:
- Add a revert API that rebuilds the target snapshot via
  upserts/removals using raw content comparison.
- Expose a root-only Revert action with a modal and API wiring in the web UI.
- Add server, unit, and e2e coverage for the revert flow.

Result:

- Users can revert a repository to a chosen revision directly from the
  history page.
- Closes line#298
@ikhoon ikhoon added this to the 0.81.0 milestone Feb 4, 2026
@ikhoon ikhoon requested a review from jrhee17 as a code owner February 4, 2026 12:34
@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Implements a repository revert feature enabling rollback to specific commits. Introduces a RevertRequest DTO, a new REST endpoint that compares target and head revisions to compute change sets, a frontend modal for user confirmation, and comprehensive test coverage spanning backend integration, frontend unit, and end-to-end tests.

Changes

Cohort / File(s) Summary
Backend: Core Implementation
common/src/main/java/com/linecorp/centraldogma/internal/api/v1/RevertRequest.java, server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java
Introduces RevertRequest DTO with targetRevision and commitMessage fields; adds revert() endpoint that fetches target/head entries, compares content, builds change set with upserts and removals, validates non-emptiness, and pushes new commit.
Backend: Testing
server/src/test/java/com/linecorp/centraldogma/server/internal/api/RevertApiTest.java
Adds integration tests for revert API covering restore-and-delete, undelete-file, delete-only-extra, and redundant-change-exception scenarios with state validation.
Frontend: API Integration
webapp/src/dogma/features/api/apiSlice.ts
Adds RevertRequest type and revertRepository mutation that POSTs to the revert endpoint; exposes useRevertRepositoryMutation hook.
Frontend: UI Components
webapp/src/dogma/features/history/RevertCommitModal.tsx, webapp/src/dogma/features/history/HistoryList.tsx
Introduces RevertCommitModal component with form handling and notification dispatch; enhances HistoryList with headRevision prop, revert button in action column, and modal integration.
Frontend: Page Integration
webapp/src/pages/app/projects/[projectName]/repos/[repoName]/commits/[[...path]]/index.tsx
Passes headRevision prop from HistoryListPage to HistoryList component.
Frontend & E2E Tests
webapp/tests/dogma/feature/history/HistoryList.test.tsx, webapp/tests/dogma/feature/history/RevertCommitModal.test.tsx, webapp/e2e/revert.spec.ts
Updates HistoryList test props; adds RevertCommitModal unit tests validating pre-fill and submit behavior; adds E2E test exercising complete revert workflow from login through API call and state verification.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/UI
    participant Modal as RevertCommitModal
    participant API as Frontend API
    participant Backend as ContentServiceV1
    participant Repo as Repository
    
    User->>Modal: Open modal & set targetRevision
    Modal->>Modal: Initialize form with<br/>prefilled commit message
    User->>Modal: Submit revert request
    Modal->>API: Call useRevertRepositoryMutation
    API->>Backend: POST /revert<br/>(targetRevision, commitMessage)
    Backend->>Repo: Fetch target entries
    Backend->>Repo: Fetch head entries
    Backend->>Backend: Compare content &<br/>build change set
    alt Changes exist
        Backend->>Repo: Push new commit
        Backend-->>API: Return PushResultDto
        API-->>Modal: Success
        Modal->>User: Show success notification
    else No changes
        Backend-->>API: RedundantChangeException
        API-->>Modal: Conflict
        Modal->>User: Show no-changes notification
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • trustin
  • jrhee17
  • minwoox

Poem

🐰 A hop, skip, and a git revert away!
We roll back the commits from yesterday,
Target revision in sight, changes compared,
New commits pushed with history repaired. ✨
Revert to the past, no worries today!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a revert endpoint and UI to allow repository rollback functionality.
Description check ✅ Passed The description clearly explains the motivation, modifications, and expected results; all are related to the revert feature implementation.
Linked Issues check ✅ Passed The PR fully implements the rollback mechanism requested in issue #298, providing both API and UI for reverting to a selected commit.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the revert endpoint and UI; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`:
- Around line 325-337: The method toUpsertChange currently throws a
java.lang.Error for unexpected entry types; replace that with throwing an
IllegalStateException (preserving the existing message) so application-level
unexpected states are signaled correctly; update the throw in toUpsertChange
(and keep existing behavior for switch cases and the assert on
entry.rawContent()) to throw new IllegalStateException("unexpected entry type: "
+ entry.type()) instead of new Error(...).
- Around line 317-323: Replace the runtime-unsafe assert in isSameContent with
explicit null checks: use Objects.requireNonNull(first.rawContent(),
"first.rawContent() must not be null") and
Objects.requireNonNull(second.rawContent(), "second.rawContent() must not be
null") (import java.util.Objects) before comparing via equals; update the
isSameContent(Entry<?> first, Entry<?> second) method to perform these checks so
nulls are handled deterministically in production.
- Around line 259-315: The revert method currently calls the private push(...)
helper directly and skips meta-repo validation; before invoking push in the
thenCompose block, call the existing checkMetaRepoPush(repository, changes)
validation (same one used by the public /contents endpoint) using the collected
changes to ensure protected repos like "dogma"/"meta" cannot be reverted to
disallowed states, and only then proceed to call push(...). Ensure you reference
the local variables used there (changes, repository, author, headRevision,
request.commitMessage(), commitTimeMillis) so the validation runs
synchronously/throws before push is executed.

In `@webapp/e2e/revert.spec.ts`:
- Around line 3-35: The test hard-codes API_BASE which uses a different
origin/port and breaks cookie/CSRF context; remove or stop using the top-level
API_BASE constant and instead derive the API base inside apiPost (or before
calling it) from the current page origin (e.g. use new URL(await
page.url()).origin) and concatenate that origin with the path when building the
fetch URL; update the apiPost function (and any callers) so the evaluated fetch
uses the derived origin + path rather than the hard-coded API_BASE to ensure
cookies and CSRF tokens match the request origin.
🧹 Nitpick comments (2)
.gitignore (1)

143-145: Unrelated change: Consider separating into its own commit.

This .gitignore addition for /AGENTS.md appears unrelated to the revert feature. While harmless, bundling unrelated changes makes it harder to track the history of changes.

webapp/src/dogma/features/history/RevertCommitModal.tsx (1)

73-90: Simplify error handling - remove dead code.

  1. Lines 75-77: After .unwrap(), errors are thrown automatically, so the response.error check is never reached.
  2. Lines 78-81: The backend throws RedundantChangeException (HTTP 409) when no changes exist, which is caught in the catch block. The API returns a PushResultDto on success, not null.
♻️ Proposed simplification
   const onSubmit = async (formData: FormData) => {
     const data = {
       targetRevision,
       commitMessage: {
         summary: formData.summary,
         detail: formData.detail,
       },
     };
     try {
-      const response = await revertRepository({ projectName, repoName, data }).unwrap();
-      if ((response as { error: FetchBaseQueryError | SerializedError }).error) {
-        throw (response as { error: FetchBaseQueryError | SerializedError }).error;
-      }
-      if (response === null) {
-        dispatch(
-          newNotification('No changes to revert', `Repository is already at r${targetRevision}`, 'info'),
-        );
-      } else {
-        dispatch(newNotification('Repository reverted', `Reverted to r${targetRevision}`, 'success'));
-      }
+      await revertRepository({ projectName, repoName, data }).unwrap();
+      dispatch(newNotification('Repository reverted', `Reverted to r${targetRevision}`, 'success'));
       reset();
       onClose();
     } catch (error) {
       dispatch(newNotification(`Failed to revert`, ErrorMessageParser.parse(error), 'error'));
     }
   };

Comment on lines +317 to +323
private static boolean isSameContent(Entry<?> first, Entry<?> second) {
if (first.type() != second.type()) {
return false;
}
assert first.rawContent() != null && second.rawContent() != null;
return first.rawContent().equals(second.rawContent());
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid assert for null checks in production code.

Assertions can be disabled at runtime with the -da JVM flag. Use explicit null checks or requireNonNull for production-critical validations.

🔧 Proposed fix
 private static boolean isSameContent(Entry<?> first, Entry<?> second) {
     if (first.type() != second.type()) {
         return false;
     }
-    assert first.rawContent() != null && second.rawContent() != null;
+    if (first.rawContent() == null || second.rawContent() == null) {
+        return false;
+    }
     return first.rawContent().equals(second.rawContent());
 }
🤖 Prompt for AI Agents
In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`
around lines 317 - 323, Replace the runtime-unsafe assert in isSameContent with
explicit null checks: use Objects.requireNonNull(first.rawContent(),
"first.rawContent() must not be null") and
Objects.requireNonNull(second.rawContent(), "second.rawContent() must not be
null") (import java.util.Objects) before comparing via equals; update the
isSameContent(Entry<?> first, Entry<?> second) method to perform these checks so
nulls are handled deterministically in production.

Copy link
Contributor

@jrhee17 jrhee17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍 👍

public CompletableFuture<PushResultDto> revert(
Repository repository, Author author, RevertRequest request) {
requireNonNull(request, "request");
final Revision headRevision = repository.normalizeNow(Revision.HEAD);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question) Would it make sense to apply the revert within the lock? The following scenario seems counter-intuitive to me

  • Revert request A and push request B is received simultaneously
  • request A fetches the head as version (n)
  • request B wins and a push is applied first, now the repo is version (n + 1)
  • the revert is computed to target (n - k), only diffs between (n - k)..(n) is computed
  • the revert is pushed, applying the revert of (n - k)..(n) on top of (n + 1)
  • given that overwriting methods are used (upsert, removal), no conflict and the push goes through.

I don't think it makes much sense that a revert operation throws a conflict exception either

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that overwriting methods are used (upsert, removal), no conflict and the push goes through.

The head revision (n) is specified for the revert commit.

return push(commitTimeMillis, author, repository, headRevision, request.commitMessage(), changes)

Therefore, if the head revision is advanced by request B, the operation will fail with ChangeConflictException. Do you think it is inappropriate for a revert operation to throw ChangeConflictException?

final Revision normBaseRevision = gitRepository.normalizeNow(baseRevision);
final Revision headRevision = gitRepository.cachedHeadRevision();
if (headRevision.major() != normBaseRevision.major()) {
throw new ChangeConflictException(
"invalid baseRevision: " + baseRevision + " (expected: " + headRevision +
" or equivalent)");
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The head revision (n) is specified for the revert commit.

I see, I think I missed this point. In that case, I think the current changes make sense to me.

Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍 👍

return false;
}
assert first.rawContent() != null && second.rawContent() != null;
return first.rawContent().equals(second.rawContent());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do this in the blocking task executor instead of the repository worker? And is there any chance that this is executed by the event loop when CachingRepository is involved?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this comparison is too expensive to run on the event loop? I didn't understand why we need to offload the computation.

@ikhoon ikhoon modified the milestones: 0.81.0, 0.82.0 Mar 12, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java (3)

304-314: ⚠️ Potential issue | 🟠 Major

Missing checkMetaRepoPush validation before push.

The revert endpoint bypasses the checkMetaRepoPush validation that protects dogma and meta repositories from unauthorized changes. This allows reverting to states that may include disallowed files.

🛡️ Proposed fix
     }).thenCompose(changes -> {
         if (changes.isEmpty()) {
             throw new RedundantChangeException(headRevision,
                                                "No changes to revert. Target revision(" +
                                                targetRevision.major() + ") is the same as HEAD(" +
                                                headRevision.major() + ").");
         }
+        checkMetaRepoPush(repository.name(), changes);
         final long commitTimeMillis = System.currentTimeMillis();
         return push(commitTimeMillis, author, repository, headRevision, request.commitMessage(), changes)
                 .thenApply(rrev -> DtoConverter.newPushResultDto(rrev, commitTimeMillis));
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`
around lines 304 - 314, The revert flow in ContentServiceV1 skips the repository
protection check and should call the existing checkMetaRepoPush validation
before performing push; in the lambda where you currently compute
commitTimeMillis and call push(...), invoke checkMetaRepoPush(repository,
changes) (or the appropriate signature used elsewhere) and handle its failure
before calling push, so protected repositories like "dogma" and "meta" are
validated prior to push and the subsequent DtoConverter.newPushResultDto call.

325-337: ⚠️ Potential issue | 🟠 Major

Replace assert with explicit null check and use IllegalStateException instead of Error.

The assert on line 326 can be disabled at runtime. The Error on line 335 is typically reserved for JVM-level problems; application-level unexpected states should use IllegalStateException.

🔧 Proposed fix
 private static Change<?> toUpsertChange(Entry<?> entry) {
-    assert entry.rawContent() != null;
+    if (entry.rawContent() == null) {
+        throw new IllegalStateException("Entry has no content: " + entry.path());
+    }
     switch (entry.type()) {
         case JSON:
             return Change.ofJsonUpsert(entry.path(), entry.rawContent());
         case YAML:
             return Change.ofYamlUpsert(entry.path(), entry.rawContent());
         case TEXT:
             return Change.ofTextUpsert(entry.path(), entry.rawContent());
         default:
-            throw new Error("unexpected entry type: " + entry.type());
+            throw new IllegalStateException("Unexpected entry type: " + entry.type());
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`
around lines 325 - 337, In toUpsertChange(Entry<?> entry) replace the
runtime-optional assert with an explicit null check for entry.rawContent() and
throw an IllegalStateException if it is null; also change the fallback throw
from new Error(...) to throw new IllegalStateException("unexpected entry type: "
+ entry.type()) so application-level unexpected states use
IllegalStateException; keep existing switch behavior for JSON/YAML/TEXT and
ensure the null-check is done before the switch.

317-323: ⚠️ Potential issue | 🟠 Major

Replace assert with explicit null check.

Assertions can be disabled at runtime with the -da JVM flag, making this validation unreliable in production.

🔧 Proposed fix
 private static boolean isSameContent(Entry<?> first, Entry<?> second) {
     if (first.type() != second.type()) {
         return false;
     }
-    assert first.rawContent() != null && second.rawContent() != null;
+    if (first.rawContent() == null || second.rawContent() == null) {
+        return false;
+    }
     return first.rawContent().equals(second.rawContent());
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`
around lines 317 - 323, The method isSameContent uses an assertion to check
rawContent() non-null which can be disabled; replace the assert with an explicit
null-safe comparison: ensure you still compare types via isSameContent(Entry<?>
first, Entry<?> second) -> check first.type() != second.type() first, then
handle nulls from first.rawContent() or second.rawContent() (e.g. if either is
null return false or use Objects.equals(first.rawContent(), second.rawContent())
to safely compare), referencing the Entry<?> rawContent() and type() methods so
no assertion is used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`:
- Around line 269-273: The revert endpoint currently constructs a Revision from
request.targetRevision() without validating it, causing new Revision(...) to
throw for the default 0 value; update ContentServiceV1 to validate
RevertRequest.targetRevision before calling new Revision: in the method handling
reverts (taking Repository, Author, RevertRequest), check that
request.targetRevision() is present and > 0 (or reject missing/zero with a
400/IllegalArgumentException) and return an appropriate API error; only call
repository.normalizeNow(new
Revision(Integer.toString(request.targetRevision()))) when the targetRevision is
a valid positive integer.

---

Duplicate comments:
In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`:
- Around line 304-314: The revert flow in ContentServiceV1 skips the repository
protection check and should call the existing checkMetaRepoPush validation
before performing push; in the lambda where you currently compute
commitTimeMillis and call push(...), invoke checkMetaRepoPush(repository,
changes) (or the appropriate signature used elsewhere) and handle its failure
before calling push, so protected repositories like "dogma" and "meta" are
validated prior to push and the subsequent DtoConverter.newPushResultDto call.
- Around line 325-337: In toUpsertChange(Entry<?> entry) replace the
runtime-optional assert with an explicit null check for entry.rawContent() and
throw an IllegalStateException if it is null; also change the fallback throw
from new Error(...) to throw new IllegalStateException("unexpected entry type: "
+ entry.type()) so application-level unexpected states use
IllegalStateException; keep existing switch behavior for JSON/YAML/TEXT and
ensure the null-check is done before the switch.
- Around line 317-323: The method isSameContent uses an assertion to check
rawContent() non-null which can be disabled; replace the assert with an explicit
null-safe comparison: ensure you still compare types via isSameContent(Entry<?>
first, Entry<?> second) -> check first.type() != second.type() first, then
handle nulls from first.rawContent() or second.rawContent() (e.g. if either is
null return false or use Objects.equals(first.rawContent(), second.rawContent())
to safely compare), referencing the Entry<?> rawContent() and type() methods so
no assertion is used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 61286d55-0a39-40f6-a8e9-0366dfa109cf

📥 Commits

Reviewing files that changed from the base of the PR and between 4e19cf2 and db34f98.

📒 Files selected for processing (1)
  • server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java

Comment on lines +269 to +273
Repository repository, Author author, RevertRequest request) {
requireNonNull(request, "request");
final Revision headRevision = repository.normalizeNow(Revision.HEAD);
final Revision targetRevision =
repository.normalizeNow(new Revision(Integer.toString(request.targetRevision())));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how Revision handles "0" or invalid values
ast-grep --pattern $'new Revision($_)'
rg -n "class Revision" --type java -A 30 | head -60

Repository: line/centraldogma

Length of output: 50373


🏁 Script executed:

#!/bin/bash
# Find and examine the Revision class definition
fd -t f "Revision.java" --path "*/common/src/main/java*" | head -1 | xargs cat -n | head -100

Repository: line/centraldogma

Length of output: 294


🏁 Script executed:

#!/bin/bash
# Find Revision.java file
fd "Revision.java" "common/src/main/java" -t f

# Then examine the class definition
if [ -f "common/src/main/java/com/linecorp/centraldogma/common/Revision.java" ]; then
  cat -n "common/src/main/java/com/linecorp/centraldogma/common/Revision.java" | head -150
fi

Repository: line/centraldogma

Length of output: 6241


🏁 Script executed:

#!/bin/bash
# Find RevertRequest definition to check default value behavior
fd "RevertRequest.java" -t f

Repository: line/centraldogma

Length of output: 142


🏁 Script executed:

#!/bin/bash
# Examine RevertRequest definition
cat -n "common/src/main/java/com/linecorp/centraldogma/internal/api/v1/RevertRequest.java"

Repository: line/centraldogma

Length of output: 2875


Add input validation for targetRevision in revert endpoint.

When targetRevision is omitted from the JSON payload, it defaults to 0. Passing this to new Revision(...) throws an IllegalArgumentException since Revision rejects zero. Validate the value at the API layer instead:

Proposed fix
     public CompletableFuture<PushResultDto> revert(
             Repository repository, Author author, RevertRequest request) {
         requireNonNull(request, "request");
+        if (request.targetRevision() == 0) {
+            throw new IllegalArgumentException("targetRevision must be specified");
+        }
         final Revision headRevision = repository.normalizeNow(Revision.HEAD);
         final Revision targetRevision =
                 repository.normalizeNow(new Revision(Integer.toString(request.targetRevision())));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Repository repository, Author author, RevertRequest request) {
requireNonNull(request, "request");
final Revision headRevision = repository.normalizeNow(Revision.HEAD);
final Revision targetRevision =
repository.normalizeNow(new Revision(Integer.toString(request.targetRevision())));
Repository repository, Author author, RevertRequest request) {
requireNonNull(request, "request");
if (request.targetRevision() == 0) {
throw new IllegalArgumentException("targetRevision must be specified");
}
final Revision headRevision = repository.normalizeNow(Revision.HEAD);
final Revision targetRevision =
repository.normalizeNow(new Revision(Integer.toString(request.targetRevision())));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@server/src/main/java/com/linecorp/centraldogma/server/internal/api/ContentServiceV1.java`
around lines 269 - 273, The revert endpoint currently constructs a Revision from
request.targetRevision() without validating it, causing new Revision(...) to
throw for the default 0 value; update ContentServiceV1 to validate
RevertRequest.targetRevision before calling new Revision: in the method handling
reverts (taking Repository, Author, RevertRequest), check that
request.targetRevision() is present and > 0 (or reject missing/zero with a
400/IllegalArgumentException) and return an appropriate API error; only call
repository.normalizeNow(new
Revision(Integer.toString(request.targetRevision()))) when the targetRevision is
a valid positive integer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide a way to rollback to certain commit

3 participants