diff --git a/.github/scripts/add-code-samples.ts b/.github/scripts/add-code-samples.ts index 0aaaa7c4..5b072dbc 100644 --- a/.github/scripts/add-code-samples.ts +++ b/.github/scripts/add-code-samples.ts @@ -310,13 +310,32 @@ function mergeSamplesIntoSchema( /** * Write updated OpenAPI schemas back to files */ -function writeOpenAPISchemas(schemas: Array<{ path: string; schema: any }>): void { +function writeOpenAPISchemas(schemas: Array<{ path: string; schema: any }>, outputPath?: string): void { console.log(`šŸ’¾ Writing ${schemas.length} updated schema(s)...`); for (const schemaInfo of schemas) { const content = JSON.stringify(schemaInfo.schema, null, 2); - fs.writeFileSync(schemaInfo.path, content, 'utf-8'); - console.log(` āœ“ Updated ${path.basename(schemaInfo.path)}`); + + // Determine output file path + let outputFilePath: string; + if (outputPath) { + // If output path is provided, save files there + const fileName = path.basename(schemaInfo.path); + + // Ensure output directory exists + if (!fs.existsSync(outputPath)) { + fs.mkdirSync(outputPath, { recursive: true }); + } + + outputFilePath = path.join(outputPath, fileName); + console.log(` āœ… Writing ${fileName} to ${outputPath}`); + } else { + // Otherwise, save in place + outputFilePath = schemaInfo.path; + console.log(` āœ… Updated ${path.basename(schemaInfo.path)}`); + } + + fs.writeFileSync(outputFilePath, content, 'utf-8'); } console.log('āœ… All schemas updated successfully'); @@ -341,10 +360,11 @@ function cleanup(dir: string): void { /** * Main execution function */ -export async function main(directoryPath?: string, pattern?: string): Promise { +export async function main(directoryPath?: string, pattern?: string, outputPath?: string): Promise { // Get command line arguments if not provided let dir = directoryPath; let pat = pattern; + let outPath = outputPath; if (!dir || !pat) { const args = process.argv.slice(2); @@ -352,24 +372,31 @@ export async function main(directoryPath?: string, pattern?: string): Promise '); + console.error('Usage: cd .github/scripts && npm run add-sdk-samples -- [output]'); console.error(''); console.error('Arguments:'); console.error(' - Path to directory containing OpenAPI JSON files'); console.error(' - Regex pattern to match filenames'); + console.error(' [output] - Optional output directory (if not provided, files are saved in place)'); console.error(''); console.error('Examples:'); console.error(' cd .github/scripts && npm run add-sdk-samples -- "../../openapi" "openapi.*\\.json"'); + console.error(' cd .github/scripts && npm run add-sdk-samples -- "../../openapi" "openapi.*\\.json" "../../output"'); return 1; } dir = args[0]; pat = args[1]; + outPath = args[2]; // Optional third argument } console.log('šŸš€ Starting multi-SDK sample extraction...\n'); console.log(`Searching in directory: ${dir}`); - console.log(`Pattern: ${pat}\n`); + console.log(`Pattern: ${pat}`); + if (outPath) { + console.log(`Output directory: ${outPath}`); + } + console.log(); // Find matching OpenAPI files const openapiFiles = findMatchingFiles(dir, pat); @@ -490,7 +517,7 @@ export async function main(directoryPath?: string, pattern?: string): Promise { + if (typeof content !== 'object' || content === null) { + return { result: content, count: 0 } + } + + if (Array.isArray(content)) { + const { result, count } = content.reduce((acc, item) => { + const { result: itemResult, count: itemCount } = replaceValuesForKey(item, key, oldValue, newValue) + return { + result: [...acc.result, itemResult], + count: acc.count + itemCount + } + }, { result: [] as any[], count: 0 }) + return { result, count } + } + + let regex = new RegExp(oldValue, 'g'); + let totalCount = 0; + + const result = Object.keys(content).reduce((acc, objKey) => { + const value = content[objKey] + if ((objKey === key) && typeof value === 'string') { + const matches = value.match(regex); + const count = matches ? matches.length : 0; + totalCount += count; + acc[objKey] = value.replace(regex, newValue) + } else if (typeof value === 'object' && value !== null) { + const { result: nestedResult, count } = replaceValuesForKey(value, key, oldValue, newValue) + totalCount += count; + acc[objKey] = nestedResult + } else { + acc[objKey] = value + } + return acc + }, {} as Record) + + return { result, count: totalCount } +} + /** * Replace all occurrences of provided links with localised version in the given content */ -function replaceLinks(content: string, oldUrl: string, newUrl: string): string { - return content.replace(new RegExp(oldUrl, 'g'), newUrl); +function replaceLinks(content: string, oldUrl: string, newUrl: string): { content: string, count: number } { + let parsed = JSON.parse(content); + let { result: updated, count } = replaceValuesForKey(parsed, 'description', oldUrl, newUrl) + return { content: JSON.stringify(updated, null, 2), count } } /** * Process a single OpenAPI file */ -function processFile(filePath: string, oldUrl: string, newUrl: string): void { +function processFile(filePath: string, oldUrl: string, newUrl: string, outputPath?: string): void { try { console.log(`Processing: ${filePath}`); @@ -36,22 +77,35 @@ function processFile(filePath: string, oldUrl: string, newUrl: string): void { process.exit(1); } - // Count occurrences before replacement - const matches = content.match(new RegExp(oldUrl, 'g')); - const count = matches ? matches.length : 0; + // Replace links and get the actual count + const { content: updatedContent, count } = replaceLinks(content, oldUrl, newUrl); if (count === 0) { console.log(` ā„¹ļø No links to replace in ${filePath}`); return; } - // Replace links - const updatedContent = replaceLinks(content, oldUrl, newUrl); - - // Write back to file - fs.writeFileSync(filePath, updatedContent, 'utf-8'); + // Determine output file path + let outputFilePath: string; + if (outputPath) { + // If output path is provided, save files there + const fileName = path.basename(filePath); + + // Ensure output directory exists + if (!fs.existsSync(outputPath)) { + fs.mkdirSync(outputPath, { recursive: true }); + } + + outputFilePath = path.join(outputPath, fileName); + console.log(` āœ… Replaced ${count} occurrence(s), saved to ${outputFilePath}`); + } else { + // Otherwise, save in place + outputFilePath = filePath; + console.log(` āœ… Replaced ${count} occurrence(s) in ${filePath}`); + } - console.log(` āœ… Replaced ${count} occurrence(s) in ${filePath}`); + // Write to file + fs.writeFileSync(outputFilePath, updatedContent, 'utf-8'); } catch (e) { console.error(` āŒ Error processing ${filePath}:`, (e as Error).message); process.exit(1); @@ -68,16 +122,18 @@ export function main(): number { if (args.length < 4) { console.error('āŒ Error: Missing required arguments'); console.error(''); - console.error('Usage: cd .github/scripts && npm run replace-links -- '); + console.error('Usage: cd .github/scripts && npm run replace-links -- [output]'); console.error(''); console.error('Arguments:'); console.error(' - Path to directory containing JSON files'); console.error(' - Regex pattern to match filenames'); console.error(' - URL to replace'); console.error(' - Replacement URL'); + console.error(' [output] - Optional output directory (if not provided, files are saved in place)'); console.error(''); console.error('Examples:'); - console.error(' cd .github/scripts && npm run replace-links -- "openapi" "openapi.*\\.json" "https://developer.box.com" "https://ja.developer.box.com"'); + console.error(' cd .github/scripts && npm run replace-links -- "../../openapi" "openapi.*\\.json" "https://developer.box.com" "https://ja.developer.box.com"'); + console.error(' cd .github/scripts && npm run replace-links -- "../../openapi" "openapi.*\\.json" "https://developer.box.com" "https://ja.developer.box.com" "output"'); return 1; } @@ -85,10 +141,15 @@ export function main(): number { const pattern = args[1]; const oldUrl = args[2]; const newUrl = args[3]; + const outputPath = args[4]; // Optional fifth argument console.log(`Replacing "${oldUrl}" with "${newUrl}"`); console.log(`Searching in directory: ${directoryPath}`); - console.log(`Pattern: ${pattern}\n`); + console.log(`Pattern: ${pattern}`); + if (outputPath) { + console.log(`Output directory: ${outputPath}`); + } + console.log(); // Find matching files const filePaths = findMatchingFiles(directoryPath, pattern); @@ -104,7 +165,7 @@ export function main(): number { // Process each file for (const filePath of filePaths) { - processFile(filePath, oldUrl, newUrl); + processFile(filePath, oldUrl, newUrl, outputPath); } console.log('\nāœ… All files processed successfully!'); @@ -116,4 +177,3 @@ if (require.main === module) { const exitCode = main(); process.exit(exitCode); } - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38c0db2d..31ac933e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,18 +56,6 @@ jobs: event-type: openapi-update client-payload: "{}" - - name: "Trigger Netlify deployment" - uses: joelwmale/webhook-action@2.4.1 - env: - WEBHOOK_URL: ${{ secrets.NETLIFY_BOXDEV_WEBHOOK }} - data: "{}" - - - name: "Trigger Netlify deployment (Box.dev mirror)" - uses: joelwmale/webhook-action@2.4.1 - env: - WEBHOOK_URL: ${{ secrets.NETLIFY_BOXDEV_MIRROR_WEBHOOK }} - data: "{}" - - name: Send Slack using Slack GHA notification uses: slackapi/slack-github-action@v1.27.0 with: @@ -113,12 +101,6 @@ jobs: FOLDER: openapi GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: "Trigger Netlify deployment" - uses: joelwmale/webhook-action@2.4.1 - env: - WEBHOOK_URL: ${{ secrets.NETLIFY_BOXDEV_STAGING_WEBHOOK }} - data: "{}" - - name: Send Slack using Slack GHA notification uses: slackapi/slack-github-action@v1.27.0 with: diff --git a/.github/workflows/en-api-docs.yml b/.github/workflows/en-api-docs.yml index 3757a806..b4ae1e6b 100644 --- a/.github/workflows/en-api-docs.yml +++ b/.github/workflows/en-api-docs.yml @@ -48,12 +48,12 @@ jobs: - name: Run add-code-samples script working-directory: .github/scripts - run: npm run add-code-samples -- "../../openapi" "openapi.*\\.json" + run: npm run add-code-samples -- "../../openapi" "openapi.*\\.json" "../../output" - name: Push openapi directory to en-api-docs branch uses: s0/git-publish-subdir-action@v2.6.0 env: REPO: self - BRANCH: refs/heads/en-api-docs - FOLDER: openapi - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: en-api-docs + FOLDER: output + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/jp-api-docs.yml b/.github/workflows/jp-api-docs.yml index 702b971d..99fd0efd 100644 --- a/.github/workflows/jp-api-docs.yml +++ b/.github/workflows/jp-api-docs.yml @@ -48,16 +48,16 @@ jobs: - name: Run add-code-samples script working-directory: .github/scripts - run: npm run add-code-samples -- "../../openapi" "openapi.*\\.json" + run: npm run add-code-samples -- "../../openapi" "openapi.*\\.json" "../../output" - name: Run link replacement script working-directory: .github/scripts - run: npm run replace-links -- "../../openapi" "openapi.*\\.json" "https://developer.box.com/" "https://developer.box.com/ja/" + run: npm run replace-links -- "../../output" "openapi.*\\.json" "https://developer.box.com" "https://developer.box.com/ja" - name: Push openapi directory to jp-api-docs branch uses: s0/git-publish-subdir-action@v2.6.0 env: REPO: self - BRANCH: refs/heads/jp-api-docs - FOLDER: openapi + BRANCH: jp-api-docs + FOLDER: output GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/notify.yml b/.github/workflows/notify.yml index 3a1b31f7..07762e42 100644 --- a/.github/workflows/notify.yml +++ b/.github/workflows/notify.yml @@ -9,7 +9,7 @@ on: - jp jobs: - # A task that notifies Netlify of changes to the jp branch + # A task that notifies other repositories of changes to the jp branch notify-from-jp: # We run this on the latest ubuntu runs-on: ubuntu-latest