From f1ee6f7ad75ccdb705fd1c009e8ee3af4b73bf32 Mon Sep 17 00:00:00 2001 From: Franklin Koch Date: Fri, 23 Feb 2024 15:23:21 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=AA=AA=20Add=20id=20to=20project=20frontm?= =?UTF-8?q?atter=20and=20populate=20on=20init=20(#934)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🪪 Default project id is only uuid --- .changeset/neat-dancers-carry.md | 6 ++++++ docs/frontmatter.md | 18 ++++++++++++++++++ package-lock.json | 16 ++++++++++++++++ packages/myst-cli/package.json | 2 ++ .../myst-cli/src/build/gh-actions/index.ts | 14 +------------- packages/myst-cli/src/build/init.ts | 5 ++++- packages/myst-cli/src/build/utils/github.ts | 14 ++++++++++++++ packages/myst-cli/src/build/utils/index.ts | 1 + .../myst-frontmatter/src/project/project.yml | 2 ++ packages/myst-frontmatter/src/project/types.ts | 2 ++ .../myst-frontmatter/src/project/validators.ts | 3 +++ 11 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 .changeset/neat-dancers-carry.md create mode 100644 packages/myst-cli/src/build/utils/github.ts diff --git a/.changeset/neat-dancers-carry.md b/.changeset/neat-dancers-carry.md new file mode 100644 index 000000000..cc32f3f18 --- /dev/null +++ b/.changeset/neat-dancers-carry.md @@ -0,0 +1,6 @@ +--- +'myst-frontmatter': patch +'myst-cli': patch +--- + +Add id to project frontmatter and populate on init diff --git a/docs/frontmatter.md b/docs/frontmatter.md index 1a59740cf..3fbd9555c 100644 --- a/docs/frontmatter.md +++ b/docs/frontmatter.md @@ -139,6 +139,21 @@ The following table lists the available frontmatter fields, a brief description * - `options` - a dictionary of arbitrary options validated and consumed by templates, for example, during site or PDF build - page can override project +* - `id` + - id for the project, intended as a unique identifier as the project is used across different contexts + - project only +* - `references` + - configuration for intersphinx references (see [](#intersphinx)) + - project only +* - `requirements` + - files required for reproducing the executional environment, included in the MECA bundle to enable portable execution + - project only +* - `resources` + - other resources associated with your project, distributed in the MECA bundle + - project only +* - `jupyter` or `thebe` + - configuration for Jupyter execution (see [](./integrating-jupyter.md)) + - project only ``` +++ @@ -156,6 +171,9 @@ Frontmatter can be attached to a “page”, meaning a local `.md` or `.ipynb` o `page can override project` : the field is available on both page & project but the value of the field on the page will override any set of the project. Note that the page field must be omitted or undefined, for the project value to be used, value of `null` (or `[]` in the case of `authors`) will still override the project value but clear the field for that page. +`project only` +: the field is only available on projects, and not present on pages and it will be ignored if set there. + +++ (titles)= diff --git a/package-lock.json b/package-lock.json index 8da265109..66f931373 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1727,6 +1727,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, "node_modules/@types/which": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.0.tgz", @@ -12490,6 +12496,14 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/uvu": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", @@ -13884,6 +13898,7 @@ "unist-util-filter": "^4.0.0", "unist-util-remove": "^3.1.0", "unist-util-select": "^4.0.3", + "uuid": "^8.3.2", "vfile": "^5.3.5", "which": "^3.0.1", "ws": "^8.9.0", @@ -13897,6 +13912,7 @@ "@types/fs-extra": "^11.0.1", "@types/inquirer": "^9.0.3", "@types/mime-types": "^2.1.1", + "@types/uuid": "^8.3.4", "@types/which": "^3.0.0", "@types/ws": "^8.5.5", "concurrently": "^8.2.0", diff --git a/packages/myst-cli/package.json b/packages/myst-cli/package.json index fc60efbdc..5cb00d453 100644 --- a/packages/myst-cli/package.json +++ b/packages/myst-cli/package.json @@ -100,6 +100,7 @@ "unist-util-filter": "^4.0.0", "unist-util-remove": "^3.1.0", "unist-util-select": "^4.0.3", + "uuid": "^8.3.2", "vfile": "^5.3.5", "which": "^3.0.1", "ws": "^8.9.0", @@ -113,6 +114,7 @@ "@types/fs-extra": "^11.0.1", "@types/inquirer": "^9.0.3", "@types/mime-types": "^2.1.1", + "@types/uuid": "^8.3.4", "@types/which": "^3.0.0", "@types/ws": "^8.5.5", "concurrently": "^8.2.0", diff --git a/packages/myst-cli/src/build/gh-actions/index.ts b/packages/myst-cli/src/build/gh-actions/index.ts index 945b1a767..cb5d7056f 100644 --- a/packages/myst-cli/src/build/gh-actions/index.ts +++ b/packages/myst-cli/src/build/gh-actions/index.ts @@ -4,6 +4,7 @@ import inquirer from 'inquirer'; import chalk from 'chalk'; import type { ISession } from 'myst-cli-utils'; import { makeExecutable, writeFileToFolder } from 'myst-cli-utils'; +import { getGithubUrl } from '../utils/github.js'; function createGithubPagesAction({ defaultBranch = 'main', @@ -96,19 +97,6 @@ jobs: `; } -export async function getGithubUrl() { - try { - const gitUrl = await makeExecutable('git config --get remote.origin.url', null)(); - if (!gitUrl.includes('github.com')) return undefined; - return gitUrl - .replace('git@github.com:', 'https://github.com/') - .trim() - .replace(/\.git$/, ''); - } catch (error) { - return undefined; - } -} - async function checkFolderIsGit(): Promise { try { await makeExecutable('git status', null)(); diff --git a/packages/myst-cli/src/build/init.ts b/packages/myst-cli/src/build/init.ts index 0f263dc13..b7d20b0b1 100644 --- a/packages/myst-cli/src/build/init.ts +++ b/packages/myst-cli/src/build/init.ts @@ -1,6 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import yaml from 'js-yaml'; +import { v4 as uuid } from 'uuid'; import { defaultConfigFile, loadConfig, writeConfigs } from '../config.js'; import { loadProjectFromDisk } from '../project/load.js'; import { selectors } from '../store/index.js'; @@ -8,12 +9,14 @@ import type { ISession } from '../session/types.js'; import inquirer from 'inquirer'; import chalk from 'chalk'; import { startServer } from './site/start.js'; -import { getGithubUrl, githubCurvenoteAction, githubPagesAction } from './gh-actions/index.js'; +import { githubCurvenoteAction, githubPagesAction } from './gh-actions/index.js'; +import { getGithubUrl } from './utils/github.js'; const VERSION_CONFIG = '# See docs at: https://mystmd.org/guide/frontmatter\nversion: 1\n'; function createProjectConfig({ github }: { github?: string } = {}) { return `project: + id: ${uuid()} # title: # description: keywords: [] diff --git a/packages/myst-cli/src/build/utils/github.ts b/packages/myst-cli/src/build/utils/github.ts new file mode 100644 index 000000000..5ed612e29 --- /dev/null +++ b/packages/myst-cli/src/build/utils/github.ts @@ -0,0 +1,14 @@ +import { makeExecutable } from 'myst-cli-utils'; + +export async function getGithubUrl() { + try { + const gitUrl = await makeExecutable('git config --get remote.origin.url', null)(); + if (!gitUrl.includes('github.com')) return undefined; + return gitUrl + .replace('git@github.com:', 'https://github.com/') + .trim() + .replace(/\.git$/, ''); + } catch (error) { + return undefined; + } +} diff --git a/packages/myst-cli/src/build/utils/index.ts b/packages/myst-cli/src/build/utils/index.ts index a6925295c..0deff91ca 100644 --- a/packages/myst-cli/src/build/utils/index.ts +++ b/packages/myst-cli/src/build/utils/index.ts @@ -5,3 +5,4 @@ export * from './getFileContent.js'; export * from './localArticleExport.js'; export * from './resolveAndLogErrors.js'; export * from './bibtex.js'; +export * from './github.js'; diff --git a/packages/myst-frontmatter/src/project/project.yml b/packages/myst-frontmatter/src/project/project.yml index d40990ed5..25b42714a 100644 --- a/packages/myst-frontmatter/src/project/project.yml +++ b/packages/myst-frontmatter/src/project/project.yml @@ -10,6 +10,7 @@ cases: normalized: {} - title: full object returns self raw: + id: my/project title: frontmatter description: project frontmatter venue: @@ -58,6 +59,7 @@ cases: resources: - my-script.sh normalized: + id: my/project title: frontmatter description: project frontmatter venue: diff --git a/packages/myst-frontmatter/src/project/types.ts b/packages/myst-frontmatter/src/project/types.ts index c57325699..80d8b0d69 100644 --- a/packages/myst-frontmatter/src/project/types.ts +++ b/packages/myst-frontmatter/src/project/types.ts @@ -32,6 +32,7 @@ export const PROJECT_AND_PAGE_FRONTMATTER_KEYS = [ export const PROJECT_FRONTMATTER_KEYS = [ ...PROJECT_AND_PAGE_FRONTMATTER_KEYS, // These keys only exist on the project + 'id', 'references', 'requirements', 'resources', @@ -62,6 +63,7 @@ export type ProjectAndPageFrontmatter = SiteFrontmatter & { }; export type ProjectFrontmatter = ProjectAndPageFrontmatter & { + id?: string; /** Intersphinx and cross-project references */ references?: Record; requirements?: string[]; diff --git a/packages/myst-frontmatter/src/project/validators.ts b/packages/myst-frontmatter/src/project/validators.ts index c7252c58f..02a49da19 100644 --- a/packages/myst-frontmatter/src/project/validators.ts +++ b/packages/myst-frontmatter/src/project/validators.ts @@ -147,6 +147,9 @@ export function validateProjectFrontmatterKeys( ) { const output: ProjectFrontmatter = validateProjectAndPageFrontmatterKeys(value, opts); // This is only for the project, and is not defined on pages + if (defined(value.id)) { + output.id = validateString(value.id, incrementOptions('id', opts)); + } if (defined(value.references)) { const referencesOpts = incrementOptions('references', opts); const references = validateObject(value.references, referencesOpts);