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

[Infrastructure] Update jquery validate periodically #56725

Merged
merged 17 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 16 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
54 changes: 54 additions & 0 deletions .github/workflows/update-jquery-validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Update jquery-validation

on:
schedule:
- cron: '0 0 1 * *' # Run on the first day of the month
workflow_dispatch: # Allow manual runs

permissions:
contents: write
issues: write
pull-requests: write

jobs:
update-jquery-validate:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'

- name: Set RepoRoot
run: echo "RepoRoot=$(pwd)" >> $GITHUB_ENV

- name: Update dependencies
working-directory: ${{ env.RepoRoot }}/src/Mvc/build
run: |
npm install --no-lockfile
npm run build
npm run update-identity-ui-scripts
echo "JQUERY_VALIDATE_VERSION=$(npm ls jquery-validation --json | jq -r '.dependencies["jquery-validation"].version')" >> $GITHUB_ENV

- name: Update script tags
working-directory: ${{ env.RepoRoot }}/src/Identity/UI
run: node update-jquery-validate.mjs

- name: Create Pull Request
uses: dotnet/actions-create-pull-request@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: Update jquery.validate to ${{ env.JQUERY_VALIDATE_VERSION }}
title: '[Templates][Identity] Update jquery-validation to ${{ env.JQUERY_VALIDATE_VERSION }}'
body: |
Updates the jquery-validation scripts to ${{ env.JQUERY_VALIDATE_VERSION }}
branch: update-jquery-validate-to-${{ env.JQUERY_VALIDATE_VERSION }}
paths: |
**/jquery.validate.js
**/jquery.validate.min.js
**/*.cshtml
src/Identity/UI/jquery-validate-versions.json
4 changes: 4 additions & 0 deletions src/Identity/UI/jquery-validate-versions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"currentVersion": "1.19.5",
"integrity": "sha256-JwUksNJ6/R07ZiLRoXbGeNrtlFZMFDKX4hemPiHOmCA="
}
60 changes: 60 additions & 0 deletions src/Identity/UI/update-jquery-validate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

// Iterate over all the .razor files in Pages and replace
// https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/<<current-version>>/jquery.validate.min.js
// with the new version.
// Also replace the integrity attribute with the new integrity attribute.
// The current integrity attribute and the current version can be read from a json file on this script folder
// called jquery-validate-versions.json that has the following structure:
// {
// "currentVersion": "1.19.5",
// "integrity": "sha256-JwUksNJ6/R07ZiLRoXbGeNrtlFZMFDKX4hemPiHOmCA=",
// "newVersion": "1.20.1",
// "newIntegrity": "sha256-7Z6+1q1Z2+7e5Z2e5Z2+7e5Z2+7e5Z2+7e5Z2+7e5Z2="
// }
// After we've updated the files, we'll update the json file with the new version and integrity.

// Read the JSON file
import fs from 'fs';

const jqueryValidateVersions = JSON.parse(fs.readFileSync('./jquery-validate-versions.json', 'utf8'));

// Get the current version and integrity
const currentVersion = jqueryValidateVersions.currentVersion;
const integrity = jqueryValidateVersions.integrity;

// Get the new version and integrity
const newVersion = jqueryValidateVersions.newVersion;
const newIntegrity = jqueryValidateVersions.newIntegrity;

// Iterate recursively over all the .razor files in the Pages folder
const replaceIntegrity = (dir) => {
const files = fs.readdirSync(dir);
files.forEach((file) => {
const filePath = `${dir}/${file}`;
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
replaceIntegrity(filePath);
} else {
if (filePath.endsWith('.cshtml')) {
// Read the file
let content = fs.readFileSync(filePath, 'utf8');
// Replace the old version with the new version
content = content.replace(`https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/${currentVersion}/jquery.validate.min.js`, `https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/${newVersion}/jquery.validate.min.js`);
// Replace the old integrity with the new integrity
content = content.replace(`integrity="${integrity}"`, `integrity="${newIntegrity}"`);
// Write the file
fs.writeFileSync(filePath, content);
}
}
});
}

replaceIntegrity('./src/Areas/Identity');

// Update the JSON file with the new version and integrity
jqueryValidateVersions.currentVersion = newVersion;
jqueryValidateVersions.integrity = newIntegrity;
delete jqueryValidateVersions.newVersion;
delete jqueryValidateVersions.newIntegrity;

fs.writeFileSync('./jquery-validate-versions.json', JSON.stringify(jqueryValidateVersions, null, 2));
34 changes: 34 additions & 0 deletions src/Mvc/build/copy-files.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as fs from 'fs';
import * as path from 'path';

const repoRoot = process.env.RepoRoot;
if (!repoRoot) {
throw new Error('RepoRoot environment variable is not set')
}

// Search recursively over all the folders in the src directory for the files "jquery.validate.js" and "jquery.validate.min.js" except for node_modules, bin, and obj

const srcDir = path.join(repoRoot, 'src');
const files = [];
const search = (dir) => {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== 'bin' && entry.name !== 'obj') {
search(path.join(dir, entry.name));
} else if (entry.isFile() && (entry.name === 'jquery.validate.js' || entry.name === 'jquery.validate.min.js')) {
files.push(path.join(dir, entry.name));
}
}
}

search(srcDir);

// Replace each found file with the file of the same name that we downloaded during install and that is located in node_modules/jquery-validation/dist/
const nodeModulesDir = path.join(import.meta.dirname, 'node_modules', 'jquery-validation', 'dist');

for (const file of files) {
const source = path.join(nodeModulesDir, path.basename(file));
const target = file;
fs.copyFileSync(source, target);
console.log(`Copied ${path.basename(file)} to ${target}`);
}
12 changes: 12 additions & 0 deletions src/Mvc/build/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "jquery-validation-dependency",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "node copy-files.mjs",
"update-identity-ui-scripts": "node update-identity-ui-integrity.mjs"
},
"devDependencies": {
"jquery-validation": "1.20.0"
}
}
32 changes: 32 additions & 0 deletions src/Mvc/build/update-identity-ui-integrity.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Get jquery.validate.min.js from node_modules/jquery-validation/dist/ and compute its sha256 integrity attribute
// Get the version from node_modules/jquery-validation/package.json
// Update <<RepoRoot>>/src/Identity/UI/jquery-validate-versions.json with the version and integrity attribute
// by adding the newVersion and newIntegrity properties to the top level object.

import crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';

const repoRoot = process.env.RepoRoot;
if (!repoRoot) {
throw new Error('RepoRoot environment variable is not set')
}

// Get the version from node_modules/jquery-validation/package.json
const packageJson = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, 'node_modules', 'jquery-validation', 'package.json')));
const newVersion = packageJson.version;

// Get jquery.validate.min.js from node_modules/jquery-validation/dist/ and compute its sha256 integrity attribute
const nodeModulesDir = path.join(import.meta.dirname, 'node_modules', 'jquery-validation', 'dist');
const source = path.join(nodeModulesDir, 'jquery.validate.min.js');
// Compute Base64(SHA256(jquery.validate.min.js bytes))
const sha256Hash = crypto.createHash('sha256').update(fs.readFileSync(source)).digest('base64');
console.log(`Computed integrity hash for jquery.validate.min.js: sha256-${sha256Hash}`);

// Update <<RepoRoot>>/src/Identity/UI/jquery-validate-versions.json with the version and integrity attribute
const jqueryValidateVersionsFile = path.join(repoRoot, 'src', 'Identity', 'UI', 'jquery-validate-versions.json');
const jqueryValidateVersions = JSON.parse(fs.readFileSync(jqueryValidateVersionsFile));
jqueryValidateVersions.newVersion = newVersion;
jqueryValidateVersions.newIntegrity = `sha256-${sha256Hash}`;
fs.writeFileSync(jqueryValidateVersionsFile, JSON.stringify(jqueryValidateVersions, null, 2));
console.log(`Updated ${jqueryValidateVersionsFile} with new version and integrity hash`);
Loading