Skip to content

Commit

Permalink
Bug fix: Cloud Functions Runtime Config Hash Value (#5355)
Browse files Browse the repository at this point in the history
Bug fix: convert runtime configuration into a sorted array
  • Loading branch information
mercury2269 authored Jan 10, 2023
1 parent b501f07 commit 127ca3f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Fix bug where CLI was unable to deploy Firebase Functions in some monorepo setups (#5391)
- Upgrade Storage Rules Runtime to v1.1.3 to support ternary operators (#5370)
- Fixes an issue where already deployed functions with the same remote configuration do not get skipped (#5354)
17 changes: 16 additions & 1 deletion src/deploy/functions/prepareFunctionsUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ interface PackagedSourceInfo {
hash: string;
}

type SortedConfig = string | { key: string; value: SortedConfig }[];

// TODO(inlined): move to a file that's not about uploading source code
export async function getFunctionsConfig(projectId: string): Promise<Record<string, unknown>> {
try {
Expand Down Expand Up @@ -88,8 +90,11 @@ async function packageSource(
});
}
if (typeof runtimeConfig !== "undefined") {
// In order for hash to be consistent, configuration object tree must be sorted by key, only possible with arrays.
const runtimeConfigHashString = JSON.stringify(convertToSortedKeyValueArray(runtimeConfig));
hashes.push(runtimeConfigHashString);

const runtimeConfigString = JSON.stringify(runtimeConfig, null, 2);
hashes.push(runtimeConfigString);
archive.append(runtimeConfigString, {
name: CONFIG_DEST_FILE,
mode: 420 /* 0o644 */,
Expand Down Expand Up @@ -125,3 +130,13 @@ export async function prepareFunctionsUpload(
): Promise<PackagedSourceInfo | undefined> {
return packageSource(sourceDir, config, runtimeConfig);
}

export function convertToSortedKeyValueArray(config: any): SortedConfig {
if (typeof config !== "object" || config === null) return config;

return Object.keys(config)
.sort()
.map((key) => {
return { key, value: convertToSortedKeyValueArray(config[key]) };
});
}
48 changes: 48 additions & 0 deletions src/test/deploy/functions/prepareFunctionsUpload.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect } from "chai";
import * as prepareFunctionsUpload from "../../../deploy/functions/prepareFunctionsUpload";

describe("prepareFunctionsUpload", () => {
describe("convertToSortedKeyValueArray", () => {
it("should deep sort the resulting array when an input config object is not sorted", () => {
const config = {
b: "b",
a: {
b: {
c: "c",
a: "a",
},
a: "a",
},
};
const expected = [
{
key: "a",
value: [
{ key: "a", value: "a" },
{
key: "b",
value: [
{
key: "a",
value: "a",
},
{
key: "c",
value: "c",
},
],
},
],
},
{ key: "b", value: "b" },
];
expect(prepareFunctionsUpload.convertToSortedKeyValueArray(config)).to.deep.equal(expected);
});
it("should return null when config input is null", () => {
expect(prepareFunctionsUpload.convertToSortedKeyValueArray(null)).to.be.equal(null);
});
it("should return an empty array when config input is an empty object", () => {
expect(prepareFunctionsUpload.convertToSortedKeyValueArray({})).to.deep.equal([]);
});
});
});

0 comments on commit 127ca3f

Please sign in to comment.