好莱坞
好莱坞从打入的TypeScript定义中生成了GitHub Actions. 还有 运行本地导出动作进行测试.
将 GitHub 动作用于触发器、 工作依赖性、 跑者选择 , 权限和秘密 使用好莱坞进行动作逻辑,输入和 产出、结构化进程执行和生成的工作流程文件.
好莱坞生成标准 action.yml 文件, JavaScript 条目点,以及
工作流程 YAML. 生成动作使用GitHub的官方动作工具包.
文件网站出版
llms.txt 财务报告和审定财务报表
llms-full.txt 用于工具
作为文本使用项目文档.
见 捐款额 (c) 向《公约》/《议定书》/《公约》缔约方会议提供捐款 ROADMAP.md 地图 计划捐款领域。 见 警卫 (b) 强化政策.
文档
已出版的文档现场 https://oss.dedaluslabs.ai/holywood (英语)。 。 。 .
本地构建它们 :
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r docs/requirements.txt
python -m mkdocs serve -f mkdocs.yml
捐款
好莱坞接受来自担保贡献者的外部代码. 由于增加
音量 AI 生成代码, 好莱坞使用 邮袋
作为贡献者信任和CLA资格的仲裁者
请求。 列入 VOUCHED.td 表示维护者已经核实了
GitHub 账户和记录 洛杉矶。 。 。 .
流动是:
- 开"口袋请求"一期.
- 确认您已读取并接受
CLA.md。 。 。 . - 链接公共 GitHub 工作、 项目网站或其他公共身份 帮助维护者识别你.
- 如果现有的担保人认识你,请他们就 问题.
- 一个维护者将您的 GitHub 手柄添加到
VOUCHED.td。 。 。 .
别把自己加进去 VOUCHED.td 在你的第一次贡献。 CLA的检查
从可信任的基础分支读取该文件, 因此正常拉动请求不能
自来自来.
对于代码和docs更改,叉出寄存器并打开来自
您的树枝进入 dedalus-labs/hollywood:main。见
捐款额 完整的核对表.
节点要求
软件包运行时间和寄存器工具链有不同的节点 所需经费:
| 表面 | 节点要求 |
|---|---|
| 已安装软件包和 CLI | 节点20或更新 |
| 生成 GitHub 动作 | GitHub 的节点 24 动作运行时间 |
| 在当地建设好莱坞 | 节点22.18+或节点24.11+ |
已发布的软件包声明 engines.node >=20 内
package.json。构建输出目标20
tsdown.config.ts。 。 。 . tsconfig.json 只检查类型
配置; 这不是运行时支持合同 .
贡献时使用节点22.18+或节点24.11+,因为本地建筑和 声明生成工具链的引擎要求比 已发布运行时间软件包 .
安装
npm install --save-dev @dedalus-labs/hollywood
安装一个本地 hollywood 二进制在 node_modules/.bin/hollywood运行
带它 npx hollywood ...,或设置 hollywood ... 在 npm 脚本中.
运行时间依赖关系
软件包有8个直接运行时间依赖:
@actions/core@actions/exec@actions/expressions@actions/workflow-parser@octokit/openapi-typesesbuildyamlzod
五个依赖提供了 GitHub 的动作工具包,表达式 parser, 工作流程解析器和 REST API 类型。 发布软件包包含运行时间 文件、类型声明、软件包元数据、README和许可证.
前后
在好莱坞之前,一个容器发布步骤可能是这样的:
- name: Publish container image
run: |
set -euo pipefail
IMAGE_REF="ghcr.io/acme/api:${GITHUB_SHA}"
docker buildx build \
--file Dockerfile \
--tag "${IMAGE_REF}" \
--push \
--provenance false \
.
echo "image_ref=${IMAGE_REF}" >> "$GITHUB_OUTPUT"
和好莱坞一起,程序被打入了TypeScript,而不是隐藏在YAML中的文本:
import {
type ActionInputValues,
type ActionOutputValues,
action,
booleanInput,
choiceInput,
integerInput,
pathInput,
stringInput,
stringOutput,
} from "@dedalus-labs/hollywood";
const publishInputs = {
image: stringInput({ description: "Container image name, including registry." }),
tag: stringInput({ description: "Container image tag." }),
context: pathInput({ description: "Build context path.", default: "." }),
dockerfile: pathInput({ description: "Dockerfile path.", default: "Dockerfile" }),
platform: choiceInput({
description: "Build target platform.",
options: ["linux/amd64", "linux/arm64"] as const,
default: "linux/amd64",
}),
provenance: choiceInput({
description: "Build provenance mode.",
options: ["false", "min", "max"] as const,
default: "false",
}),
cacheFrom: stringInput({ description: "Optional build cache source.", default: "" }),
buildAttempt: integerInput({ description: "CI build attempt number." }),
push: booleanInput({ description: "Push instead of loading locally.", default: "true" }),
} as const;
const publishOutputs = {
imageRef: stringOutput({ description: "Published image reference." }),
} as const;
type PublishImageInput = ActionInputValues<typeof publishInputs>;
type PublishImageOutput = ActionOutputValues<typeof publishOutputs>;
const imageRef = (input: Pick<PublishImageInput, "image" | "tag">): string =>
`${input.image}:${input.tag}`;
const dockerBuildArgs = (input: PublishImageInput, ref: string): readonly string[] => {
const args = [
"buildx",
"build",
"--file",
input.dockerfile,
"--platform",
input.platform,
"--tag",
ref,
"--label",
`ci.build-attempt=${input.buildAttempt}`,
"--provenance",
input.provenance,
] as string[];
if (input.cacheFrom.length > 0) {
args.push("--cache-from", input.cacheFrom);
}
args.push(input.push ? "--push" : "--load", input.context);
return args;
};
export const publishImage = action({
name: "publish-container-image",
description: "Build and publish a container image without embedding shell in workflow YAML.",
inputs: publishInputs,
outputs: publishOutputs,
run: async ({ exec, input }): Promise<PublishImageOutput> => {
const ref = imageRef(input);
await exec("docker", dockerBuildArgs(input, ref));
return { imageRef: ref };
},
});
好莱坞解析 GitHub 的字符串输入 PublishImageInput 在此之前 run
启动。 您仍然可以分层 Zod, Effect Schema, 或者您自己的解析器在顶端
特定存储库的政策 :
import { z } from "zod";
const publishPolicy = z.object({
image: z.string().regex(/^ghcr\.io\/[a-z0-9-]+\/[a-z0-9._/-]+$/),
tag: z.string().min(1).max(128).regex(/^[A-Za-z0-9_.-]+$/),
context: z.string().refine((path) => !path.includes(".."), "context must stay inside workspace"),
push: z.boolean(),
});
const validatePublishPolicy = (input: PublishImageInput): void => {
publishPolicy.parse(input);
};
export const publishImage = action({
// ...
run: async ({ exec, input }): Promise<PublishImageOutput> => {
validatePublishPolicy(input);
const ref = imageRef(input);
await exec("docker", dockerBuildArgs(input, ref));
return { imageRef: ref };
},
});
这些计划软件包就住在你的工作流程库里 好莱坞不拉 进入自己的运行时间依赖图.
GitHub 仍然看到一个正常的本地动作步骤:
- name: Publish container image
uses: ./.github/actions/publish-container-image
with:
image: ghcr.io/acme/api
tag: ${{ github.sha }}
context: .
dockerfile: Dockerfile
platform: linux/amd64
provenance: "false"
build-attempt: ${{ github.run_attempt }}
push: "true"
重要的位点是命令形状:
const args = [
"buildx",
"build",
"--file",
input.dockerfile,
"--platform",
input.platform,
"--tag",
ref,
"--label",
`ci.build-attempt=${input.buildAttempt}`,
input.context,
];
await exec("docker", args);
这是 execve(2)- 形状:
一条可执行路径和一系列参数.
没有外壳插值,也没有YAML引用谜题.
本地运行
在持久性 Linux 容器中运行导出动作 :
npx hollywood run gha/containers/publish-image.ts \
--export publishImage \
--provider container \
--with image=ghcr.io/acme/api \
--with tag="$(git rev-parse --short HEAD)" \
--with context=. \
--with dockerfile=Dockerfile \
--with buildAttempt=1 \
--with provenance=false
选择多克、波德曼或苹果 container 当然 Docker 桌面用户
选择 docker 桌面是否使用 Docker VMM 或 Apple 虚拟化
框架:
npx hollywood run gha/cache/s3-cache.ts \
--export s3Cache \
--provider podman \
--with mode=restore \
--with bucket=ci-cache \
--with prefix=node \
--with key=linux-arm64 \
--with archivePath=/tmp/cache.tar.gz \
--with contentsPath=/tmp/node-cache
好莱坞在一个Linux容器中运行与节点24的捆绑动作. 这个
挂载 /github/workspace 并创建选定的 GitHub 文件命令路径,
包括 GITHUB_STATE编辑
默认图像来自 GitHub 的官方动作跑取图像, 并被绑定
通过文摘。 见 执行提供者 支助
和不支持的行为.
对于可重复的本地和CI处决,好莱坞还定义了 已核实的运行中图像一个秘密安全跑者 探测器和机器可读兼容合同.
GitHub 跑车作业
创建单工作 JIT 配置 :
export GITHUB_TOKEN="$(gh auth token)"
npx hollywood runner jit-config OWNER/REPOSITORY \
--runner-group-id 1 \
--label self-hosted hollywood-local
运行匹配的 GitHub 任务与正式动作运行器 :
npx hollywood runner listen .hollywood-jit-config \
--provider docker \
--diagnostics .hollywood/runner-diagnostics
此模式启动被绑 Runner.Listener 财务报告和审定财务报表 Runner.Worker 进程.
工人处理行动前和事后操作、国家传播和工作
钩子. GitHub 提供调度、权限、缓存和文物服务,
OpenID 连接符,日志和工作状态. 模式需要 GitHub 发行
JIT配置并推出工作流程源. 听众可以跑到本地去
工作站或远程主机。 它只需要外出进入GitHub. 见
与 GitHub 跑车运行任务。 。 。 .
生成动作
生成本地行动元数据和切入点:
npx hollywood generate
好莱坞推断出源根来自 gha/ 或者说 ci/,并使用 @/* 从
tsconfig.json 用于在路径别名存在时生成的导入.
好莱坞写普通的 GitHub 动作文件 :
.github/actions/publish-container-image/action.yml
.github/actions/publish-container-image/src/index.ts
.github/workflows/container-release.yml
生成的文件包括标记 :
# @generated by Hollywood. Do not edit by hand.
编辑 TypeScript 源并再生 。 我们建议不要用手拍 生成 YAML .
工作流程来源
好莱坞也可以从打出的工作流程对象生成工作流程YAML:
import { generateWorkflowFile, job, uses, workflow } from "@dedalus-labs/hollywood";
import { gh } from "@dedalus-labs/hollywood/expr";
import { publishImage } from "./containers/publish-image";
export const containerRelease = workflow({
name: "Container Release",
on: {
push: { branches: ["main"] },
workflow_dispatch: {},
},
permissions: { contents: "read", packages: "write" },
jobs: {
publish_image: job({
"runs-on": "ubuntu-latest",
steps: [
{ uses: "actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10" },
uses(publishImage, {
name: "Publish container image",
with: {
image: "ghcr.io/acme/api",
tag: gh.github.sha,
provenance: "false",
},
}),
],
}),
},
});
export default generateWorkflowFile({
sourcePath: "gha/container-release.ts",
sourceRoot: "gha",
workflowsDir: ".github/workflows",
workflow: containerRelease,
});
与本地同时运行独立检查 parallel 财务报告和审定财务报表 background 步骤.
见 类型脚本示例。 。 。 .
使用大小写
当CI/CD步骤是一个真正的程序时,好莱坞是有用的:
- 发布容器图像
- 创建释放文物
- 在环境之间促进 GitOps 显示
- 运行 Terraform 计划/应用包装
- 恢复和保存存储对象的缓存
- 用路径依赖的任务验证拉请求
好莱坞不是本地的GitHub Actions模拟器. GitHub 仍然决定事件 有效载荷、跑道标签、秘密、权限和工作时间安排.
路线图
未来工作在以下各处跟踪: ROADMAP.md 地图具体任务应当成为 GitHub 执行前的问题,特别是如果它们改变了公共API或 生成 YAML .
许可证
麻省理工学院.
发展
npm ci
npm test
npm run build
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r docs/requirements.txt
python -m mkdocs build --strict -f mkdocs.yml
仓库安装禁用依赖的生命周期脚本. 每栋建筑
步骤是明确的,而不是运行代码 npm ci. CI 也拒绝
高度的劝告 缺少或无效的登记签名。 。 。 .