Skip to content

Commit e5a26d5

Browse files
authored
Merge branch 'master' into inlined.env-import
2 parents ea02e90 + 4aca0cb commit e5a26d5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1847
-1109
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
- Fixed an issue with deploying indexes to Firestore Enterprise edition databases where explicit `__name__` fields could be incorrectly handled.
2+
- The `experimental:mcp` command has been renamed to `mcp`. The old name is now an alias.
13
- `firebase_update_environment` MCP tool supports accepting Gemini in Firebase Terms of Service.
24
- Fixed a bug when `firebase init dataconnect` failed to create a React app when launched from VS Code extension (#9171).
5+
- Improved the clarity of the `firebase apptesting:execute` command when you have zero or multiple apps.

scripts/mcp-tests/gemini-smoke-test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ await client.connect(
1515
new StdioClientTransport({
1616
command: "../../lib/bin/firebase.js",
1717
args: [
18-
"experimental:mcp",
18+
"mcp",
1919
"--only",
2020
"firestore,dataconnect,messaging,remoteconfig,crashlytics,auth,storage,apphosting",
2121
],

scripts/publish.sh

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@
22
set -e
33

44
printusage() {
5-
echo "publish.sh <version>"
5+
echo "publish.sh <version> [branch]"
66
echo "REPOSITORY_ORG and REPOSITORY_NAME should be set in the environment."
77
echo "e.g. REPOSITORY_ORG=user, REPOSITORY_NAME=repo"
88
echo ""
99
echo "Arguments:"
10-
echo " version: 'patch', 'minor', 'major', or 'artifactsOnly'"
10+
echo " version: 'patch', 'minor', 'major', 'artifactsOnly', or 'preview'"
11+
echo " branch: required if version is 'preview'"
1112
}
1213

1314
VERSION=$1
15+
BRANCH=$2
1416
if [[ $VERSION == "" ]]; then
1517
printusage
1618
exit 1
1719
elif [[ $VERSION == "artifactsOnly" ]]; then
1820
echo "Skipping npm package publish since VERSION is artifactsOnly."
1921
exit 0
22+
elif [[ $VERSION == "preview" ]]; then
23+
if [[ $BRANCH == "" ]]; then
24+
printusage
25+
exit 1
26+
fi
2027
elif [[ ! ($VERSION == "patch" || $VERSION == "minor" || $VERSION == "major") ]]; then
2128
printusage
2229
exit 1
@@ -61,6 +68,11 @@ echo "Moved to temporary directory."
6168
echo "Cloning repository..."
6269
git clone "[email protected]:${REPOSITORY_ORG}/${REPOSITORY_NAME}.git"
6370
cd "${REPOSITORY_NAME}"
71+
if [[ $VERSION == "preview" ]]; then
72+
echo "Checking out branch $BRANCH..."
73+
git checkout "$BRANCH"
74+
echo "Checked out branch $BRANCH."
75+
fi
6476
echo "Cloned repository."
6577

6678
echo "Making sure there is a changelog..."
@@ -78,10 +90,18 @@ echo "Running tests..."
7890
npm test
7991
echo "Ran tests."
8092

81-
echo "Making a $VERSION version..."
82-
npm version $VERSION
83-
NEW_VERSION=$(jq -r ".version" package.json)
84-
echo "Made a $VERSION version."
93+
if [[ $VERSION == "preview" ]]; then
94+
echo "Making a preview version..."
95+
sanitized_branch=$(echo "$BRANCH" | sed 's/[^a-zA-Z0-9]/-/g')
96+
npm version prerelease --preid=${sanitized_branch}
97+
NEW_VERSION=$(jq -r ".version" package.json)
98+
echo "Made a preview version."
99+
else
100+
echo "Making a $VERSION version..."
101+
npm version $VERSION
102+
NEW_VERSION=$(jq -r ".version" package.json)
103+
echo "Made a $VERSION version."
104+
fi
85105

86106
echo "Making the release notes..."
87107
RELEASE_NOTES_FILE=$(mktemp)
@@ -95,20 +115,22 @@ echo "Publishing to npm..."
95115
npx [email protected] --before-script ./scripts/clean-shrinkwrap.sh
96116
echo "Published to npm."
97117

98-
echo "Updating package-lock.json for Docker image..."
99-
npm --prefix ./scripts/publish/firebase-docker-image install
100-
echo "Updated package-lock.json for Docker image."
118+
if [[ $VERSION != "preview" ]]; then
119+
echo "Updating package-lock.json for Docker image..."
120+
npm --prefix ./scripts/publish/firebase-docker-image install
121+
echo "Updated package-lock.json for Docker image."
101122

102-
echo "Cleaning up release notes..."
103-
rm CHANGELOG.md
104-
touch CHANGELOG.md
105-
git commit -m "[firebase-release] Removed change log and reset repo after ${NEW_VERSION} release" CHANGELOG.md scripts/publish/firebase-docker-image/package-lock.json
106-
echo "Cleaned up release notes."
123+
echo "Cleaning up release notes..."
124+
rm CHANGELOG.md
125+
touch CHANGELOG.md
126+
git commit -m "[firebase-release] Removed change log and reset repo after ${NEW_VERSION} release" CHANGELOG.md scripts/publish/firebase-docker-image/package-lock.json
127+
echo "Cleaned up release notes."
107128

108-
echo "Pushing to GitHub..."
109-
git push origin master --tags
110-
echo "Pushed to GitHub."
129+
echo "Pushing to GitHub..."
130+
git push origin master --tags
131+
echo "Pushed to GitHub."
111132

112-
echo "Publishing release notes..."
113-
hub release create --file "${RELEASE_NOTES_FILE}" "v${NEW_VERSION}"
114-
echo "Published release notes."
133+
echo "Publishing release notes..."
134+
hub release create --file "${RELEASE_NOTES_FILE}" "v${NEW_VERSION}"
135+
echo "Published release notes."
136+
fi

scripts/publish/cloudbuild.yaml

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,15 @@ steps:
9898
# Publish the package.
9999
- name: "gcr.io/$PROJECT_ID/package-builder"
100100
dir: "${_REPOSITORY_NAME}"
101-
args: ["bash", "./scripts/publish.sh", "${_VERSION}"]
101+
entrypoint: bash
102+
args:
103+
- -c
104+
- |
105+
if [ "${_VERSION}" == "preview" ]; then
106+
./scripts/publish.sh "${_VERSION}" "${_BRANCH}"
107+
else
108+
./scripts/publish.sh "${_VERSION}"
109+
fi
102110
env:
103111
- "REPOSITORY_ORG=${_REPOSITORY_ORG}"
104112
- "REPOSITORY_NAME=${_REPOSITORY_NAME}"
@@ -110,25 +118,51 @@ steps:
110118
# Set up the hub credentials for firepit-builder.
111119
- name: "gcr.io/$PROJECT_ID/firepit-builder"
112120
entrypoint: "bash"
113-
args: ["-c", "mkdir -vp ~/.config && cp -v hub ~/.config/hub"]
121+
args:
122+
- "-c"
123+
- |
124+
if [ "${_VERSION}" != "preview" ]; then
125+
mkdir -vp ~/.config && cp -v hub ~/.config/hub
126+
else
127+
echo "Skipping hub credentials for firepit-builder for preview."
128+
fi
114129
115130
# Publish the firepit builds.
116131
- name: "gcr.io/$PROJECT_ID/firepit-builder"
117-
entrypoint: "node"
118-
args: ["/usr/src/app/pipeline.js", "--package=firebase-tools@latest", "--publish"]
132+
entrypoint: "bash"
133+
args:
134+
- "-c"
135+
- |
136+
if [ "${_VERSION}" != "preview" ]; then
137+
node /usr/src/app/pipeline.js --package=firebase-tools@latest --publish
138+
else
139+
echo "Skipping firepit build for preview version."
140+
fi
119141
120142
# Grab the latest version, store in workspace
121143
- id: "Read New Version Number from npm"
122144
name: "node"
123145
entrypoint: "sh"
124-
args: ["-c", "npm view firebase-tools version > /workspace/version_number.txt"]
146+
args:
147+
- "-c"
148+
- |
149+
if [ "${_VERSION}" != "preview" ]; then
150+
npm view firebase-tools version > /workspace/version_number.txt
151+
else
152+
echo "Skipping version lookup for preview version."
153+
fi
125154
126155
# Publish the Firebase docker image
127156
- name: "gcr.io/cloud-builders/docker"
128-
entrypoint: "sh"
157+
entrypoint: "bash"
129158
args:
130159
- "-c"
131-
- "docker build -t us-docker.pkg.dev/${_ARTIFACT_REGISTRY_PROJECT}/us/firebase:$(cat /workspace/version_number.txt) -t us-docker.pkg.dev/${_ARTIFACT_REGISTRY_PROJECT}/us/firebase:latest -f ./firebase-docker-image/Dockerfile ./firebase-docker-image"
160+
- |
161+
if [ "${_VERSION}" != "preview" ]; then
162+
docker build -t us-docker.pkg.dev/${_ARTIFACT_REGISTRY_PROJECT}/us/firebase:$(cat /workspace/version_number.txt) -t us-docker.pkg.dev/${_ARTIFACT_REGISTRY_PROJECT}/us/firebase:latest -f ./firebase-docker-image/Dockerfile ./firebase-docker-image
163+
else
164+
echo "Skipping docker build for preview version."
165+
fi
132166
133167
images:
134168
- "us-docker.pkg.dev/${_ARTIFACT_REGISTRY_PROJECT}/us/firebase"
@@ -142,6 +176,7 @@ options:
142176

143177
substitutions:
144178
_VERSION: ""
179+
_BRANCH: ""
145180
_KEY_RING: "cloud-build-ring"
146181
_KEY_NAME: "publish"
147182
_REPOSITORY_ORG: "firebase"

scripts/publish/run.sh

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,33 @@
22
set -e
33

44
printusage() {
5-
echo "run.sh <version>"
5+
echo "run.sh <version> [branch]"
66
echo ""
77
echo "Arguments:"
8-
echo " version: 'patch', 'minor', 'major', or 'artifactsOnly'"
8+
echo " version: 'patch', 'minor', 'major', 'artifactsOnly', or 'preview'"
9+
echo " branch: required if version is 'preview'"
910
}
1011

1112
VERSION=$1
13+
BRANCH=$2
1214
if [[ $VERSION == "" ]]; then
1315
printusage
1416
exit 1
17+
elif [[ $VERSION == "preview" ]]; then
18+
if [[ $BRANCH == "" ]]; then
19+
printusage
20+
exit 1
21+
fi
1522
elif [[ ! ($VERSION == "patch" || $VERSION == "minor" || $VERSION == "major" || $VERSION == "artifactsOnly") ]]; then
1623
printusage
1724
exit 1
1825
fi
1926

27+
SUBSTITUTIONS="_VERSION=$VERSION"
28+
if [[ $VERSION == "preview" ]]; then
29+
SUBSTITUTIONS="$SUBSTITUTIONS,_BRANCH=$BRANCH"
30+
fi
31+
2032
THIS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
2133

2234
cd "$THIS_DIR"
@@ -25,5 +37,5 @@ gcloud --project fir-tools-builds \
2537
builds \
2638
submit \
2739
--machine-type=e2-highcpu-8 \
28-
--substitutions=_VERSION=$VERSION \
40+
--substitutions=$SUBSTITUTIONS \
2941
.

src/apphosting/secrets/dialogs.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe("dialogs", () => {
9292
]);
9393
});
9494

95-
it("uses 'service accounts' header if any backend uses more than one service accont", async () => {
95+
it("uses 'service accounts' header if any backend uses more than one service account", async () => {
9696
const table = dialogs.tableForBackends(await dialogs.toMetadata("number", [legacy, modernA]));
9797
const legacyAccounts = await secrets.serviceAccountsForBackend("number", legacy);
9898
expect(table[0]).to.deep.equal(["location", "backend", "service accounts"]);

src/bin/firebase.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
// Check for older versions of Node no longer supported by the CLI.
44
import * as semver from "semver";
5-
import { isEnabled } from "../experiments";
65
const pkg = require("../../package.json");
76
const nodeVersion = process.version;
87
if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
@@ -13,7 +12,7 @@ if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
1312
}
1413

1514
// we short-circuit the normal process for MCP
16-
if (isEnabled("mcp") && process.argv[2] === "experimental:mcp") {
15+
if (process.argv[2] === "mcp" || process.argv[2] === "experimental:mcp") {
1716
const { mcp } = require("./mcp");
1817
mcp();
1918
} else {

src/bin/mcp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ This is a running process of the Firebase MCP server. This command should only b
1414
"mcpServers": {
1515
"firebase": {
1616
"command": "firebase",
17-
"args": ["experimental:mcp", "--dir", "/path/to/firebase/project"]
17+
"args": ["mcp", "--dir", "/path/to/firebase/project"]
1818
}
1919
}
2020
}

src/commands/apptesting-execute.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { FirebaseError } from "../error";
1111
import { marked } from "marked";
1212
import { needProjectId } from "../projectUtils";
1313
import { consoleUrl } from "../utils";
14-
import { AppPlatform, listFirebaseApps } from "../management/apps";
14+
import { AppPlatform, listFirebaseApps, checkForApps } from "../management/apps";
1515

1616
export const command = new Command("apptesting:execute <target>")
1717
.description("Run automated tests written in natural language driven by AI")
@@ -32,13 +32,28 @@ export const command = new Command("apptesting:execute <target>")
3232
.before(requireConfig)
3333
.action(async (target: string, options: any) => {
3434
const projectId = needProjectId(options);
35-
const appList = await listFirebaseApps(projectId, AppPlatform.WEB);
36-
let app = appList.find((a) => a.appId === options.app);
37-
if (!app && appList.length === 1) {
38-
app = appList[0];
39-
logger.info(`No app specified, defaulting to ${app.appId}`);
40-
} else if (!app) {
41-
throw new FirebaseError("Invalid app id");
35+
const apps = await listFirebaseApps(projectId, AppPlatform.WEB);
36+
// Fail out early if there's no apps.
37+
checkForApps(apps, AppPlatform.WEB);
38+
39+
let app = apps.find((a) => a.appId === options.app);
40+
if (!app) {
41+
if (options.app) {
42+
// An app ID was provided, but it's invalid.
43+
throw new FirebaseError(
44+
`App with ID '${options.app}' was not found in project ${projectId}. You can list available apps with 'firebase apps:list'.`,
45+
);
46+
}
47+
// if there's only one app, we don't need to prompt interactively
48+
if (apps.length === 1) {
49+
// If there's only one, use it.
50+
app = apps[0];
51+
} else {
52+
// If there's > 1, fail
53+
throw new FirebaseError(
54+
`Project ${projectId} has multiple apps, must specify a web app id with '--app', you can list available apps with 'firebase apps:list'.`,
55+
);
56+
}
4257
}
4358

4459
const testDir = options.config.src.apptesting?.testDir || "tests";

src/commands/database-instances-create.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const command = new Command("database:instances:create <instanceName>")
2525
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2626
.action(async (instanceName: string, options: any) => {
2727
const projectId = needProjectId(options);
28-
const defaultDatabaseInstance = await getDefaultDatabaseInstance({ project: projectId });
28+
const defaultDatabaseInstance = await getDefaultDatabaseInstance(projectId);
2929
if (defaultDatabaseInstance === "") {
3030
throw new FirebaseError(MISSING_DEFAULT_INSTANCE_ERROR_MESSAGE);
3131
}

0 commit comments

Comments
 (0)