diff --git a/.github/scripts/update-smoke-test-template.mjs b/.github/scripts/update-smoke-test-template.mjs new file mode 100644 index 00000000000..986d26a5ae0 --- /dev/null +++ b/.github/scripts/update-smoke-test-template.mjs @@ -0,0 +1,69 @@ +#!/usr/bin/env node +import fs from "node:fs"; +import path from "node:path"; + +const [appDir, targetDir] = process.argv.slice(2); + +if (!appDir || !targetDir) { + console.error("Usage: update-smoke-test-template.sh "); + process.exit(1); +} + +function readJson(filePath) { + return JSON.parse(fs.readFileSync(filePath, "utf8")); +} + +function writeJson(filePath, data) { + fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n"); +} + +const resolvedAppDir = path.resolve(appDir); +const resolvedTargetDir = path.resolve(targetDir); + +fs.rmSync(path.join(resolvedAppDir, ".ember-cli"), { force: true }); + +const pkgPath = path.join(resolvedAppDir, "package.json"); +const pkg = readJson(pkgPath); +pkg.scripts = pkg.scripts || {}; +pkg.scripts.test = "ember test"; + +if (pkg.devDependencies && pkg.devDependencies["@glimmer/component"]) { + pkg.devDependencies["@glimmer/component"] = "workspace:^"; +} else if (pkg.dependencies && pkg.dependencies["@glimmer/component"]) { + pkg.dependencies["@glimmer/component"] = "workspace:^"; +} else { + pkg.devDependencies = pkg.devDependencies || {}; + pkg.devDependencies["@glimmer/component"] = "workspace:^"; +} + +if (pkg.devDependencies && pkg.devDependencies["ember-source"]) { + pkg.devDependencies["ember-source"] = "workspace:*"; +} + +writeJson(pkgPath, pkg); + +const envPath = path.join(resolvedAppDir, "config", "environment.js"); +const source = fs.readFileSync(envPath, "utf8"); +if (!source.includes("_OVERRIDE_DEPRECATION_VERSION")) { + const block = [ + "/* The following enables the infrastructure allow us to test as if deprecations", + " have been turned into errors at a specific version.", + "*/", + "_OVERRIDE_DEPRECATION_VERSION: process.env.OVERRIDE_DEPRECATION_VERSION," + ]; + const updated = source.replace( + /EmberENV:\s*\{\s*\n([ \t]*)/, + (match, indent) => { + const pad = `${indent} `; + const injected = block.map((line) => pad + line).join("\n"); + return match + injected + "\n" + indent; + } + ); + if (updated === source) { + throw new Error("Failed to locate EmberENV block for injection."); + } + fs.writeFileSync(envPath, updated); +} + +fs.rmSync(resolvedTargetDir, { recursive: true, force: true }); +fs.renameSync(resolvedAppDir, resolvedTargetDir); diff --git a/.github/workflows/smoke-test-app-template-updates.yml b/.github/workflows/smoke-test-app-template-updates.yml new file mode 100644 index 00000000000..e49d577fe4c --- /dev/null +++ b/.github/workflows/smoke-test-app-template-updates.yml @@ -0,0 +1,127 @@ +name: Update ember-test-app on ember-cli minor release + +on: + workflow_dispatch: + schedule: + - cron: '0 9 * * 1' # weekly on Monday; job will self-gate to every 10 weeks + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + gate: + name: Gate to every 10 weeks + runs-on: ubuntu-latest + steps: + - name: Check schedule + run: | + set -euo pipefail + week=$(date +%V) + if [ $((10#$week % 10)) -ne 0 ]; then + echo "Skipping: ISO week $week is not a 10-week interval." + exit 0 + fi + + update-app-template: + name: Regenerate smoke-tests app template + runs-on: ubuntu-latest + needs: gate + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Generate ember-test-app using classic blueprint + run: | + set -euo pipefail + tmpdir=$(mktemp -d) + echo "Using temp dir: $tmpdir" + cd "$tmpdir" + pnpm dlx ember-cli@latest new ember-test-app -b @ember-tooling/classic-build-app-blueprint --no-welcome --skip-git --skip-npm --ember-data=false + node "$GITHUB_WORKSPACE/.github/scripts/update-smoke-test-template.mjs" \ + "$tmpdir/ember-test-app" \ + "$GITHUB_WORKSPACE/smoke-tests/app-template" + + - name: Create PR + uses: peter-evans/create-pull-request@v7 + with: + branch: smoke-tests/update-app-template + delete-branch: false + commit-message: "Update ember-test-app template" + title: "Update ember-test-app template (ember-cli latest)" + body: | + Regenerated the smoke-tests app-template using ember-cli latest. + + update-v2-app-template: + name: Regenerate smoke-tests v2 app template + runs-on: ubuntu-latest + needs: gate + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Generate v2-app-template + run: | + set -euo pipefail + tmpdir=$(mktemp -d) + echo "Using temp dir: $tmpdir" + cd "$tmpdir" + pnpm dlx ember-cli@latest new v2-app-template --no-welcome --skip-git --skip-npm --ember-data=false + node "$GITHUB_WORKSPACE/.github/scripts/update-smoke-test-template.mjs" \ + "$tmpdir/v2-app-template" \ + "$GITHUB_WORKSPACE/smoke-tests/v2-app-template" + + - name: Create PR + uses: peter-evans/create-pull-request@v7 + with: + branch: smoke-tests/update-v2-app-template + delete-branch: false + commit-message: "Update v2-app-template" + title: "Update v2-app-template (ember-cli latest)" + body: | + Regenerated the smoke-tests v2-app-template using ember-cli latest. + + report-failure: + name: Report failure + runs-on: ubuntu-latest + needs: + - update-app-template + - update-v2-app-template + if: failure() + steps: + - name: Create issue + uses: actions/github-script@v7 + with: + script: | + const title = "Smoke-test app template update failed"; + const body = [ + "The scheduled smoke-test app template update workflow failed.", + "", + `Run: ${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`, + "", + `Attempt: ${process.env.GITHUB_RUN_ATTEMPT}` + ].join("\\n"); + + const { data: existing } = await github.rest.search.issuesAndPullRequests({ + q: `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open in:title "${title}"` + }); + + if (existing.items.length > 0) { + core.info(`Existing issue found: #${existing.items[0].number}`); + return; + } + + const { data: issue } = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + assignees: ["kategengler"] + }); + + core.info(`Created issue #${issue.number}`);