Skip to content
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

Add fauna schema pull --active #392

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions src/commands/schema/pull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export default class PullSchemaCommand extends SchemaCommand {
"Delete .fsl files in the target directory that are not part of the database schema",
default: false,
}),
staged: Flags.boolean({
description: "Pulls staged schema instead of the active schema",
active: Flags.boolean({
description: "Pulls the active schema instead of the staged schema.",
default: false,
}),
};
Expand All @@ -27,36 +27,30 @@ export default class PullSchemaCommand extends SchemaCommand {
const { url, secret } = await this.fetchsetup();

try {
// Gather remote schema files to download.
const filesres = await fetch(new URL("/schema/1/files", url), {
// Check if there's a staged schema, and require `--staged` if there is one.
const statusres = await fetch(new URL(`/schema/1/staged/status`, url), {
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
});
const filesjson = await filesres.json();
if (filesjson.error) {
this.error(filesjson.error.message);
}

// Check if there's a staged schema, and require `--staged` if there is one.
const params = new URLSearchParams({
version: filesjson.version,
});
const statusres = await fetch(
new URL(`/schema/1/staged/status?${params}`, url),
{
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
}
);
const statusjson = await statusres.json();
if (statusjson.error) {
this.error(statusjson.error.message);
}

if (statusjson.status !== "none" && !this.flags?.staged) {
this.error("There is a staged schema change. Use --staged to pull it.");
} else if (statusjson.status === "none" && this.flags?.staged) {
this.error("There are no staged schema changes to pull.");
let isStagedPull = statusjson.status !== "none" && !this.flags?.active;

// Gather remote schema files to download.
const params = new URLSearchParams({
version: statusjson.version,
staged: isStagedPull ? "true" : "false",
});
const filesres = await fetch(new URL(`/schema/1/files?${params}`, url), {
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
});
const filesjson = await filesres.json();
if (filesjson.error) {
this.error(filesjson.error.message);
}

// Sort for consistent order. It's nice for tests.
Expand Down Expand Up @@ -112,8 +106,15 @@ export default class PullSchemaCommand extends SchemaCommand {
}

for (const filename of filenames) {
const params = new URLSearchParams({
version: statusjson.version,
staged: isStagedPull ? "true" : "false",
});
const fileres = await fetch(
new URL(`/schema/1/files/${encodeURIComponent(filename)}`, url),
new URL(
`/schema/1/files/${encodeURIComponent(filename)}?${params}`,
url
),
{
method: "GET",
headers: { AUTHORIZATION: `Bearer ${secret}` },
Expand Down
85 changes: 45 additions & 40 deletions test/commands/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,15 +326,15 @@ describe(`fauna schema pull`, () => {
.persist()
.post("/", matchFqlReq(query.Now()))
.reply(200, new Date())
.get("/schema/1/files")
.get("/schema/1/staged/status")
.reply(200, { status: "none", version: 0 })
.get("/schema/1/files?version=0&staged=false")
.reply(200, pullfiles)
.get("/schema/1/staged/status?version=0")
.reply(200, { status: "none" })
.get("/schema/1/files/functions.fsl")
.get("/schema/1/files/functions.fsl?version=0&staged=false")
.reply(200, functions)
.get("/schema/1/files/main.fsl")
.get("/schema/1/files/main.fsl?version=0&staged=false")
.reply(200, main)
.get("/schema/1/files/roles%2Fmyrole.fsl")
.get("/schema/1/files/roles%2Fmyrole.fsl?version=0&staged=false")
.reply(200, myrole);

// Running the command with options
Expand Down Expand Up @@ -380,71 +380,76 @@ describe(`fauna schema pull`, () => {
});
}

it(`requires --staged when there's a staged schema`, async () => {
it(`runs schema pull with a staged schema`, async () => {
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);

nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(query.Now()))
.reply(200, new Date())
.get("/schema/1/files")
.get("/schema/1/staged/status")
.reply(200, { status: "ready", version: 0 })
.get("/schema/1/files?version=0&staged=true")
.reply(200, pullfiles)
.get("/schema/1/staged/status?version=0")
.reply(200, { status: "ready" });
.get("/schema/1/staged/status?version=0&staged=true")
.reply(200, { status: "ready" })
.get("/schema/1/files/functions.fsl?version=0&staged=true")
.reply(200, functions)
.get("/schema/1/files/main.fsl?version=0&staged=true")
.reply(200, main)
.get("/schema/1/files/roles%2Fmyrole.fsl?version=0&staged=true")
.reply(200, myrole);

const { error } = await runCommand(
// This should work as normal.
const { stdout } = await runCommand(
withOpts(["schema pull", `--dir=${testdir}`])
);
expect(error?.message).to.equal(
"There is a staged schema change. Use --staged to pull it."
expect(stdout).to.contain("Pull makes the following changes:");
expect(
fs.readFileSync(path.join(testdir, "functions.fsl"), "utf8")
).to.equal(functions.content);
expect(fs.readFileSync(path.join(testdir, "main.fsl"), "utf8")).to.equal(
main.content
);

stubConfirm.restore();
});

it(`disallows --staged when there's no staged schema`, async () => {
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);

nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(query.Now()))
.reply(200, new Date())
.get("/schema/1/files")
.reply(200, pullfiles)
.get("/schema/1/staged/status?version=0")
.reply(200, { status: "none" });

const { error } = await runCommand(
withOpts(["schema pull", `--dir=${testdir}`, `--staged`])
expect(
fs.readFileSync(path.join(testdir, "roles", "myrole.fsl"), "utf8")
).to.equal(myrole.content);
expect(fs.statSync(path.join(testdir, "no.fsl")).isDirectory()).to.equal(
true
);
expect(error?.message).to.equal(
"There are no staged schema changes to pull."
expect(fs.statSync(path.join(testdir, "nofsl")).isDirectory()).to.equal(
true
);
expect(fs.statSync(path.join(testdir, "main.notfsl")).isFile()).to.equal(
true
);

stubConfirm.restore();
});

it(`runs schema pull --staged`, async () => {
it(`runs schema pull --active with a staged schema`, async () => {
const stubConfirm = sinon.stub(inquirer, "confirm").resolves(true);

nock(getEndpoint(), { allowUnmocked: false })
.persist()
.post("/", matchFqlReq(query.Now()))
.reply(200, new Date())
.get("/schema/1/files")
.get("/schema/1/staged/status")
.reply(200, { status: "ready", version: 0 })
.get("/schema/1/files?version=0&staged=false")
.reply(200, pullfiles)
.get("/schema/1/staged/status?version=0")
.get("/schema/1/staged/status?version=0&staged=false")
.reply(200, { status: "ready" })
.get("/schema/1/files/functions.fsl")
.get("/schema/1/files/functions.fsl?version=0&staged=false")
.reply(200, functions)
.get("/schema/1/files/main.fsl")
.get("/schema/1/files/main.fsl?version=0&staged=false")
.reply(200, main)
.get("/schema/1/files/roles%2Fmyrole.fsl")
.get("/schema/1/files/roles%2Fmyrole.fsl?version=0&staged=false")
.reply(200, myrole);

// This should work as normal.
const { stdout } = await runCommand(
withOpts(["schema pull", `--dir=${testdir}`, `--staged`])
withOpts(["schema pull", `--dir=${testdir}`, `--active`])
);
expect(stdout).to.contain("Pull makes the following changes:");
expect(
Expand Down