-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Feat: Combine remoteconfig publish and rollback tools #9164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
a824e5c
feat: Combine remoteconfig publish and rollback tools
google-labs-jules[bot] d862f8f
feat: Combine remoteconfig publish and rollback tools
google-labs-jules[bot] 05ec97b
Update src/mcp/tools/remoteconfig/update_template.ts
joehan 08d19c4
Format
joehan a781c9b
fix: Add validation for positive version number
google-labs-jules[bot] 0ccd5f5
Cleaning up typing problem
joehan 66b1bb4
Format
joehan 520959a
Fixing tests
joehan 8db5dd2
Merge branch 'master' into feat/remoteconfig-update-template
joehan 02d8b9d
Merge branch 'master' into feat/remoteconfig-update-template
dsjadaun-google 15bb0c5
Merge branch 'master' into feat/remoteconfig-update-template
joehan 866af6b
Pr suggestion
joehan 26b4b69
Merge branch 'master' into feat/remoteconfig-update-template
joehan b8adc0d
Merge branch 'master' into feat/remoteconfig-update-template
joehan 18f7b0d
Formats
joehan c297133
Merge branch 'master' into feat/remoteconfig-update-template
joehan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
import { ServerTool } from "../../tool"; | ||
import { get_template } from "./get_template"; | ||
import { rollback_template } from "./rollback_template"; | ||
import { publish_template } from "./publish_template"; | ||
import { update_template } from "./update_template"; | ||
|
||
export const remoteConfigTools: ServerTool[] = [get_template, publish_template, rollback_template]; | ||
export const remoteConfigTools: ServerTool[] = [get_template, update_template]; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { expect } from "chai"; | ||
import * as sinon from "sinon"; | ||
import * as nock from "nock"; | ||
import * as api from "../../../api"; | ||
import { RemoteConfigTemplate } from "../../../remoteconfig/interfaces"; | ||
import { update_template } from "./update_template"; | ||
import { toContent } from "../../util"; | ||
import { McpContext } from "../../types"; | ||
|
||
const PROJECT_ID = "the-remote-config-project"; | ||
const TEMPLATE: RemoteConfigTemplate = { | ||
conditions: [], | ||
parameters: {}, | ||
parameterGroups: {}, | ||
etag: "whatever", | ||
version: { | ||
versionNumber: "1", | ||
updateTime: "2020-01-01T12:00:00.000000Z", | ||
updateUser: { | ||
email: "someone@google.com", | ||
}, | ||
updateOrigin: "CONSOLE", | ||
updateType: "INCREMENTAL_UPDATE", | ||
}, | ||
}; | ||
|
||
describe("update_template", () => { | ||
let sandbox: sinon.SinonSandbox; | ||
|
||
beforeEach(() => { | ||
sandbox = sinon.createSandbox(); | ||
}); | ||
|
||
afterEach(() => { | ||
sandbox.restore(); | ||
nock.cleanAll(); | ||
}); | ||
|
||
it("should publish the latest template", async () => { | ||
nock(api.remoteConfigApiOrigin()) | ||
.put(`/v1/projects/${PROJECT_ID}/remoteConfig`) | ||
.reply(200, TEMPLATE); | ||
|
||
const result = await update_template.fn({ template: TEMPLATE }, { | ||
projectId: PROJECT_ID, | ||
} as any as McpContext); | ||
expect(result).to.deep.equal(toContent(TEMPLATE)); | ||
}); | ||
|
||
it("should publish the latest template with * etag", async () => { | ||
nock(api.remoteConfigApiOrigin()) | ||
.put(`/v1/projects/${PROJECT_ID}/remoteConfig`, undefined, { | ||
reqheaders: { | ||
"If-Match": "*", | ||
}, | ||
}) | ||
.reply(200, TEMPLATE); | ||
|
||
const result = await update_template.fn({ template: TEMPLATE, force: true }, { | ||
projectId: PROJECT_ID, | ||
} as any as McpContext); | ||
expect(result).to.deep.equal(toContent(TEMPLATE)); | ||
}); | ||
|
||
it("should reject if the publish api call fails", async () => { | ||
nock(api.remoteConfigApiOrigin()).put(`/v1/projects/${PROJECT_ID}/remoteConfig`).reply(404, {}); | ||
|
||
await expect( | ||
update_template.fn({ template: TEMPLATE }, { projectId: PROJECT_ID } as any as McpContext), | ||
).to.be.rejected; | ||
}); | ||
|
||
it("should return a rollback to the version number specified", async () => { | ||
nock(api.remoteConfigApiOrigin()) | ||
.post(`/v1/projects/${PROJECT_ID}/remoteConfig:rollback?versionNumber=1`) | ||
.reply(200, TEMPLATE); | ||
|
||
const result = await update_template.fn({ version_number: 1 }, { | ||
projectId: PROJECT_ID, | ||
} as any as McpContext); | ||
expect(result).to.deep.equal(toContent(TEMPLATE)); | ||
}); | ||
|
||
it("should reject if the rollback api call fails", async () => { | ||
nock(api.remoteConfigApiOrigin()) | ||
.post(`/v1/projects/${PROJECT_ID}/remoteConfig:rollback?versionNumber=1`) | ||
.reply(404, {}); | ||
|
||
await expect( | ||
update_template.fn({ version_number: 1 }, { projectId: PROJECT_ID } as any as McpContext), | ||
).to.be.rejected; | ||
}); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { z } from "zod"; | ||
import { tool } from "../../tool"; | ||
import { mcpError, toContent } from "../../util"; | ||
import { publishTemplate } from "../../../remoteconfig/publish"; | ||
import { rollbackTemplate } from "../../../remoteconfig/rollback"; | ||
import { RemoteConfigTemplate } from "../../../remoteconfig/interfaces"; | ||
|
||
export const update_template = tool( | ||
{ | ||
name: "update_template", | ||
description: | ||
"Publishes a new remote config template or rolls back to a specific version for the project", | ||
inputSchema: z | ||
.object({ | ||
template: z.object({}).optional().describe("The Remote Config template object to publish."), | ||
version_number: z | ||
.number() | ||
.positive() | ||
.optional() | ||
.describe("The version number to roll back to."), | ||
force: z | ||
.boolean() | ||
.optional() | ||
.describe( | ||
"If true, the publish will bypass ETag validation and overwrite the current template. Defaults to false if not provided.", | ||
), | ||
}) | ||
.refine( | ||
(data) => | ||
(data.template && !data.version_number) || (!data.template && data.version_number), | ||
{ | ||
message: | ||
"Either provide a template for publish, or a version number to rollback to, but not both.", | ||
}, | ||
), | ||
annotations: { | ||
title: "Update Remote Config template", | ||
readOnlyHint: false, | ||
}, | ||
_meta: { | ||
requiresAuth: true, | ||
requiresProject: true, | ||
}, | ||
}, | ||
async ({ template, version_number, force }, { projectId }) => { | ||
if (version_number) { | ||
joehan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return toContent(await rollbackTemplate(projectId, version_number!)); | ||
Check warning on line 47 in src/mcp/tools/remoteconfig/update_template.ts
|
||
} | ||
|
||
if (template) { | ||
if (force === undefined) { | ||
return toContent(await publishTemplate(projectId, template as any as RemoteConfigTemplate)); | ||
} | ||
return toContent( | ||
await publishTemplate(projectId, template as any as RemoteConfigTemplate, { force }), | ||
); | ||
} | ||
|
||
// This part should not be reached due to the refine validation, but as a safeguard: | ||
return mcpError("Either a template or a version number must be specified."); | ||
}, | ||
); |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.