Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .github/workflows/nuxflare-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ jobs:
with:
fetch-depth: 0

- uses: actions/cache@v4
with:
path: |
playground/.sst
key: ${{ runner.os }}-sst-playground

- name: Install pnpm
uses: pnpm/action-setup@v4
with:
Expand All @@ -48,6 +42,7 @@ jobs:
- name: Build Nuxflare
working-directory: .
run: |
pnpm i
pnpm run build

- name: Install deps
Expand All @@ -66,11 +61,12 @@ jobs:
STAGE="${{ github.event.inputs.stage }}"
else
# Sanitize branch name: lower-case and replace non-alphanumeric chars with dashes
echo "${GITHUB_REF_NAME} and ${GITHUB_REF} and ${GITHUB_EVENT_NAME}"
STAGE=$(echo "${GITHUB_REF_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g')
fi
echo "Deploying to stage: ${STAGE}"
DEPLOY_CMD="deploy --stage ${STAGE}"
fi

echo "Running: ${DEPLOY_CMD}"
node ../dist/index.js ${DEPLOY_CMD}
../dist/index.js ${DEPLOY_CMD}
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"drizzle-kit": "^0.30.0",
"eslint": "^9.16.0",
"nuxthub-ratelimit": "^1.0.4",
"sst": "^3.9.26",
"sst": "^3.9.27",
"vue-tsc": "^2.1.10",
"wrangler": "^3.95.0",
"zod": "^3.24.1"
Expand Down
50 changes: 25 additions & 25 deletions playground/pnpm-lock.yaml

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

11 changes: 5 additions & 6 deletions playground/sst.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/// <reference path="./.sst/platform/config.d.ts" />
import Nuxt from "./.nuxflare/utils/nuxt";
import Nuxt from "./nuxflare/nuxt";

const prodDomain = "test.tanay.codes";
const devDomain = "chat.tanay.codes";
const prodDomain = "chat.tanay.codes";
const devDomain = undefined;

export default $config({
app(input) {
return {
name: "tanay-chat",
removal: input?.stage === "production" ? "retain" : "remove",
protect: ["production"].includes(input?.stage),
home: "cloudflare",
providers: {
cloudflare: true,
Expand All @@ -23,8 +22,8 @@ export default $config({
$app.stage === "production"
? prodDomain || undefined
: devDomain
? `${$app.stage}.${devDomain}`
: undefined;
? `${$app.stage}.${devDomain}`
: undefined;
Nuxt("App", {
dir: ".",
domain,
Expand Down
3 changes: 2 additions & 1 deletion src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async function displayProjectUrls(stage: string) {
}
}
} catch (error) {
console.log("error project uurls", error)
// If there's an error reading the directory, just skip URL display
console.error("Unable to read deployment URLs");
}
Expand Down Expand Up @@ -87,7 +88,7 @@ export async function deploy(options: DeployOptions = {}) {
log.step(`Deploying to stage: ${deployStage}`);

try {
await executeSST(["deploy", "--stage", deployStage], {
await executeSST(["deploy", "--stage", deployStage, "--verbose"], {
stdio: "inherit",
env: {
NITRO_PRESET: "cloudflare-module",
Expand Down
60 changes: 41 additions & 19 deletions src/commands/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,16 @@ export async function init() {
placeholder:
"e.g., dev.example.codes (stages like 'dev' will deploy to 'dev.dev.example.codes')",
}),
setupGithubActions: () =>
p.confirm({
message: "Would you like to setup GitHub Actions?",
githubActions: () =>
p.select({
message: "How would you like to setup GitHub Actions?",
options: [
{ value: "none", label: "Don't setup GitHub Actions" },
{ value: "manual", label: "Manual deployments only (via workflow dispatch)" },
{ value: "prod", label: "Automatic production deployments only (main branch)" },
{ value: "full", label: "Full setup (automatic prod and preview deployments for PRs)" },
],
initialValue: "none",
}),
},
{
Expand Down Expand Up @@ -161,7 +168,7 @@ export async function init() {
{
title: "Setting up GitHub Actions",
task: async () => {
if (!results.setupGithubActions) {
if (results.githubActions === "none") {
return "GitHub Actions setup skipped";
}

Expand All @@ -171,7 +178,10 @@ export async function init() {
// Copy and render the action.yml template
const engine = new Liquid()
const template = engine.parse(await fs.readFile(path.join(initDir, "action.yml.liquid"), "utf8"));
const actionContent = await engine.render(template, { package_manager: results.packageManager });
const actionContent = await engine.render(template, {
package_manager: results.packageManager,
github_action_type: results.githubActions
});

await fs.writeFile(
path.join(githubDir, "nuxflare-deploy.yml"),
Expand Down Expand Up @@ -217,21 +227,33 @@ export async function init() {

log.success(chalk.green("✅ Successfully initialized Nuxflare!"));

const nextSteps = [
`1. Run ${chalk.cyan(
"nuxflare deploy --stage <stage>",
)} to do a preview deployment.`,
`2. Run ${chalk.cyan(
"nuxflare deploy --production",
)} to deploy to production.`,
`3. Run ${chalk.cyan(
"nuxflare dev --stage <stage>",
)} to run a local dev server and connect to remote resources.`,
`4. Run ${chalk.cyan(
"nuxflare copy-env --stage <stage> --file .env",
)} to copy environment variables from a .env file to a stage.`
];

if (results.githubActions !== "none") {
nextSteps.push(
`5. ${chalk.yellow("Important:")} Review your GitHub Actions workflow in ${chalk.cyan(
".github/workflows/nuxflare-deploy.yml"
)} and add your ${chalk.cyan(
"CLOUDFLARE_API_TOKEN"
)} to your repository secrets by going to Settings > Secrets and variables > Actions > New repository secret.`
);
}

p.note(
[
`1. Run ${chalk.cyan(
"nuxflare deploy --stage <stage>",
)} to do a preview deployment.`,
`2. Run ${chalk.cyan(
"nuxflare deploy --production",
)} to deploy to production.`,
`3. Run ${chalk.cyan(
"nuxflare dev --stage <stage>",
)} to run a local dev server and connect to remote resources.`,
`4. Run ${chalk.cyan(
"nuxflare copy-env --stage <stage> --file .env",
)} to copy environment variables from a .env file to a stage.`
].join("\n"),
nextSteps.join("\n"),
"Next steps",
);
} catch (error) {
Expand Down
13 changes: 12 additions & 1 deletion src/init/action.yml.liquid
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
name: "Nuxflare Deploy"

on:
{% if github_action_type == "full" %}
push:
pull_request:
{% elsif github_action_type == "prod" %}
push:
branches:
- main
{% endif %}
workflow_dispatch:
inputs:
stage:
Expand All @@ -15,7 +21,10 @@ concurrency:

jobs:
deploy:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
{% if github_action_type == "full" %}if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
{% elsif github_action_type == "prod" %}if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
{% else %}if: github.event_name == 'workflow_dispatch'
{% endif %}
runs-on: ubuntu-latest
permissions:
contents: read
Expand All @@ -42,6 +51,8 @@ jobs:
{% elsif package_manager == "pnpm" %}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9.15.0

- name: Set up Node.js
uses: actions/setup-node@v4
Expand Down
32 changes: 32 additions & 0 deletions src/init/sst/nuxflare/builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as path from "node:path";
import { Semaphore } from "./semaphore";

const limiter = new Semaphore(
parseInt(process.env.SST_BUILD_CONCURRENCY_SITE || "1"),
);
export async function builder(
name: string,
{
dir,
env,
packageManager,
}: { dir: string; env?: Record<string, any>; packageManager: string },
): Promise<any> {
return new Promise((res) => {
$resolve({ env }).apply(async ({ env }) => {
// acquire semaphore after only resolving environment and we are ready to build
await limiter.acquire();
const cmd = new command.local.Command(`${name}Build`, {
dir: path.resolve(dir),
create: `[ -z "$SKIP_BUILD" ] && NITRO_PRESET=cloudflare-module ${packageManager} run build || ( [ -n "$SKIP_BUILD" ] && echo "Skipping build." )`,
update: `[ -z "$SKIP_BUILD" ] && NITRO_PRESET=cloudflare-module ${packageManager} run build || ( [ -n "$SKIP_BUILD" ] && echo "Skipping build." )`,
triggers: [new Date().toString()],
environment: env,
});
cmd.urn.apply(() => {
limiter.release();
res(cmd);
});
});
});
}
Loading
Loading