Skip to content

Commit 85b2320

Browse files
authored
Have CI deploy rules/functions to test project as needed (#6531)
1 parent dd9acd0 commit 85b2320

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

.github/workflows/deploy-config.yml

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Deploy Project Config
2+
3+
on: pull_request
4+
5+
# Detects if any project config files (rules or functions) have changed,
6+
# and deploys them to the test project used for CI if so.
7+
# Run this in its own workflow instead of as a step before each test
8+
# workflow to avoid too many deploys, possibly causing race conditions.
9+
# Since the build step of each test workflow takes a long time, this
10+
# this should finish before the tests begin running.
11+
12+
jobs:
13+
test:
14+
name: Deploy Firebase Project Rules and Functions
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout Repo
19+
uses: actions/checkout@master
20+
with:
21+
# This makes Actions fetch all Git history so run-changed script can diff properly.
22+
fetch-depth: 0
23+
- name: Set up Node (14)
24+
uses: actions/setup-node@v2
25+
with:
26+
node-version: 14.x
27+
- name: Yarn install
28+
run: yarn
29+
- name: Deploy project config if needed
30+
run: yarn ts-node scripts/ci-test/deploy-if-needed.ts
31+
env:
32+
FIREBASE_CLI_TOKEN: ${{secrets.FIREBASE_CLI_TOKEN}}

scripts/ci-test/deploy-if-needed.ts

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* @license
3+
* Copyright 2022 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { resolve } from 'path';
19+
import chalk from 'chalk';
20+
import simpleGit from 'simple-git';
21+
import { exec } from 'child-process-promise';
22+
const firebaseTools = require('firebase-tools');
23+
24+
const root = resolve(__dirname, '../..');
25+
const config = require(resolve(root, 'config/ci.config.json'));
26+
const git = simpleGit(root);
27+
28+
interface DeployOptions {
29+
project: string;
30+
token: string;
31+
cwd: string;
32+
only?: string;
33+
}
34+
35+
/**
36+
* Changes to these files require redeployment to the project backend.
37+
*/
38+
const projectConfigGroups = [
39+
{ file: 'config/firebase.json', flag: 'all' },
40+
{ file: 'config/firestore.rules', flag: 'firestore' },
41+
{ file: 'config/firestore.indexes.json', flag: 'firestore' },
42+
{ file: 'config/database.rules.json', flag: 'database' },
43+
{ file: 'config/functions/index.js', flag: 'functions' }
44+
];
45+
46+
/**
47+
* Deploy Firebase project config files (functions, rules) to CI
48+
* test project if there have been any changes to them.
49+
*/
50+
async function deployIfNeeded() {
51+
const token = process.env.FIREBASE_CLI_TOKEN;
52+
if (!token) {
53+
throw new Error('No FIREBASE_CLI_TOKEN found, exiting.');
54+
}
55+
const diff = await git.diff(['--name-only', 'origin/master...HEAD']);
56+
const changedFiles = diff.split('\n');
57+
let flags: string[] = [];
58+
for (const group of projectConfigGroups) {
59+
if (changedFiles.includes(group.file)) {
60+
if (group.flag === 'all') {
61+
flags = ['all'];
62+
break;
63+
}
64+
flags.push(group.flag);
65+
}
66+
}
67+
const deployOptions: DeployOptions = {
68+
project: config.projectId,
69+
token,
70+
cwd: resolve(root, 'config')
71+
};
72+
if (flags.length === 0) {
73+
console.log(
74+
chalk`{green No changes detected in project config files. Not deploying. }`
75+
);
76+
return;
77+
}
78+
if (flags[0] !== 'all') {
79+
deployOptions.only = flags.join(',');
80+
console.log(chalk`{blue Deploying to ${flags.toString()} }`);
81+
} else {
82+
console.log(
83+
chalk`{blue firebase.json changed - deploying full config directory. }`
84+
);
85+
}
86+
if (flags[0] === 'all' || flags.includes('functions')) {
87+
// npm install the dependencies for functions
88+
await exec('npm install', {
89+
cwd: resolve(root, 'config/functions')
90+
});
91+
}
92+
await firebaseTools.deploy(deployOptions);
93+
}
94+
95+
deployIfNeeded();

0 commit comments

Comments
 (0)