-
Notifications
You must be signed in to change notification settings - Fork 67
feat: plugin synchronization from repository to CMS #820
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
Merged
Merged
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
7b97396
chore: wip
nickytonline 19fa8e6
chore: switched to ES2022 for TS
nickytonline edcb194
chore: got query returning actual authors instead of refs
nickytonline 7bb4943
chore: moved back to TypeScript because existing tests aren't current…
nickytonline a560cfd
test: added tests for getSanityPluginLookup
nickytonline a059c6d
chore: added a new line at end of gitignore
nickytonline a01a086
chore: added getPluginDiffsForSanity
nickytonline 78db1b0
chore: refactor to avoid passing in a Promise
nickytonline 836ec22
chore: removed commented out dead code
nickytonline 6d62bb8
chore: fix type import for SanityClient
nickytonline 1f04cf3
chore: added GH action to synch plugins to CMS
nickytonline b32b988
chore: added some TODOs for going to production with the sync to CMS …
nickytonline 0fa5977
chore: cleaning up the script a bit
nickytonline b0101df
chore: added _id field to query so it can be used to retrieve full ob…
nickytonline b80c77a
chore: now only number of diffs is logged instead of payload
nickytonline 6985148
chore: first iteration of updating CMS working
nickytonline a92eedb
chore: plugin sync to CMS now includes plugin compatibility property
nickytonline 036dfad
chore: fixed some logic/tests
nickytonline 19a2b31
chore: added some logging around plugin diffs found
nickytonline de0661b
chore: fixed some issues around plugins sync in regards to authors
nickytonline 8751c55
chore: improved log messaging
nickytonline 4dedfa6
chore: added some comments and more types
nickytonline dd21118
chore: renamed synchronization script
nickytonline d6e60af
chore: removed dryrun config used for debugging purposes
nickytonline 8ef77b4
chore: updated a type
nickytonline 5be7bf7
chore: cleaned up some comments
nickytonline 905be79
chore: promisises from fs is aliased now
nickytonline 55b1c0d
chore: fixed a type typo
nickytonline 314e47f
Merge remote-tracking branch 'origin/main' into nickytonline/sync-plu…
nickytonline 599099d
chore: updated logic for compatibility field now that CMS schema has …
nickytonline 06ce3e5
chore: updated comment on how to run script for local development
nickytonline 8e82935
chore: added the Sanity uuid package to generate _key properties for …
nickytonline b155978
chore: clean up diff logic for plugins to Sanity sync
nickytonline 780d0c9
chore: adds a _key field to compatibility items as required by Sanity
nickytonline c95dbd0
test: updated tests
nickytonline aa84c9f
chore: removed unused fields for sync
nickytonline 08e4004
chore: added some more comments
nickytonline 623313d
chore: stripped _key property for compatibility array comparison
nickytonline 05d93ec
test: updated test to ensure _key properties are in compatibility items
nickytonline 7859001
chore: removed environment config from sync GitHub action
nickytonline c0f3829
Merge remote-tracking branch 'origin/main' into nickytonline/sync-plu…
nickytonline 900b903
chore: removed running sync HG action on PR changes
nickytonline 3db0190
chore: added a guard to not run repo to cms sync if cms_sync PR label…
nickytonline 3dc374e
chore: added a comment about the GH action guard
nickytonline 51cdb27
Merge remote-tracking branch 'origin/main' into nickytonline/sync-plu…
nickytonline File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| name: Sync Plugins to CMS | ||
| on: | ||
| pull_request: | ||
| types: | ||
| - closed | ||
| jobs: | ||
| sync-to-cms: | ||
| # Only run if the merged PR wasn't an automated PR for synching from the cms to the repo | ||
| if: github.event.pull_request.merged && !contains(github.event.pull_request.labels.*.name, 'cms_sync') | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Git checkout | ||
| uses: actions/checkout@v3 | ||
| - name: Using Node.js | ||
| uses: actions/setup-node@v3 | ||
| with: | ||
| node-version: '*' | ||
| cache: 'npm' | ||
| check-latest: true | ||
| - name: Install dependencies | ||
| run: npm install | ||
| - name: Sync plugins to CMS | ||
| env: | ||
| SANITY_API_TOKEN: ${{ secrets.SANITY_API_TOKEN }} | ||
| SANITY_PROJECT_ID: ${{ secrets.SANITY_PROJECT_ID }} | ||
| SANITY_DATASET: ${{ secrets.SANITY_DATASET }} | ||
| run: npx tsx bin/sync_plugins_to_cms.js | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| // eslint-env node | ||
nickytonline marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /* eslint-disable n/prefer-global/process */ | ||
| import { promises as fs } from 'fs' | ||
| import path from 'path' | ||
|
|
||
| import sanityClient from '@sanity/client' | ||
| import { uuid } from '@sanity/uuid' | ||
|
|
||
| // when testing this script locally, add a path in your .env for GITHUB_WORKSPACE or pass it in | ||
| // e.g. GITHUB_WORKSPACE="$(pwd)" npx tsx bin/sync_plugins_to_cms.js | ||
|
|
||
| /** | ||
| * @typedef { import("../types/plugins").SanityBuildPluginEntity } SanityBuildPluginEntity | ||
| * @typedef { import("@sanity/client").SanityClient } SanityClient | ||
| * @typedef { import("@sanity/client").Transaction } Transaction | ||
| * @typedef { import("@sanity/client").Patch } Patch | ||
| * @typedef { import("../types/plugins").BuildPluginEntity } BuildPluginEntity | ||
| */ | ||
|
|
||
| import { getPluginDiffsForSanity, getSanityPluginLookup } from './utils.js' | ||
|
|
||
| if (process.env.NODE_ENV === 'development') { | ||
| // Using dotenv for local development. | ||
| console.log('running in development mode') | ||
|
|
||
| const dotenv = await import('dotenv') | ||
| dotenv.config() | ||
| } | ||
|
|
||
| const { GITHUB_WORKSPACE, SANITY_API_TOKEN, SANITY_PROJECT_ID, SANITY_DATASET } = process.env | ||
| const [apiVersion] = new Date().toISOString().split('T') | ||
|
|
||
| const config = { | ||
| projectId: SANITY_PROJECT_ID, | ||
| dataset: SANITY_DATASET, | ||
| apiVersion, | ||
| token: SANITY_API_TOKEN, | ||
| // make sure we have the freshest data when doing the diff with plugins.json | ||
| useCdn: false, | ||
| } | ||
|
|
||
| /** | ||
| * Creates a transaction containing updates to plugins for the CMS | ||
| * | ||
| * @param {Transaction} transaction | ||
| * @param {Patch} patch | ||
| * @param {BuildPluginEntity[]} diffs | ||
| * @returns | ||
| */ | ||
| const createUpdates = (transaction, patch, diffs) => | ||
| diffs.reduce((tx, plugin) => { | ||
| const { _id, ...changes } = plugin | ||
| const fieldUpdates = {} | ||
| const fieldRemovals = [] | ||
|
|
||
| for (const [key, value] of Object.entries(changes)) { | ||
| // any property that is null needs to be unset instead of being set to null | ||
| if (value === null) { | ||
| fieldRemovals.push(key) | ||
| } else { | ||
| fieldUpdates[key] = value | ||
| } | ||
| } | ||
|
|
||
| const update = patch(_id).set(fieldUpdates) | ||
|
|
||
| if (fieldRemovals.length !== 0) { | ||
| update.unset(fieldRemovals) | ||
| } | ||
|
|
||
| tx.patch(update) | ||
|
|
||
| return tx | ||
| }, transaction) | ||
|
|
||
| /** | ||
| * @type {SanityClient} | ||
| */ | ||
| const client = sanityClient(config) | ||
|
|
||
| // These are the only fields to synch for the moment. | ||
| const query = `*[_type == "buildPlugin"] { | ||
| _id, | ||
| packageName, | ||
| version, | ||
| compatibility[] | ||
| }` | ||
|
|
||
| // TODO: Add a retry mechanism to handle network errors | ||
nickytonline marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| try { | ||
| const pluginsFilePath = path.join(GITHUB_WORKSPACE, '/site/plugins.json') | ||
| const fileContents = await fs.readFile(pluginsFilePath) | ||
| const plugins = JSON.parse(fileContents).map((plugin) => { | ||
| // Ensure if a compatibility field exists, that it has all the necessary fields to sync with Sanity | ||
| if (plugin.compatibility) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| plugin.compatibility = plugin.compatibility.map((compatibilityItem) => { | ||
| const updatedCompatibilityItem = { | ||
| // A _key property is required by Sanity so each array item can be identified in a collaborative way | ||
| // See https://www.sanity.io/docs/array-type#92296c6c45ea | ||
| _key: uuid(), | ||
| ...compatibilityItem, | ||
| } | ||
|
|
||
| return updatedCompatibilityItem | ||
| }) | ||
| } | ||
|
|
||
| return plugin | ||
| }) | ||
|
|
||
| console.info('Detecting plugin changes...') | ||
|
|
||
| /** | ||
| * @type {SanityBuildPluginEntity[]} | ||
| */ | ||
| const sanityBuildPlugins = await client.fetch(query, {}) | ||
| const sanityPluginLookup = await getSanityPluginLookup(sanityBuildPlugins) | ||
| const pluginDiffs = getPluginDiffsForSanity(sanityPluginLookup, plugins) | ||
|
|
||
| if (pluginDiffs.length === 0) { | ||
| console.info('No plugin changes found.') | ||
| } else { | ||
| console.info(`Found ${pluginDiffs.length} plugins with changes`) | ||
| console.info('Updating plugins...') | ||
|
|
||
| const transaction = createUpdates(client.transaction(), client.patch, pluginDiffs) | ||
|
|
||
| client.mutate(transaction) | ||
| console.info('Plugins were updated in the CMS.') | ||
| } | ||
| } catch (error) { | ||
| console.error(error) | ||
| throw new Error('Unable to synchronize plugins to the CMS') | ||
| } | ||
|
|
||
| /* eslint-enable n/prefer-global/process */ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| { | ||
| "compilerOptions": { | ||
| /* Visit https://aka.ms/tsconfig.json to read more about this file */ | ||
|
|
||
| /* Projects */ | ||
| // "incremental": true, /* Enable incremental compilation */ | ||
| // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ | ||
| // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ | ||
| // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ | ||
| // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ | ||
| // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ | ||
|
|
||
| /* Language and Environment */ | ||
| "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, | ||
| // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ | ||
| // "jsx": "preserve", /* Specify what JSX code is generated. */ | ||
| // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ | ||
| // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ | ||
| // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ | ||
| // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ | ||
| // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ | ||
| // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ | ||
| // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ | ||
| // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ | ||
|
|
||
| /* Modules */ | ||
| "module": "ES2022" /* Specify what module code is generated. */, | ||
| // "rootDir": "./", /* Specify the root folder within your source files. */ | ||
| "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, | ||
| // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ | ||
| // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ | ||
| // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ | ||
| // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ | ||
| // "types": [], /* Specify type package names to be included without being referenced in a source file. */ | ||
| // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ | ||
| // "resolveJsonModule": true, /* Enable importing .json files */ | ||
| // "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */ | ||
|
|
||
| /* JavaScript Support */ | ||
| // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ | ||
| // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ | ||
| // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ | ||
|
|
||
| /* Emit */ | ||
| // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ | ||
| // "declarationMap": true, /* Create sourcemaps for d.ts files. */ | ||
| // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ | ||
| // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ | ||
| // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ | ||
| // "outDir": "./", /* Specify an output folder for all emitted files. */ | ||
| // "removeComments": true, /* Disable emitting comments. */ | ||
| // "noEmit": true, /* Disable emitting files from a compilation. */ | ||
| // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ | ||
| // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ | ||
| // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ | ||
| // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ | ||
| // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ | ||
| // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ | ||
| // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ | ||
| // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ | ||
| // "newLine": "crlf", /* Set the newline character for emitting files. */ | ||
| // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ | ||
| // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ | ||
| // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ | ||
| // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ | ||
| // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ | ||
| // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ | ||
|
|
||
| /* Interop Constraints */ | ||
| // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ | ||
| // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ | ||
| "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, | ||
| // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ | ||
| "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, | ||
|
|
||
| /* Type Checking */ | ||
| "strict": true /* Enable all strict type-checking options. */, | ||
| // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ | ||
| // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ | ||
| // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ | ||
| // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ | ||
| // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ | ||
| // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ | ||
| // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ | ||
| // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ | ||
| // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ | ||
| // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ | ||
| // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ | ||
| // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ | ||
| // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ | ||
| // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ | ||
| // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ | ||
| // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ | ||
| // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ | ||
| // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ | ||
|
|
||
| /* Completeness */ | ||
| // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ | ||
| "skipLibCheck": true /* Skip type checking all .d.ts files. */ | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@estephinson @tzmanics, this is the guard to prevent a potential infinite loop of sync repo to cms/cms to repo I mentioned. Ed or whoever will need to reapprove the PR.