mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 11:30:12 +08:00
feat: create stage
This commit is contained in:
1 parent
65ad72223b
commit
77fe2d37b3
11 files changed
+67
-18
No files matched your search
@@ -0,0 +1,18 @@
|
|||||||
|
import { IStage, ICommand } from './types'
|
||||||
|
import { Condition } from './condition/Condition'
|
||||||
|
|
||||||
|
export class Stage {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
condition: Condition
|
||||||
|
|
||||||
|
constructor({ id, name, condition }: IStage) {
|
||||||
|
this.id = id
|
||||||
|
this.name = name
|
||||||
|
this.condition = new Condition(condition)
|
||||||
|
}
|
||||||
|
|
||||||
|
satisfies(command: ICommand): boolean {
|
||||||
|
return this.condition.match(command)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
|
|
||||||
export class CommandMatcher implements Matcher {
|
export class CommandMatcher implements Matcher {
|
||||||
@@ -7,7 +7,7 @@ export class CommandMatcher implements Matcher {
|
|||||||
this.matcher = new RegExp(command, flags)
|
this.matcher = new RegExp(command, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return !!command.command && this.matcher.test(command.command)
|
return !!command.command && this.matcher.test(command.command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Command,
|
ICommand,
|
||||||
ICondition,
|
ICondition,
|
||||||
IFileExistenceChecker,
|
IFileExistenceChecker,
|
||||||
FileExistenceInput,
|
FileExistenceInput,
|
||||||
@@ -30,7 +30,7 @@ export class Condition {
|
|||||||
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
||||||
}
|
}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return this.matchers.every((matcher) => {
|
return this.matchers.every((matcher) => {
|
||||||
return matcher.match(command)
|
return matcher.match(command)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
|
|
||||||
export class ErrorMatcher implements Matcher {
|
export class ErrorMatcher implements Matcher {
|
||||||
private matcher?: RegExp
|
private matcher?: RegExp
|
||||||
@@ -9,7 +9,7 @@ export class ErrorMatcher implements Matcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
if (!this.matcher) {
|
if (!this.matcher) {
|
||||||
return !command.error
|
return !command.error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
|
|
||||||
export interface Matcher {
|
export interface Matcher {
|
||||||
match(command: Command): boolean
|
match(command: ICommand): boolean
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
|
|
||||||
export class NotMatcher implements Matcher {
|
export class NotMatcher implements Matcher {
|
||||||
constructor(private condition: Matcher) {}
|
constructor(private condition: Matcher) {}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return !this.condition.match(command)
|
return !this.condition.match(command)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
|
|
||||||
export class OrMatcher implements Matcher {
|
export class OrMatcher implements Matcher {
|
||||||
constructor(private conditions: Matcher[]) {}
|
constructor(private conditions: Matcher[]) {}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return this.conditions.some((condition) => condition.match(command))
|
return this.conditions.some((condition) => condition.match(command))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
|
|
||||||
export class OutputMatcher implements Matcher {
|
export class OutputMatcher implements Matcher {
|
||||||
@@ -7,7 +7,7 @@ export class OutputMatcher implements Matcher {
|
|||||||
this.matcher = new RegExp(pattern, args)
|
this.matcher = new RegExp(pattern, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return !!command.output && this.matcher.test(command.output.trim())
|
return !!command.output && this.matcher.test(command.output.trim())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Command } from '../types.js'
|
import { ICommand } from '../types.js'
|
||||||
import { Matcher } from './Matcher.js'
|
import { Matcher } from './Matcher.js'
|
||||||
|
|
||||||
export class PwdMatcher implements Matcher {
|
export class PwdMatcher implements Matcher {
|
||||||
constructor(private pwd: string) {}
|
constructor(private pwd: string) {}
|
||||||
|
|
||||||
match(command: Command): boolean {
|
match(command: ICommand): boolean {
|
||||||
return command.pwd === this.pwd
|
return command.pwd === this.pwd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface Command {
|
export interface ICommand {
|
||||||
command?: string
|
command?: string
|
||||||
output?: string
|
output?: string
|
||||||
error?: string
|
error?: string
|
||||||
@@ -12,7 +12,7 @@ export interface ICondition {
|
|||||||
pwd?: string
|
pwd?: string
|
||||||
or?: ICondition[]
|
or?: ICondition[]
|
||||||
not?: ICondition
|
not?: ICondition
|
||||||
files: FileExistenceInput[]
|
files?: FileExistenceInput[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FileType {
|
export enum FileType {
|
||||||
@@ -32,3 +32,9 @@ export interface FileExistenceInput extends FileInput {
|
|||||||
export interface IFileExistenceChecker {
|
export interface IFileExistenceChecker {
|
||||||
exists(file: FileInput): Promise<boolean>
|
exists(file: FileInput): Promise<boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IStage {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
condition: ICondition
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { test, expect } from '@jest/globals'
|
||||||
|
import { Stage } from '../src/Stage'
|
||||||
|
|
||||||
|
test('check stage condition', () => {
|
||||||
|
const stage = new Stage({
|
||||||
|
id: 'stage1',
|
||||||
|
name: 'List the files using `ls`',
|
||||||
|
condition: {
|
||||||
|
command: 'ls',
|
||||||
|
pwd: '/home/user',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(
|
||||||
|
stage.satisfies({
|
||||||
|
command: 'ls',
|
||||||
|
pwd: '/home/user',
|
||||||
|
})
|
||||||
|
).toBe(true)
|
||||||
|
expect(
|
||||||
|
stage.satisfies({
|
||||||
|
command: 'ls',
|
||||||
|
pwd: '/home/user/Downloads',
|
||||||
|
})
|
||||||
|
).toBe(false)
|
||||||
|
})
|
||||||
Reference in new issue
Block a user