|
| 1 | +#!/usr/bin/env -S deno run -A |
| 2 | +import { conditions, defineMatrix, expr, job, step, workflow } from "jsr:@david/gagen@^0.5.0"; |
| 3 | + |
| 4 | +const pluginName = "typescript"; |
| 5 | +const cargoWasmName = `dprint_plugin_${pluginName}`; |
| 6 | + |
| 7 | +const matrix = defineMatrix({ |
| 8 | + config: [ |
| 9 | + { os: "ubuntu-latest", kind: "test_release" }, |
| 10 | + { os: "ubuntu-latest", kind: "test_debug" }, |
| 11 | + ], |
| 12 | +}); |
| 13 | + |
| 14 | +const kind = expr("matrix.config.kind"); |
| 15 | +const os = expr("matrix.config.os"); |
| 16 | + |
| 17 | +const isRelease = kind.equals("test_release"); |
| 18 | +const isDebug = kind.equals("test_debug"); |
| 19 | +const isTag = conditions.isTag(); |
| 20 | +const isReleaseAndTag = isRelease.and(isTag); |
| 21 | + |
| 22 | +const getTagVersion = step({ |
| 23 | + id: "get_tag_version", |
| 24 | + name: "Get tag version", |
| 25 | + if: isReleaseAndTag, |
| 26 | + run: `echo "TAG_VERSION=\${GITHUB_REF/refs\\/tags\\//}" >> "$GITHUB_OUTPUT"`, |
| 27 | + outputs: ["TAG_VERSION"], |
| 28 | +}); |
| 29 | + |
| 30 | +const buildJob = job("build", { |
| 31 | + name: `${kind} ${os}`, |
| 32 | + runsOn: os, |
| 33 | + strategy: { matrix }, |
| 34 | + env: { |
| 35 | + CARGO_INCREMENTAL: 0, |
| 36 | + RUST_BACKTRACE: "full", |
| 37 | + }, |
| 38 | + steps: [ |
| 39 | + { uses: "actions/checkout@v6" }, |
| 40 | + { uses: "dsherret/rust-toolchain-file@v1" }, |
| 41 | + { |
| 42 | + name: "Install wasm32 target", |
| 43 | + if: isRelease, |
| 44 | + run: "rustup target add wasm32-unknown-unknown", |
| 45 | + }, |
| 46 | + { |
| 47 | + uses: "Swatinem/rust-cache@v2", |
| 48 | + with: { "save-if": "${{ github.ref == 'refs/heads/main' }}" }, |
| 49 | + }, |
| 50 | + // deno is needed by the "Lint workflow generation" step (test_debug) |
| 51 | + // and by the "Pre-release" step (test_release on tag). Install it |
| 52 | + // once at the top of every job to keep the matrix steps simple. |
| 53 | + { |
| 54 | + uses: "denoland/setup-deno@v2", |
| 55 | + with: { "deno-version": "v2.x" }, |
| 56 | + }, |
| 57 | + |
| 58 | + { name: "Build debug", if: isDebug, run: "cargo build" }, |
| 59 | + { name: "Lint", if: isDebug, run: "cargo clippy" }, |
| 60 | + { name: "Test debug", if: isDebug, run: "cargo test" }, |
| 61 | + |
| 62 | + { |
| 63 | + name: "Build release", |
| 64 | + if: isRelease, |
| 65 | + run: `cargo build --target wasm32-unknown-unknown --features "wasm" --release`, |
| 66 | + }, |
| 67 | + { name: "Test release", if: isRelease, run: "cargo test --release" }, |
| 68 | + |
| 69 | + // wasm integration test (typescript-specific) |
| 70 | + { |
| 71 | + name: "Wasm integration test - Setup", |
| 72 | + if: isRelease, |
| 73 | + run: |
| 74 | + `echo '{ "plugins": ["./target/wasm32-unknown-unknown/release/${cargoWasmName}.wasm"] }' >> dprint.test.json`, |
| 75 | + }, |
| 76 | + { |
| 77 | + name: "Wasm integration test - Run", |
| 78 | + if: isRelease, |
| 79 | + uses: "dprint/check@v2.2", |
| 80 | + with: { "config-path": "dprint.test.json" }, |
| 81 | + }, |
| 82 | + { |
| 83 | + name: "Wasm integration test - Cleanup", |
| 84 | + if: isRelease, |
| 85 | + run: "rm dprint.test.json", |
| 86 | + }, |
| 87 | + |
| 88 | + getTagVersion, |
| 89 | + |
| 90 | + // NPM |
| 91 | + { |
| 92 | + uses: "actions/setup-node@v6", |
| 93 | + if: isRelease, |
| 94 | + with: { |
| 95 | + "node-version": "24.x", |
| 96 | + "registry-url": "https://registry.npmjs.org", |
| 97 | + }, |
| 98 | + }, |
| 99 | + { |
| 100 | + name: "Setup and test npm deployment", |
| 101 | + if: isRelease, |
| 102 | + run: [ |
| 103 | + "cd deployment/npm", |
| 104 | + "npm install", |
| 105 | + "node setup.js", |
| 106 | + "npm run test", |
| 107 | + ], |
| 108 | + }, |
| 109 | + |
| 110 | + // GITHUB RELEASE |
| 111 | + { |
| 112 | + name: "Pre-release", |
| 113 | + if: isReleaseAndTag, |
| 114 | + run: [ |
| 115 | + "# update config schema to have version", |
| 116 | + `sed -i 's/${pluginName}\\/0.0.0/${pluginName}\\/${getTagVersion.outputs.TAG_VERSION}/' deployment/schema.json`, |
| 117 | + "# rename the wasm file", |
| 118 | + `(cd target/wasm32-unknown-unknown/release/ && mv ${cargoWasmName}.wasm plugin.wasm)`, |
| 119 | + "# create release notes", |
| 120 | + `deno run -A ./scripts/generate_release_notes.ts ${getTagVersion.outputs.TAG_VERSION} > \${{ github.workspace }}-CHANGELOG.txt`, |
| 121 | + ], |
| 122 | + }, |
| 123 | + { |
| 124 | + name: "Release", |
| 125 | + // pinned because softprops/action-gh-release was once compromised |
| 126 | + uses: "softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844", |
| 127 | + if: isReleaseAndTag, |
| 128 | + env: { GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" }, |
| 129 | + with: { |
| 130 | + files: [ |
| 131 | + "target/wasm32-unknown-unknown/release/plugin.wasm", |
| 132 | + "deployment/schema.json", |
| 133 | + ].join("\n"), |
| 134 | + body_path: "${{ github.workspace }}-CHANGELOG.txt", |
| 135 | + draft: false, |
| 136 | + }, |
| 137 | + }, |
| 138 | + { |
| 139 | + name: "Lint workflow generation", |
| 140 | + if: isDebug, |
| 141 | + run: [ |
| 142 | + "./.github/workflows/ci.ts --lint", |
| 143 | + "./.github/workflows/publish.ts --lint", |
| 144 | + "./.github/workflows/release.ts --lint", |
| 145 | + ], |
| 146 | + }, |
| 147 | + ], |
| 148 | +}); |
| 149 | + |
| 150 | +workflow({ |
| 151 | + name: "CI", |
| 152 | + on: { |
| 153 | + pull_request: { branches: ["main"] }, |
| 154 | + push: { branches: ["main"], tags: ["*"] }, |
| 155 | + }, |
| 156 | + jobs: [buildJob], |
| 157 | +}).writeOrLint({ |
| 158 | + filePath: new URL("./ci.generated.yml", import.meta.url), |
| 159 | + header: "# GENERATED BY ./ci.ts -- DO NOT DIRECTLY EDIT", |
| 160 | + pinDeps: true, |
| 161 | +}); |
0 commit comments