feat(build): ENV-first Deno + discovery metadata (os/arch/github ref) + Xcode Cloud

- env.go (new): DENO_ENABLE and DENO_BUILD environment variables activate
  Deno builds even when repo only has package.json or bare frontend/ dir
- wails.go + node.go + apple.go + release.yml + xcode_cloud.go: honor the
  ENV flags across builder + workflow + Xcode Cloud script generation
- discovery.go: record host os/arch + GitHub ref metadata (ref, branch, tag,
  is_tag, sha, short_sha, repo, owner)
- api/provider.go: /discover exposes the new metadata
- Regression coverage across discovery/builders/apple/workflow/xcode_cloud/api

Verified: go test ./... passes

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-04-14 21:35:50 +01:00
parent cbdb8028dc
commit 293dfd6e66
16 changed files with 377 additions and 8 deletions

View file

@ -175,6 +175,8 @@ func TestBuildCmd_RunReleaseWorkflow_Good(t *testing.T) {
assert.Contains(t, content, "libwebkit2gtk-4.1-dev")
assert.Contains(t, content, "Install MkDocs")
assert.Contains(t, content, "Setup Deno")
assert.Contains(t, content, "env.DENO_ENABLE == 'true'")
assert.Contains(t, content, "inputs.deno-build != ''")
assert.Contains(t, content, "build-cache:")
assert.Contains(t, content, "Restore build cache")
assert.Contains(t, content, "actions/cache@v4")
@ -236,6 +238,8 @@ func TestBuildCmd_RunReleaseWorkflow_Good(t *testing.T) {
assert.Contains(t, content, "Install Linux Wails dependencies")
assert.Contains(t, content, "Install MkDocs")
assert.Contains(t, content, "Setup Deno")
assert.Contains(t, content, "env.DENO_ENABLE == 'true'")
assert.Contains(t, content, "inputs.deno-build != ''")
assert.Contains(t, content, "build-cache:")
assert.Contains(t, content, "Restore build cache")
assert.Contains(t, content, "--sign=false")

View file

@ -332,6 +332,8 @@ func (p *BuildProvider) discoverProject(c *gin.Context) {
c.JSON(http.StatusOK, api.OK(map[string]any{
"types": typeStrings,
"os": discovery.OS,
"arch": discovery.Arch,
"primary": primary,
"primary_stack": discovery.PrimaryStack,
"suggested_stack": discovery.SuggestedStack,
@ -339,6 +341,14 @@ func (p *BuildProvider) discoverProject(c *gin.Context) {
"has_frontend": discovery.HasFrontend,
"has_subtree_npm": discovery.HasSubtreeNpm,
"linux_packages": discovery.LinuxPackages,
"ref": discovery.Ref,
"branch": discovery.Branch,
"tag": discovery.Tag,
"is_tag": discovery.IsTag,
"sha": discovery.SHA,
"short_sha": discovery.ShortSHA,
"repo": discovery.Repo,
"owner": discovery.Owner,
"build_options": options.String(),
"options": map[string]any{
"obfuscate": options.Obfuscate,

View file

@ -944,6 +944,9 @@ func TestProvider_GenerateReleaseWorkflow_EmptyBody_Good(t *testing.T) {
func TestProvider_DiscoverProject_Good(t *testing.T) {
gin.SetMode(gin.TestMode)
t.Setenv("GITHUB_SHA", "0123456789abcdef")
t.Setenv("GITHUB_REF", "refs/heads/main")
t.Setenv("GITHUB_REPOSITORY", "dappcore/core")
projectDir := t.TempDir()
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "go.mod"), []byte("module example"), 0o644))
@ -975,12 +978,21 @@ build:
assert.Equal(t, http.StatusOK, recorder.Code)
body := recorder.Body.String()
assert.Contains(t, body, `"types":["wails","go","node"]`)
assert.Contains(t, body, `"os":"`)
assert.Contains(t, body, `"arch":"`)
assert.Contains(t, body, `"primary":"wails"`)
assert.Contains(t, body, `"primary_stack":"wails"`)
assert.Contains(t, body, `"suggested_stack":"wails2"`)
assert.Contains(t, body, `"has_frontend":true`)
assert.Contains(t, body, `"has_subtree_npm":false`)
assert.Contains(t, body, `"linux_packages":`)
assert.Contains(t, body, `"ref":"refs/heads/main"`)
assert.Contains(t, body, `"branch":"main"`)
assert.Contains(t, body, `"is_tag":false`)
assert.Contains(t, body, `"sha":"0123456789abcdef"`)
assert.Contains(t, body, `"short_sha":"0123456"`)
assert.Contains(t, body, `"repo":"dappcore/core"`)
assert.Contains(t, body, `"owner":"dappcore"`)
assert.Contains(t, body, `"build_options":"`)
assert.Contains(t, body, `"-obfuscated`)
assert.Contains(t, body, `"options":{"ldflags":["-s","-w"],"nsis":true,"obfuscate":true`)

View file

@ -658,10 +658,17 @@ func prepareWailsFrontend(ctx context.Context, cfg WailsBuildConfig) error {
func resolveWailsFrontendBuild(cfg WailsBuildConfig) (string, string, []string, error) {
frontendDir := resolveFrontendDir(io.Local, cfg.ProjectDir)
if frontendDir == "" {
return "", "", nil, nil
if DenoRequested(cfg.DenoBuild) {
frontendDir = cfg.ProjectDir
if io.Local.IsDir(ax.Join(cfg.ProjectDir, "frontend")) {
frontendDir = ax.Join(cfg.ProjectDir, "frontend")
}
} else {
return "", "", nil, nil
}
}
if hasDenoConfig(io.Local, frontendDir) {
if hasDenoConfig(io.Local, frontendDir) || DenoRequested(cfg.DenoBuild) {
command, args, err := resolveDenoBuildCommand(cfg)
if err != nil {
return "", "", nil, err
@ -686,7 +693,18 @@ func resolveFrontendDir(filesystem io.Medium, projectDir string) string {
return projectDir
}
return resolveSubtreeFrontendDir(filesystem, projectDir)
if nested := resolveSubtreeFrontendDir(filesystem, projectDir); nested != "" {
return nested
}
if DenoRequested("") {
if filesystem.IsDir(frontendDir) {
return frontendDir
}
return projectDir
}
return ""
}
func hasDenoConfig(filesystem io.Medium, dir string) bool {

View file

@ -354,6 +354,64 @@ func TestApple_BuildWailsApp_PreBuildsFrontendAndForcesCGO_Good(t *testing.T) {
assert.Equal(t, "wails3", calls[1].command)
}
func TestApple_BuildWailsApp_UsesDenoWhenEnabledWithoutManifest_Good(t *testing.T) {
projectDir := t.TempDir()
bundlePath := ax.Join(projectDir, "build", "bin", "Core.app")
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "package.json"), []byte(`{}`), 0o644))
t.Setenv("DENO_ENABLE", "true")
oldResolve := appleResolveCommand
oldCombined := appleCombinedOutput
t.Cleanup(func() {
appleResolveCommand = oldResolve
appleCombinedOutput = oldCombined
})
var calls []struct {
dir string
command string
args []string
}
appleResolveCommand = func(name string, fallbackPaths ...string) (string, error) {
return name, nil
}
appleCombinedOutput = func(ctx context.Context, dir string, env []string, command string, args ...string) (string, error) {
calls = append(calls, struct {
dir string
command string
args []string
}{
dir: dir,
command: command,
args: append([]string{}, args...),
})
switch command {
case "deno":
assert.Equal(t, projectDir, dir)
assert.Equal(t, []string{"task", "build"}, args)
case "wails3":
writeDummyAppBundle(t, bundlePath, "Core", "built")
default:
t.Fatalf("unexpected command: %s", command)
}
return "", nil
}
result, err := BuildWailsApp(context.Background(), WailsBuildConfig{
ProjectDir: projectDir,
Name: "Core",
Arch: "arm64",
})
require.NoError(t, err)
assert.Equal(t, bundlePath, result)
require.Len(t, calls, 2)
assert.Equal(t, "deno", calls[0].command)
assert.Equal(t, "wails3", calls[1].command)
}
func TestApple_BuildApple_Good(t *testing.T) {
projectDir := t.TempDir()
outputDir := ax.Join(projectDir, "dist", "apple")

View file

@ -182,7 +182,12 @@ func (b *NodeBuilder) resolvePackageManager(fs io.Medium, projectDir string) (st
//
// command, args, err := b.resolveBuildCommand("npm")
func (b *NodeBuilder) resolveBuildCommand(cfg *build.Config, fs io.Medium, projectDir string) (string, []string, error) {
if b.hasDenoConfig(fs, projectDir) {
configuredDenoBuild := ""
if cfg != nil {
configuredDenoBuild = cfg.DenoBuild
}
if b.hasDenoConfig(fs, projectDir) || build.DenoRequested(configuredDenoBuild) {
return resolveDenoBuildCommand(cfg, b.resolveDenoCli)
}

View file

@ -300,6 +300,85 @@ func TestNode_NodeBuilderBuild_Good_DenoOverrideFromEnvWins(t *testing.T) {
assert.Equal(t, "--env", lines[1])
}
func TestNode_NodeBuilderBuild_Good_DenoEnableWithoutManifest(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test in short mode")
}
binDir := t.TempDir()
setupFakeNodeToolchain(t, binDir)
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("DENO_ENABLE", "true")
projectDir := t.TempDir()
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "package.json"), []byte(`{}`), 0o644))
outputDir := t.TempDir()
logPath := ax.Join(t.TempDir(), "deno-enable.log")
t.Setenv("NODE_BUILD_LOG_FILE", logPath)
builder := NewNodeBuilder()
cfg := &build.Config{
FS: io.Local,
ProjectDir: projectDir,
OutputDir: outputDir,
Name: "denoapp",
}
artifacts, err := builder.Build(context.Background(), cfg, []build.Target{{OS: "linux", Arch: "amd64"}})
require.NoError(t, err)
require.Len(t, artifacts, 1)
content, err := ax.ReadFile(logPath)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(content)), "\n")
require.GreaterOrEqual(t, len(lines), 3)
assert.Equal(t, "deno", lines[0])
assert.Equal(t, "task", lines[1])
assert.Equal(t, "build", lines[2])
}
func TestNode_NodeBuilderBuild_Good_DenoOverrideWithoutManifest(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test in short mode")
}
binDir := t.TempDir()
setupFakeNodeToolchain(t, binDir)
setupFakeNodeCommand(t, binDir, "deno-build")
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
projectDir := t.TempDir()
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "package.json"), []byte(`{}`), 0o644))
outputDir := t.TempDir()
logPath := ax.Join(t.TempDir(), "deno-config.log")
t.Setenv("NODE_BUILD_LOG_FILE", logPath)
builder := NewNodeBuilder()
cfg := &build.Config{
FS: io.Local,
ProjectDir: projectDir,
OutputDir: outputDir,
Name: "denoapp",
DenoBuild: "deno-build --target release",
}
artifacts, err := builder.Build(context.Background(), cfg, []build.Target{{OS: "linux", Arch: "amd64"}})
require.NoError(t, err)
require.Len(t, artifacts, 1)
content, err := ax.ReadFile(logPath)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(content)), "\n")
require.GreaterOrEqual(t, len(lines), 3)
assert.Equal(t, "deno-build", lines[0])
assert.Equal(t, "--target", lines[1])
assert.Equal(t, "release", lines[2])
}
func TestNode_ResolvePackageManager_Good(t *testing.T) {
fs := io.Local
builder := NewNodeBuilder()

View file

@ -248,10 +248,18 @@ func (b *WailsBuilder) resolveFrontendBuild(cfg *build.Config) (string, string,
projectDir := cfg.ProjectDir
frontendDir := b.resolveFrontendDir(fs, projectDir)
if frontendDir == "" {
return "", "", nil, nil
if build.DenoRequested(cfg.DenoBuild) {
if fs.IsDir(ax.Join(projectDir, "frontend")) {
frontendDir = ax.Join(projectDir, "frontend")
} else {
frontendDir = projectDir
}
} else {
return "", "", nil, nil
}
}
if b.hasDenoConfig(fs, frontendDir) {
if b.hasDenoConfig(fs, frontendDir) || build.DenoRequested(cfg.DenoBuild) {
command, args, err := resolveDenoBuildCommand(cfg, b.resolveDenoCli)
if err != nil {
return "", "", nil, err
@ -312,6 +320,13 @@ func (b *WailsBuilder) resolveFrontendDir(fs io.Medium, projectDir string) strin
return nestedFrontendDir
}
if build.DenoRequested("") {
if fs.IsDir(frontendDir) {
return frontendDir
}
return projectDir
}
return ""
}

View file

@ -471,6 +471,17 @@ func TestWails_WailsBuilderResolveFrontendDir_Good(t *testing.T) {
got := builder.resolveFrontendDir(fs, projectDir)
assert.Empty(t, got)
})
t.Run("falls back to frontend directory when DENO_ENABLE is set", func(t *testing.T) {
t.Setenv("DENO_ENABLE", "true")
projectDir := t.TempDir()
frontendDir := ax.Join(projectDir, "frontend")
require.NoError(t, ax.MkdirAll(frontendDir, 0o755))
got := builder.resolveFrontendDir(fs, projectDir)
assert.Equal(t, frontendDir, got)
})
}
func TestWails_WailsBuilderBuildV2_Good(t *testing.T) {
@ -757,6 +768,68 @@ func TestWails_WailsBuilderPreBuild_Good(t *testing.T) {
assert.Equal(t, "build", lines[2])
})
t.Run("prefers deno when DENO_ENABLE is set without a deno manifest", func(t *testing.T) {
binDir := t.TempDir()
setupFakeFrontendCommand(t, binDir, "deno")
setupFakeFrontendCommand(t, binDir, "npm")
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("DENO_ENABLE", "true")
projectDir := setupWailsTestProject(t)
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "package.json"), []byte(`{}`), 0o644))
logPath := ax.Join(t.TempDir(), "frontend-deno-enable.log")
t.Setenv("BUILD_SEQUENCE_FILE", logPath)
builder := NewWailsBuilder()
cfg := &build.Config{
FS: io.Local,
ProjectDir: projectDir,
}
require.NoError(t, builder.PreBuild(context.Background(), cfg))
content, err := ax.ReadFile(logPath)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(content)), "\n")
require.Len(t, lines, 3)
assert.Equal(t, "deno", lines[0])
assert.Equal(t, "task", lines[1])
assert.Equal(t, "build", lines[2])
})
t.Run("uses configured deno build command without a deno manifest", func(t *testing.T) {
binDir := t.TempDir()
setupFakeFrontendCommand(t, binDir, "deno-build")
setupFakeFrontendCommand(t, binDir, "npm")
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
projectDir := setupWailsTestProject(t)
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "package.json"), []byte(`{}`), 0o644))
logPath := ax.Join(t.TempDir(), "frontend-config-deno.log")
t.Setenv("BUILD_SEQUENCE_FILE", logPath)
builder := NewWailsBuilder()
cfg := &build.Config{
FS: io.Local,
ProjectDir: projectDir,
DenoBuild: "deno-build --target release",
}
require.NoError(t, builder.PreBuild(context.Background(), cfg))
content, err := ax.ReadFile(logPath)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(content)), "\n")
require.Len(t, lines, 3)
assert.Equal(t, "deno-build", lines[0])
assert.Equal(t, "--target", lines[1])
assert.Equal(t, "release", lines[2])
})
t.Run("discovers nested package.json in a monorepo", func(t *testing.T) {
binDir := t.TempDir()
setupFakeFrontendCommand(t, binDir, "npm")

View file

@ -1,6 +1,8 @@
package build
import (
"runtime"
"dappco.re/go/core"
"dappco.re/go/core/build/internal/ax"
"dappco.re/go/core/io"
@ -274,6 +276,10 @@ func IsRustProject(fs io.Medium, dir string) bool {
type DiscoveryResult struct {
// Types lists all detected project types in priority order.
Types []ProjectType
// OS is the current host operating system for the discovery run.
OS string
// Arch is the current host architecture for the discovery run.
Arch string
// PrimaryStack is the best stack suggestion based on detected types.
PrimaryStack string
// SuggestedStack is the richer action-oriented stack hint derived from markers.
@ -291,6 +297,22 @@ type DiscoveryResult struct {
// Distro holds the detected Linux distribution version (e.g., "24.04").
// Used by ComputeOptions to inject webkit2_41 tag on Ubuntu 24.04+.
Distro string
// Ref is the Git ref when discovery runs under GitHub metadata.
Ref string
// Branch is the branch name when available from GitHub metadata.
Branch string
// Tag is the tag name when available from GitHub metadata.
Tag string
// IsTag reports whether Ref points at a tag.
IsTag bool
// SHA is the current GitHub commit SHA when available.
SHA string
// ShortSHA is the short GitHub commit SHA when available.
ShortSHA string
// Repo is the GitHub owner/repo string when available.
Repo string
// Owner is the GitHub repository owner when available.
Owner string
}
// DiscoverFull returns a rich discovery result with all markers and metadata.
@ -305,6 +327,8 @@ func DiscoverFull(fs io.Medium, dir string) (*DiscoveryResult, error) {
result := &DiscoveryResult{
Types: types,
OS: runtime.GOOS,
Arch: runtime.GOARCH,
Markers: make(map[string]bool),
}
@ -342,6 +366,16 @@ func DiscoverFull(fs io.Medium, dir string) (*DiscoveryResult, error) {
// Linux distro detection: used for distro-sensitive build flags.
result.Distro = detectDistroVersion(fs)
result.LinuxPackages = ResolveLinuxPackages(result.Types, result.Distro)
if git := DetectGitHubMetadata(); git != nil {
result.Ref = git.Ref
result.Branch = git.Branch
result.Tag = git.Tag
result.IsTag = git.IsTag
result.SHA = git.SHA
result.ShortSHA = git.ShortSHA
result.Repo = git.Repo
result.Owner = git.Owner
}
// Primary stack: first detected type as string, or empty
if len(types) > 0 {

View file

@ -1,6 +1,7 @@
package build
import (
"runtime"
"testing"
"dappco.re/go/core/build/internal/ax"
@ -778,6 +779,8 @@ func TestDiscovery_DiscoverFull_Good(t *testing.T) {
result, err := DiscoverFull(fs, dir)
require.NoError(t, err)
assert.Equal(t, []ProjectType{ProjectTypeGo}, result.Types)
assert.Equal(t, runtime.GOOS, result.OS)
assert.Equal(t, runtime.GOARCH, result.Arch)
assert.Equal(t, "go", result.PrimaryStack)
assert.Equal(t, "go", result.SuggestedStack)
assert.False(t, result.HasFrontend)
@ -786,6 +789,23 @@ func TestDiscovery_DiscoverFull_Good(t *testing.T) {
assert.False(t, result.Markers["wails.json"])
})
t.Run("captures GitHub metadata when available", func(t *testing.T) {
t.Setenv("GITHUB_SHA", "0123456789abcdef")
t.Setenv("GITHUB_REF", "refs/tags/v1.2.3")
t.Setenv("GITHUB_REPOSITORY", "dappcore/core")
dir := setupTestDir(t, "go.mod")
result, err := DiscoverFull(fs, dir)
require.NoError(t, err)
assert.Equal(t, "refs/tags/v1.2.3", result.Ref)
assert.Equal(t, "v1.2.3", result.Tag)
assert.True(t, result.IsTag)
assert.Equal(t, "0123456789abcdef", result.SHA)
assert.Equal(t, "0123456", result.ShortSHA)
assert.Equal(t, "dappcore/core", result.Repo)
assert.Equal(t, "dappcore", result.Owner)
})
t.Run("returns complete result for Go workspace project", func(t *testing.T) {
dir := setupTestDir(t, "go.work")
result, err := DiscoverFull(fs, dir)

View file

@ -1,5 +1,7 @@
package build
import "dappco.re/go/core"
// BuildEnvironment returns a fresh environment slice that includes the
// configured build environment, any derived cache variables, and optional
// builder-specific values.
@ -21,3 +23,27 @@ func BuildEnvironment(cfg *Config, extra ...string) []string {
return env
}
// DenoRequested reports whether the current build should prefer a Deno-backed
// frontend build. It honours the action-style environment overrides first and
// then the persisted/configured command override.
func DenoRequested(configuredBuild string) bool {
if truthyEnv(core.Env("DENO_ENABLE")) {
return true
}
if core.Trim(core.Env("DENO_BUILD")) != "" {
return true
}
return core.Trim(configuredBuild) != ""
}
func truthyEnv(value string) bool {
switch core.Lower(core.Trim(value)) {
case "1", "true", "yes", "on":
return true
default:
return false
}
}

View file

@ -326,7 +326,7 @@ jobs:
python -m pip install mkdocs
- name: Setup Deno
if: hashFiles(format('{0}/**/deno.json', inputs.working-directory), format('{0}/**/deno.jsonc', inputs.working-directory)) != ''
if: env.DENO_ENABLE == 'true' || env.DENO_ENABLE == '1' || env.DENO_ENABLE == 'yes' || env.DENO_ENABLE == 'on' || inputs.deno-build != '' || hashFiles(format('{0}/**/deno.json', inputs.working-directory), format('{0}/**/deno.jsonc', inputs.working-directory)) != ''
uses: denoland/setup-deno@v2
with:
deno-version: v2.x

View file

@ -53,6 +53,8 @@ func TestWorkflow_WriteReleaseWorkflow_Good(t *testing.T) {
assert.Contains(t, content, "python -m pip install mkdocs")
assert.Contains(t, content, "Setup Deno")
assert.Contains(t, content, "denoland/setup-deno@v2")
assert.Contains(t, content, "env.DENO_ENABLE == 'true'")
assert.Contains(t, content, "inputs.deno-build != ''")
assert.Contains(t, content, "build-cache:")
assert.Contains(t, content, "Restore build cache")
assert.Contains(t, content, "actions/cache@v4")

View file

@ -147,6 +147,16 @@ set -euo pipefail
export PATH="${HOME}/go/bin:${HOME}/.deno/bin:${HOME}/.bun/bin:${PATH}"
deno_requested() {
case "${DENO_ENABLE:-}" in
1|true|TRUE|yes|YES|on|ON)
return 0
;;
esac
[ -n "${DENO_BUILD:-}" ]
}
install_node_package_dir() {
local dir="$1"
if [ ! -f "$dir/package.json" ]; then
@ -204,7 +214,7 @@ if ! command -v wails3 >/dev/null 2>&1 && ! command -v wails >/dev/null 2>&1; th
go install github.com/wailsapp/wails/v3/cmd/wails3@latest
fi
if find . -maxdepth 3 \( -name deno.json -o -name deno.jsonc \) -not -path '*/node_modules/*' | grep -q .; then
if deno_requested || find . -maxdepth 3 \( -name deno.json -o -name deno.jsonc \) -not -path '*/node_modules/*' | grep -q .; then
if ! command -v deno >/dev/null 2>&1; then
curl -fsSL https://deno.land/install.sh | sh
export PATH="${HOME}/.deno/bin:${PATH}"

View file

@ -47,6 +47,9 @@ func TestXcodeCloud_GenerateXcodeCloudScripts_Good(t *testing.T) {
require.Len(t, scripts, 3)
assert.Contains(t, scripts[XcodeCloudPostCloneScriptName], "go install github.com/wailsapp/wails/v3/cmd/wails3@latest")
assert.Contains(t, scripts[XcodeCloudPostCloneScriptName], "find . -maxdepth 3 -name package.json")
assert.Contains(t, scripts[XcodeCloudPostCloneScriptName], "deno_requested()")
assert.Contains(t, scripts[XcodeCloudPostCloneScriptName], "DENO_ENABLE")
assert.Contains(t, scripts[XcodeCloudPostCloneScriptName], "DENO_BUILD")
assert.Contains(t, scripts[XcodeCloudPreXcodebuildScriptName], `core build apple --arch "universal" --config ".core/build.yaml" --notarise=false --dmg --appstore --bundle-id "ai.lthn.core" --team-id "ABC123DEF4"`)
assert.Contains(t, scripts[XcodeCloudPostXcodebuildScriptName], `BUNDLE_PATH="dist/apple/Core.app"`)
assert.Contains(t, scripts[XcodeCloudPostXcodebuildScriptName], "codesign --verify --deep --strict")