mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20: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'
|
||||
|
||||
export class CommandMatcher implements Matcher {
|
||||
@@ -7,7 +7,7 @@ export class CommandMatcher implements Matcher {
|
||||
this.matcher = new RegExp(command, flags)
|
||||
}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
return !!command.command && this.matcher.test(command.command)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
Command,
|
||||
ICommand,
|
||||
ICondition,
|
||||
IFileExistenceChecker,
|
||||
FileExistenceInput,
|
||||
@@ -30,7 +30,7 @@ export class Condition {
|
||||
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
|
||||
}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
return this.matchers.every((matcher) => {
|
||||
return matcher.match(command)
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Matcher } from './Matcher.js'
|
||||
import { Command } from '../types.js'
|
||||
import { ICommand } from '../types.js'
|
||||
|
||||
export class ErrorMatcher implements Matcher {
|
||||
private matcher?: RegExp
|
||||
@@ -9,7 +9,7 @@ export class ErrorMatcher implements Matcher {
|
||||
}
|
||||
}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
if (!this.matcher) {
|
||||
return !command.error
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Command } from '../types.js'
|
||||
import { ICommand } from '../types.js'
|
||||
|
||||
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'
|
||||
|
||||
export class NotMatcher implements Matcher {
|
||||
constructor(private condition: Matcher) {}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
return !this.condition.match(command)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Command } from '../types.js'
|
||||
import { ICommand } from '../types.js'
|
||||
import { Matcher } from './Matcher.js'
|
||||
|
||||
export class OrMatcher implements Matcher {
|
||||
constructor(private conditions: Matcher[]) {}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
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'
|
||||
|
||||
export class OutputMatcher implements Matcher {
|
||||
@@ -7,7 +7,7 @@ export class OutputMatcher implements Matcher {
|
||||
this.matcher = new RegExp(pattern, args)
|
||||
}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
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'
|
||||
|
||||
export class PwdMatcher implements Matcher {
|
||||
constructor(private pwd: string) {}
|
||||
|
||||
match(command: Command): boolean {
|
||||
match(command: ICommand): boolean {
|
||||
return command.pwd === this.pwd
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface Command {
|
||||
export interface ICommand {
|
||||
command?: string
|
||||
output?: string
|
||||
error?: string
|
||||
@@ -12,7 +12,7 @@ export interface ICondition {
|
||||
pwd?: string
|
||||
or?: ICondition[]
|
||||
not?: ICondition
|
||||
files: FileExistenceInput[]
|
||||
files?: FileExistenceInput[]
|
||||
}
|
||||
|
||||
export enum FileType {
|
||||
@@ -32,3 +32,9 @@ export interface FileExistenceInput extends FileInput {
|
||||
export interface IFileExistenceChecker {
|
||||
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