Skip to content

Commit

Permalink
Merge branch 'main' into renovate/website-algoliasearch-client-javasc…
Browse files Browse the repository at this point in the history
…ript-monorepo
  • Loading branch information
kodiakhq[bot] authored Nov 20, 2024
2 parents d7965f5 + 89be8a6 commit 5fb057d
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 3 deletions.
56 changes: 55 additions & 1 deletion src/commands/sites/sites-create-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import inquirer from 'inquirer'
import pick from 'lodash/pick.js'
import { render } from 'prettyjson'
import { v4 as uuid } from 'uuid'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import {
chalk,
Expand All @@ -20,7 +22,7 @@ import getRepoData from '../../utils/get-repo-data.js'
import { getGitHubToken } from '../../utils/init/config-github.js'
import { configureRepo } from '../../utils/init/config.js'
import { deployedSiteExists, getGitHubLink, getTemplateName } from '../../utils/sites/create-template.js'
import { createRepo, validateTemplate } from '../../utils/sites/utils.js'
import { callLinkSite, createRepo, validateTemplate } from '../../utils/sites/utils.js'
import { track } from '../../utils/telemetry/index.js'
import { Account, SiteInfo } from '../../utils/types.js'
import BaseCommand from '../base-command.js'
Expand Down Expand Up @@ -190,6 +192,58 @@ export const sitesCreateTemplate = async (repository: string, options: OptionVal
}

log(`🚀 Repository cloned successfully. You can find it under the ${chalk.magenta(repoResp.name)} folder`)

const { linkConfirm } = await inquirer.prompt({
type: 'confirm',
name: 'linkConfirm',
message: `Do you want to link the cloned directory to the site?`,
default: true,
})

if (linkConfirm) {
const __dirname = path.dirname(fileURLToPath(import.meta.url))

const cliPath = path.resolve(__dirname, '../../../bin/run.js')

let stdout
if (repoResp.name) {
stdout = await callLinkSite(cliPath, repoResp.name, '\n')
} else {
error()
return
}

const linkedSiteUrlRegex = /Site url:\s+(\S+)/
const lineMatch = linkedSiteUrlRegex.exec(stdout)
const urlMatch = lineMatch ? lineMatch[1] : undefined
if (urlMatch) {
log(`\nDirectory ${chalk.cyanBright(repoResp.name)} linked to site ${chalk.cyanBright(urlMatch)}\n`)
log(
`${chalk.cyanBright.bold('cd', repoResp.name)} to use other netlify cli commands in the cloned directory.\n`,
)
} else {
const linkedSiteMatch = /Site already linked to\s+(\S+)/.exec(stdout)
const linkedSiteNameMatch = linkedSiteMatch ? linkedSiteMatch[1] : undefined
if (linkedSiteNameMatch) {
log(`\nThis directory appears to be linked to ${chalk.cyanBright(linkedSiteNameMatch)}`)
log('This can happen if you cloned the template into a subdirectory of an existing Netlify project.')
log(
`You may need to move the ${chalk.cyanBright(
repoResp.name,
)} directory out of its parent directory and then re-run the ${chalk.cyanBright(
'link',
)} command manually\n`,
)
} else {
log('A problem occurred linking the site')
log('You can try again manually by running:')
log(chalk.cyanBright(`cd ${repoResp.name} && netlify link\n`))
}
}
} else {
log('To link the cloned directory manually, run:')
log(chalk.cyanBright(`cd ${repoResp.name} && netlify link\n`))
}
}

