Skip to content

Commit

Permalink
feat(circleci): allow plugins to only specify a subset of hook options
Browse files Browse the repository at this point in the history
This is so that one plugin can override the options of a parent plugin.
In the future it might be worth validating that the final merged hook
options include all the required options but that will be slightly more
complicated and I don't think it's necessary right now.
  • Loading branch information
ivomurrell committed Nov 27, 2024
1 parent c653f9b commit c39850a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 51 deletions.
108 changes: 61 additions & 47 deletions lib/schemas/src/hooks/circleci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,79 @@ import { z } from 'zod'
export const CircleCiCustom = z.record(z.unknown())
export type CircleCiCustom = z.infer<typeof CircleCiCustom>

export const CircleCiExecutor = z.object({
name: z.string(),
image: z.string()
})
export const CircleCiExecutor = z
.object({
name: z.string(),
image: z.string()
})
.partial()
.required({ name: true })
export type CircleCiExecutor = z.infer<typeof CircleCiExecutor>

export const CircleCiJob = z.object({
name: z.string(),
command: z.string()
})
export const CircleCiJob = z
.object({
name: z.string(),
command: z.string()
})
.partial()
.required({ name: true })
export type CircleCiJob = z.infer<typeof CircleCiJob>

export const CircleCiWorkflowJob = z.object({
name: z.string(),
requires: z.array(z.string()),
splitIntoMatrix: z.boolean().optional(),
runOnRelease: z.boolean().default(true),
custom: CircleCiCustom.optional()
})
export const CircleCiWorkflowJob = z
.object({
name: z.string(),
requires: z.array(z.string()),
splitIntoMatrix: z.boolean().optional(),
runOnRelease: z.boolean().default(true),
custom: CircleCiCustom.optional()
})
.partial()
.required({ name: true })
export type CircleCiWorkflowJob = z.infer<typeof CircleCiWorkflowJob>

export const CircleCiWorkflow = z.object({
name: z.string(),
jobs: z.array(CircleCiWorkflowJob),
runOnRelease: z.boolean().optional(),
custom: CircleCiCustom.optional()
})
export const CircleCiWorkflow = z
.object({
name: z.string(),
jobs: z.array(CircleCiWorkflowJob),
runOnRelease: z.boolean().optional(),
custom: CircleCiCustom.optional()
})
.partial()
.required({ name: true })
export type CircleCiWorkflow = z.infer<typeof CircleCiWorkflow>

export const CircleCiCustomConfig = CircleCiCustom
export type CircleCiCustomConfig = z.infer<typeof CircleCiCustomConfig>

export const CircleCiSchema = z.object({
executors: z
.array(CircleCiExecutor)
.optional()
.describe('an array of additional CircleCI executors to output in the generated config.'),
jobs: z
.array(CircleCiJob)
.optional()
.describe(
'an array of additional CircleCI jobs to output in the generated config. these are used for running Tool Kit commands. for running arbitrary shell commands, use `custom`.'
export const CircleCiSchema = z
.object({
executors: z
.array(CircleCiExecutor)
.optional()
.describe('an array of additional CircleCI executors to output in the generated config.'),
jobs: z
.array(CircleCiJob)
.optional()
.describe(
'an array of additional CircleCI jobs to output in the generated config. these are used for running Tool Kit commands. for running arbitrary shell commands, use `custom`.'
),
workflows: z
.array(CircleCiWorkflow)
.optional()
.describe(
'an array of additional CircleCI workflows to output in the generated config. these reference jobs defined in the `jobs` option.'
),
custom: CircleCiCustomConfig.optional().describe(
'arbitrary additional CircleCI configuration that will be merged into the Tool Kit-generated config.'
),
workflows: z
.array(CircleCiWorkflow)
.optional()
.describe(
'an array of additional CircleCI workflows to output in the generated config. these reference jobs defined in the `jobs` option.'
),
custom: CircleCiCustomConfig.optional().describe(
'arbitrary additional CircleCI configuration that will be merged into the Tool Kit-generated config.'
),
disableBaseConfig: z
.boolean()
.optional()
.describe(
'set to `true` to omit the Tool Kit CircleCI boilerplate. should be used along with `custom` to provide your own boilerplate.'
)
})
disableBaseConfig: z
.boolean()
.optional()
.describe(
'set to `true` to omit the Tool Kit CircleCI boilerplate. should be used along with `custom` to provide your own boilerplate.'
)
})
.partial()
.describe(`This hook automatically manages \`.circleci/config.yml\` in your repo to provide configuration for CircleCI workflows to run Tool Kit commands and tasks.
Options provided in your repository's \`.toolkitrc.yml\` for this hook are merged with any Tool Kit plugin that also provides options for the hook.
Expand Down
8 changes: 4 additions & 4 deletions plugins/circleci/src/circleci-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export type CircleCIState = CircleConfig
* hook's config into the larger state, and so each hook only needs to define
* the parts of the config they want to add to.
*/
export type CircleCIStatePartial = PartialDeep<CircleCIState>
export type CircleCIStatePartial = PartialDeep<CircleCIState, { recurseIntoArrays: true }>

// Make this function lazy so that the global options object will have been
// populated first.
Expand Down Expand Up @@ -325,9 +325,9 @@ const mergeInstallationResults = (

const toolKitOrbPrefix = (job: string) => `tool-kit/${job}`

const generateJobs = (workflow: CircleCiWorkflow): Job[] => {
const generateJobs = (workflow: CircleCiWorkflow): Job[] | undefined => {
const runsOnMultipleNodeVersions = getNodeVersions().length > 1
return workflow.jobs.map((job) => {
return workflow.jobs?.map((job) => {
const splitIntoMatrix = runsOnMultipleNodeVersions && (job.splitIntoMatrix ?? true)
return {
[toolKitOrbPrefix(job.name)]: merge(
Expand All @@ -337,7 +337,7 @@ const generateJobs = (workflow: CircleCiWorkflow): Job[] => {
executor: 'node'
},
{
requires: job.requires.map((required) => {
requires: job.requires?.map((required) => {
if (required === 'checkout') {
return required
}
Expand Down

0 comments on commit c39850a

Please sign in to comment.