Skip to content

Commit

Permalink
Add project.bri to build Brioche with Brioche (#157)
Browse files Browse the repository at this point in the history
* Add `project.bri` to build Brioche with Brioche

* Update `project.bri` to validate JS runtime and SQLx files

* Add comments to `project.bri`

* Update GH Actions workflow to build and upload Brioche with Brioche

* Update `.gitattributes`

* Fix artifact path for packed Brioche build

* Remove blank line from `.gitattributes`
  • Loading branch information
kylewlacy authored Jan 6, 2025
1 parent 5c7831a commit 4229563
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
*.bri linguist-language=TypeScript
brioche.lock linguist-generated
crates/brioche/runtime/dist/** linguist-generated
**/.sqlx/query-*.json linguist-generated
43 changes: 41 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,43 @@ jobs:
name: brioche-${{ matrix.platform.name }}
if-no-files-found: error
path: artifacts/brioche
build-packed:
name: Build packed artifacts
if: github.event_name == 'push'
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Brioche
uses: brioche-dev/setup-brioche@v1
- name: Build Brioche
run: brioche build -o "brioche-packed-$PLATFORM"
env:
PLATFORM: x86_64-linux
- name: Prepare artifact
run: |
mkdir -p "artifacts/brioche-packed/$PLATFORM"
tar -czf "artifacts/brioche-packed/$PLATFORM/brioche-packed-$PLATFORM.tar.gz" "brioche-packed-$PLATFORM"
if command -v sha256sum &> /dev/null; then
find artifacts/ -type f | xargs sha256sum
fi
if command -v tree &> /dev/null; then
tree --du -h artifacts/brioche-packed
fi
env:
PLATFORM: x86_64-linux
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: brioche-packed-x86_64-linux
if-no-files-found: error
path: artifacts/brioche-packed
push:
name: Push artifacts
if: github.event_name == 'push' && github.repository == 'brioche-dev/brioche'
needs: [check, test, build]
needs: [check, test, build, build-packed]
runs-on: ubuntu-24.04
steps:
- name: Download artifacts (x86_64-linux)
Expand All @@ -169,11 +202,17 @@ jobs:
with:
name: brioche-aarch64-macos
path: artifacts/brioche
- name: Download artifacts (x86_64-linux packed)
uses: actions/download-artifact@v4
with:
name: brioche-packed-x86_64-linux
path: artifacts/brioche-packed
# Upload the Brioche build for the current branch
- name: Prepare upload
run: |
mkdir -p artifacts/uploads/branch
mkdir -p artifacts/uploads/branch/brioche-packed
cp -r artifacts/brioche/* artifacts/uploads/branch/
cp -r artifacts/brioche-packed/* artifacts/uploads/branch/brioche-packed/
if command -v tree &> /dev/null; then
tree --du -h artifacts/uploads/branch
Expand Down
16 changes: 16 additions & 0 deletions brioche.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

162 changes: 162 additions & 0 deletions project.bri
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import * as std from "std";
import rust, { cargoBuild, vendorCrate } from "rust";
import curl from "curl";
import caCertificates from "ca_certificates";
import nodejs, { npmInstall } from "nodejs";
import { gitCheckout } from "git";
import openssl from "openssl";

/**
* Returns a recipe to build Brioche itself.
*/
export default function (): std.Recipe<std.Directory> {
let source = Brioche.glob(
// Cargo project files
"crates/**/*.rs",
"**/Cargo.toml",
"Cargo.lock",

// SQLx files
"crates/brioche-core/.sqlx",
"crates/brioche-core/migrations",

// JS runtime files
"crates/brioche-core/runtime/package.json",
"crates/brioche-core/runtime/package-lock.json",
"crates/brioche-core/runtime/tsconfig.json",
"crates/brioche-core/runtime/build.ts",
"crates/brioche-core/runtime/src",
"crates/brioche-core/runtime/tslib",
"crates/brioche-core/runtime/dist",

// Makefiles for miscellaneous tasks
"**/Makefile",
);
source = validateRuntime(source);
source = validateSqlxMetadata(source);

return cargoBuild({
source,
path: "crates/brioche",
runnable: "bin/brioche",

// Network access is used for vendoring libraries (e.g. V8)
unsafe: {
networking: true,
},
dependencies: [curl(), caCertificates()],
});
}

/**
* Use the SQLx CLI to validate that the prepared SQLx metadata is up-to-date
* with all of the database migrations and queries.
*/
function validateSqlxMetadata(
source: std.Recipe<std.Directory>,
): std.Recipe<std.Directory> {
const vendoredSource = vendorCrate({ source });

// Run `make check-db-schema` to ensure the database schema is up-to-date.
return validate({
recipe: source,
validation: std.runBash`
make check-db-schema
`
.workDir(vendoredSource)
.dependencies(
rust(),
sqlxCli(),
std.toolchain(),
curl(),
caCertificates(),
)
.unsafe({ networking: true })
.outputScaffold(std.directory())
.toDirectory(),
});
}

/**
* Validate that the source of the JS runtime project under
* `crates/brioche-core/runtime` matches the output `dist/` directory.
* This ensures the source and build don't go out of sync.
*/
function validateRuntime(
source: std.Recipe<std.Directory>,
): std.Recipe<std.Directory> {
return validate({
recipe: source,
validation: std.runBash`
if ! diff -r "$current_runtime" "$runtime"; then
echo "Error: 'crates/brioche-core/runtime/dist' does not match!" >&2
exit 1
fi
`
.env({
current_runtime: source.get("crates/brioche-core/runtime/dist"),
runtime: runtime(),
})
.outputScaffold(std.directory())
.toDirectory(),
});
}

/**
* Build the JS runtime project under `crates/brioche-core/runtime`. Returns
* the built directory, which is expected to be stored under the directory
* `crates/brioche-core/runtime/dist`.
*/
export function runtime(): std.Recipe<std.Directory> {
const source = Brioche.glob(
"crates/brioche-core/runtime/package.json",
"crates/brioche-core/runtime/package-lock.json",
"crates/brioche-core/runtime/tsconfig.json",
"crates/brioche-core/runtime/build.ts",
"crates/brioche-core/runtime/src",
"crates/brioche-core/runtime/tslib",
).peel(3);
const npmPackage = npmInstall({ source });

return std.runBash`
npm run build
mv dist "$BRIOCHE_OUTPUT"
`
.dependencies(nodejs())
.workDir(npmPackage)
.toDirectory();
}

export function sqlxCli() {
const source = gitCheckout(
Brioche.gitRef({
repository: "https://github.com/launchbadge/sqlx.git",
ref: "v0.7.4",
}),
);

return cargoBuild({
source,
path: "sqlx-cli",
dependencies: [openssl()],
runnable: "bin/sqlx",
});
}

interface ValidateOptions {
recipe: std.Recipe<std.Directory>;
validation: std.Recipe<std.Directory>;
}

/**
* Add a validation to a recipe. When the recipe is baked, the validation
* will also be baked, and will fail if the validation fails. The validation
* should be a process recipe that returns an empty directory on success.
*
* Internally, this just merges the validation and recipe results together.
* This results in a new recipe that depends on both the original recipe
* and the validation.
*/
function validate(options: ValidateOptions): std.Recipe<std.Directory> {
return std.merge(options.validation, options.recipe);
}

0 comments on commit 4229563

Please sign in to comment.