if (options.withCi) {
Expand Down
9 changes: 9 additions & 0 deletions src/utils/sites/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fetch from 'node-fetch'
import execa from 'execa'

import { log, GitHubRepoResponse, error } from '../command-helpers.js'
import { GitHubRepo, Template } from '../types.js'
Expand Down Expand Up @@ -68,3 +69,11 @@ export const createRepo = async (

return data as GitHubRepoResponse
}

export const callLinkSite = async (cliPath: string, repoName: string, input: string) => {
const { stdout } = await execa(cliPath, ['link'], {
input,
cwd: repoName,
})
return stdout
}
105 changes: 103 additions & 2 deletions tests/integration/commands/sites/sites-create-template.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ import { beforeEach, afterEach, describe, expect, test, vi, afterAll } from 'vit
import BaseCommand from '../../../../src/commands/base-command.ts'
import { createSitesFromTemplateCommand } from '../../../../src/commands/sites/sites.ts'
import { deployedSiteExists, fetchTemplates, getTemplateName } from '../../../../src/utils/sites/create-template.ts'
import { getTemplatesFromGitHub, validateTemplate, createRepo } from '../../../../src/utils/sites/utils.ts'
import {
getTemplatesFromGitHub,
validateTemplate,
createRepo,
callLinkSite,
} from '../../../../src/utils/sites/utils.ts'
import { getEnvironmentVariables, withMockApi } from '../../utils/mock-api.js'
import { chalk } from '../../../../src/utils/command-helpers.ts'

vi.mock('../../../../src/utils/init/config-github.ts')
vi.mock('../../../../src/utils/sites/utils.ts')
Expand Down Expand Up @@ -49,13 +55,16 @@ describe('sites:create-template', () => {
vi
.fn()
.mockImplementationOnce(() => Promise.resolve({ accountSlug: 'test-account' }))
.mockImplementationOnce(() => Promise.resolve({ name: 'test-name' })),
.mockImplementationOnce(() => Promise.resolve({ name: 'test-name' }))
.mockImplementationOnce(() => Promise.resolve({ cloneConfirm: true }))
.mockImplementationOnce(() => Promise.resolve({ linkConfirm: true })),
{
prompts: inquirer.prompt?.prompts || {},
registerPrompt: inquirer.prompt?.registerPrompt || vi.fn(),
restoreDefaultPrompts: inquirer.prompt?.restoreDefaultPrompts || vi.fn(),
},
)

vi.mocked(fetchTemplates).mockResolvedValue([
{
name: 'mockTemplateName',
Expand All @@ -82,6 +91,7 @@ describe('sites:create-template', () => {
full_name: 'mockName',
private: true,
default_branch: 'mockBranch',
name: 'repoName',
})
})

Expand Down Expand Up @@ -145,4 +155,95 @@ describe('sites:create-template', () => {
})
expect(stdoutwriteSpy).toHaveBeenCalledWith('A site with that name already exists on your account\n')
})

test('it should automatically link to the site when the user clones the template repo', async (t) => {
const mockSuccessfulLinkOutput = `
Directory Linked
Admin url: https://app.netlify.com/sites/site-name
Site url: https://site-name.netlify.app
You can now run other \`netlify\` cli commands in this directory
`
vi.mocked(callLinkSite).mockImplementationOnce(() => Promise.resolve(mockSuccessfulLinkOutput))

const autoLinkRoutes = [
{
path: 'accounts',
response: [{ slug: 'test-account' }],
},
{
path: 'sites',
response: [{ name: 'test-name-unique' }],
},
{
path: 'test-account/sites',
response: siteInfo,
method: 'post',
},
]

const stdoutwriteSpy = vi.spyOn(process.stdout, 'write')
await withMockApi(autoLinkRoutes, async ({ apiUrl }) => {
Object.assign(process.env, getEnvironmentVariables({ apiUrl }))

const program = new BaseCommand('netlify')

vi.mocked(deployedSiteExists).mockResolvedValue(false)

createSitesFromTemplateCommand(program)

await program.parseAsync(['', '', 'sites:create-template'])
})

expect(stdoutwriteSpy).toHaveBeenCalledWith(
`\nDirectory ${chalk.cyanBright('repoName')} linked to site ${chalk.cyanBright(
'https://site-name.netlify.app',
)}\n\n`,
)
})

test('it should output instructions if a site is already linked', async (t) => {
const mockUnsuccessfulLinkOutput = `
Site already linked to \"site-name\"
Admin url: https://app.netlify.com/sites/site-name
To unlink this site, run: netlify unlink
`

vi.mocked(callLinkSite).mockImplementationOnce(() => Promise.resolve(mockUnsuccessfulLinkOutput))

const autoLinkRoutes = [
{
path: 'accounts',
response: [{ slug: 'test-account' }],
},
{
path: 'sites',
response: [{ name: 'test-name-unique' }],
},
{
path: 'test-account/sites',
response: siteInfo,
method: 'post',
},
]

const stdoutwriteSpy = vi.spyOn(process.stdout, 'write')
await withMockApi(autoLinkRoutes, async ({ apiUrl }) => {
Object.assign(process.env, getEnvironmentVariables({ apiUrl }))

const program = new BaseCommand('netlify')

vi.mocked(deployedSiteExists).mockResolvedValue(false)

createSitesFromTemplateCommand(program)

await program.parseAsync(['', '', 'sites:create-template'])
})

expect(stdoutwriteSpy).toHaveBeenCalledWith(
`\nThis directory appears to be linked to ${chalk.cyanBright(`"site-name"`)}\n`,
)
})
})

0 comments on commit 5fb057d

Please sign in to comment.