From 0ac41fa38640ef18476f44cb659e9c25d33b2d9b Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 15 Aug 2025 08:19:32 -0700 Subject: [PATCH] Further nightlies cleanup (#53302) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/53302 Those files can also go as they've been moved to https://github.com/react-native-community/nightly-tests Changelog: [Internal] [Changed] - Reviewed By: cipolleschi Differential Revision: D80342950 fbshipit-source-id: 0b5cc8f424eefa00c48377fe2fbc2cca5e7ef48d --- .github/workflow-scripts/firebaseUtils.js | 261 ---------------------- .github/workflows/check-nightly.yml | 38 ---- 2 files changed, 299 deletions(-) delete mode 100644 .github/workflow-scripts/firebaseUtils.js delete mode 100644 .github/workflows/check-nightly.yml diff --git a/.github/workflow-scripts/firebaseUtils.js b/.github/workflow-scripts/firebaseUtils.js deleted file mode 100644 index f19d68ea82e..00000000000 --- a/.github/workflow-scripts/firebaseUtils.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -// We connect to firebase using a plain HTTP request because we don't want to -// add yet another devDependency to the react-native monorepo. -class FirebaseClient { - constructor() { - this.email = process.env.FIREBASE_APP_EMAIL; - this.password = process.env.FIREBASE_APP_PASS; - this.apiKey = process.env.FIREBASE_APP_APIKEY; - this.projectId = process.env.FIREBASE_APP_PROJECTNAME; - this.databaseUrl = `${this.projectId}.firebaseio.com`; - this.idToken = null; - } - - async authenticate() { - if (!this.email || !this.password) { - throw new Error( - 'Firebase credentials not found in environment variables', - ); - } - - const authData = { - email: this.email, - password: this.password, - returnSecureToken: true, - }; - - const response = await this.makeRequest( - 'identitytoolkit.googleapis.com', - `/v1/accounts:signInWithPassword?key=${this.apiKey}`, - 'POST', - authData, - ); - - this.idToken = response.idToken; - return; - } - - /** - * Make a database request for a specific date - * @param {string} date - Date in YYYY-MM-DD format - * @param {string} method - HTTP method - * @param {*} data - Data to send (optional) - * @returns {Promise<*>} - Response data - */ - async makeDatabaseRequest(date, method, data = null) { - if (!this.idToken) { - await this.authenticate(); - } - - const path = `/nightly-results/${date}.json?auth=${this.idToken}`; - return this.makeRequest(this.databaseUrl, path, method, data); - } - - /** - * Store test results for a specific date - * @param {string} date - Date in YYYY-MM-DD format - * @param {Array} results - Array of test results - * @returns {Promise} - */ - async storeResults(date, results) { - await this.makeDatabaseRequest(date, 'PUT', results); - console.log(`Successfully stored results for ${date}`); - } - - /** - * Retrieve test results for a specific date - * @param {string} date - Date in YYYY-MM-DD format - * @returns {Promise|null>} - Array of test results or null if not found - */ - async getResults(date) { - try { - return await this.makeDatabaseRequest(date, 'GET'); - } catch (error) { - if (error.message.includes('404')) { - return null; // No results found for this specific date. - } - throw error; - } - } - - /** - * Find the most recent available job results before the given date - * @param {string} currentDate - Current date in YYYY-MM-DD format - * @param {number} maxDaysBack - Maximum number of days to look back (default: 7) - * @returns {Promise<{results: Array|null, date: string|null}>} - Most recent results and their date - */ - async getLatestResults(currentDate, maxDaysBack = 7) { - if (!this.idToken) { - await this.authenticate(); - } - - const currentDateObj = new Date(currentDate); - - for (let daysBack = 1; daysBack <= maxDaysBack; daysBack++) { - const checkDate = new Date(currentDateObj); - checkDate.setDate(checkDate.getDate() - daysBack); - const checkDateStr = checkDate.toISOString().split('T')[0]; - - console.log( - `Checking for results on ${checkDateStr} (${daysBack} days back)...`, - ); - - try { - const results = await this.getResults(checkDateStr); - if (results && results.length > 0) { - console.log( - `Found results from ${checkDateStr} (${daysBack} days back)`, - ); - return {results, date: checkDateStr}; - } - } catch (error) { - console.log(`No results found for ${checkDateStr}: ${error.message}`); - continue; - } - } - - console.log( - `No previous results found within the last ${maxDaysBack} days`, - ); - return {results: null, date: null}; - } - - async makeRequest(hostname, path, method, data = null) { - const url = `https://${hostname}${path}`; - const options = { - method, - headers: { - 'Content-Type': 'application/json', - }, - }; - - if (data) { - options.body = JSON.stringify(data); - } - - const response = await fetch(url, options); - const responseText = await response.text(); - - if (!response.ok) { - let errorMessage; - try { - const parsedError = JSON.parse(responseText); - errorMessage = parsedError.error?.message || responseText; - } catch { - errorMessage = responseText; - } - throw new Error(`HTTP ${response.status}: ${errorMessage}`); - } - - try { - return JSON.parse(responseText); - } catch { - return responseText; - } - } -} - -/** - * Compare current results with previous day's results - * @param {Array} currentResults - Today's test results - * @param {Array} previousResults - Yesterday's test results - * @returns {Object} - Object containing broken and recovered tests - */ -function compareResults(currentResults, previousResults) { - if (!previousResults) { - return { - broken: [], - recovered: [], - newFailures: currentResults.filter(result => result.status !== 'success'), - }; - } - - // Create maps for easier lookup - const currentMap = new Map(); - const previousMap = new Map(); - - currentResults.forEach(result => { - const key = `${result.library}-${result.platform}`; - currentMap.set(key, result); - }); - - previousResults.forEach(result => { - const key = `${result.library}-${result.platform}`; - previousMap.set(key, result); - }); - - const broken = []; - const recovered = []; - - // Check for broken tests (was success, now failed) - for (const [key, currentResult] of currentMap) { - const previousResult = previousMap.get(key); - if (previousResult) { - if ( - previousResult.status === 'success' && - currentResult.status !== 'success' - ) { - broken.push({ - library: currentResult.library, - platform: currentResult.platform, - previousStatus: previousResult.status, - currentStatus: currentResult.status, - }); - } - } - } - - // Check for recovered tests (was failed, now success) - for (const [key, currentResult] of currentMap) { - const previousResult = previousMap.get(key); - if (previousResult) { - if ( - previousResult.status !== 'success' && - currentResult.status === 'success' - ) { - recovered.push({ - library: currentResult.library, - platform: currentResult.platform, - previousStatus: previousResult.status, - currentStatus: currentResult.status, - }); - } - } - } - - return {broken, recovered}; -} - -/** - * Get yesterday's date in YYYY-MM-DD format - * @returns {string} - Yesterday's date - */ -function getYesterdayDate() { - const yesterday = new Date(); - yesterday.setDate(yesterday.getDate() - 1); - return yesterday.toISOString().split('T')[0]; -} - -/** - * Get today's date in YYYY-MM-DD format - * @returns {string} - Today's date - */ -function getTodayDate() { - const today = new Date(); - return today.toISOString().split('T')[0]; -} - -module.exports = { - FirebaseClient, - compareResults, - getYesterdayDate, - getTodayDate, -}; diff --git a/.github/workflows/check-nightly.yml b/.github/workflows/check-nightly.yml deleted file mode 100644 index 183b21cb662..00000000000 --- a/.github/workflows/check-nightly.yml +++ /dev/null @@ -1,38 +0,0 @@ -# This jobs runs every day 2 hours after the nightly job and its purpose is to report -# a failure in case the nightly failed to be published. We are going to hook this to an internal automation. -name: Check Nightlies - -on: - workflow_dispatch: - # nightly build @ 4:15 AM UTC - schedule: - - cron: '15 4 * * *' - -jobs: - check-nightly: - runs-on: ubuntu-latest - if: github.repository == 'facebook/react-native' - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Check nightly - run: | - TODAY=$(date "+%Y%m%d") - echo "Checking nightly for $TODAY" - NIGHTLY="$(npm view react-native | grep $TODAY)" - if [[ -z $NIGHTLY ]]; then - echo 'Nightly job failed.' - exit 1 - else - echo 'Nightly Worked, All Good!' - fi - - test-libraries: - uses: ./.github/workflows/test-libraries-on-nightlies.yml - needs: check-nightly - secrets: - discord_webhook_url: ${{ secrets.NIGHTLY_DISCORD_WEBHOOK }} - firebase_app_email: ${{ secrets.FIREBASE_APP_EMAIL }} - firebase_app_pass: ${{ secrets.FIREBASE_APP_PASS }} - firebase_app_projectname: ${{ secrets.FIREBASE_APP_PROJECTNAME }} - firebase_app_apikey: ${{ secrets.FIREBASE_APP_APIKEY }}