Unverified Commit 5038932d authored by Sandro Jäckel's avatar Sandro Jäckel Committed by GitHub
Browse files

log4brains: init at 1.1.0 (#436597)

parents 43170e40 4f65f55a
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
From 6a8571098024d1eb69efaae1f1622b3a91417b5f Mon Sep 17 00:00:00 2001
From: tropf <tropf@users.noreply.github.com>
Date: Tue, 26 Aug 2025 15:08:07 +0200
Subject: [PATCH 1/2] replace version check using package.json

In the distributed (nix) version, package.json is not available under
the expected path. As nix can inject the version during build time, this
patch removes the reference to package.json, and injects a marker for
the version to be replaced during the patchPhase.
---
 packages/web/nextjs/next.config.js | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/packages/web/nextjs/next.config.js b/packages/web/nextjs/next.config.js
index 9b2b364..db9d680 100644
--- a/packages/web/nextjs/next.config.js
+++ b/packages/web/nextjs/next.config.js
@@ -5,10 +5,6 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
   enabled: process.env.ANALYZE === "true"
 });
 
-const packageJson = require(`${
-  fs.existsSync(path.join(__dirname, "package.json")) ? "./" : "../"
-}package.json`);
-
 module.exports = withBundleAnalyzer({
   reactStrictMode: true,
   target: "serverless",
@@ -16,7 +12,7 @@ module.exports = withBundleAnalyzer({
   trailingSlash: true,
   serverRuntimeConfig: {
     PROJECT_ROOT: __dirname, // https://github.com/vercel/next.js/issues/8251
-    VERSION: packageJson.version
+    VERSION: "@NIX_LOG4BRAINS_VERSION@",
   },
   webpack(config, { webpack, buildId }) {
     // For cache invalidation purpose (thanks https://github.com/vercel/next.js/discussions/14743)
-- 
2.50.1
+72 −0
Original line number Diff line number Diff line
From 8c7af30fe7377235037c1a385f484f201ecfe063 Mon Sep 17 00:00:00 2001
From: tropf <tropf@users.noreply.github.com>
Date: Tue, 26 Aug 2025 15:15:19 +0200
Subject: [PATCH 2/2] move nextjs build into temporary directory

For the build command, upstream invokes a nextjs-base build inside
node_modules. As this is read-only in nix, the corresponding directory
is copied into a newly-created directory in the temporary directory
(e.g. /tmp), from where the build can successfully run.
---
 packages/web/cli/commands/build.ts | 38 +++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/packages/web/cli/commands/build.ts b/packages/web/cli/commands/build.ts
index b611cd9..213e82f 100644
--- a/packages/web/cli/commands/build.ts
+++ b/packages/web/cli/commands/build.ts
@@ -16,6 +16,36 @@ type Deps = {
   appConsole: AppConsole;
 };
 
+const fs = require('fs');
+const os = require('os');
+
+// Helper: Recursively copy directory
+function copyDirSync(src: any, dest: any) {
+  if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
+  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
+    const srcPath = path.join(src, entry.name);
+    const destPath = path.join(dest, entry.name);
+    if (entry.isDirectory()) {
+      copyDirSync(srcPath, destPath);
+    } else {
+      fs.copyFileSync(srcPath, destPath);
+    }
+  }
+}
+
+// Helper: Recursively set writeable flag
+function setWriteableSync(target: any) {
+  const stat = fs.statSync(target);
+  if (stat.isDirectory()) {
+    fs.chmodSync(target, 0o755);
+    for (const entry of fs.readdirSync(target)) {
+      setWriteableSync(path.join(target, entry));
+    }
+  } else {
+    fs.chmodSync(target, 0o644);
+  }
+}
+
 export async function buildCommand(
   { appConsole }: Deps,
   outPath: string,
@@ -24,7 +54,13 @@ export async function buildCommand(
   process.env.NEXT_TELEMETRY_DISABLED = "1";
   appConsole.println("Building Log4brains...");
 
-  const nextDir = getNextJsDir();
+  const oldNextDir = getNextJsDir();
+
+  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'log4brains-nextjs-'));
+  copyDirSync(oldNextDir, tmpDir);
+  setWriteableSync(tmpDir);
+  const nextDir = tmpDir;
+
   // eslint-disable-next-line global-require,import/no-dynamic-require,@typescript-eslint/no-var-requires
   const nextConfig = require(path.join(nextDir, "next.config.js")) as Record<
     string,
-- 
2.50.1
+118 −0
Original line number Diff line number Diff line
{
  lib,
  stdenv,
  callPackage,
  fetchFromGitHub,
  fetchYarnDeps,
  yarnConfigHook,
  yarnBuildHook,
  yarnInstallHook,
  nodejs,
  yarn,
  moreutils,
  jq,
  makeBinaryWrapper,
  fetchpatch2,
  replaceVars,
}:
stdenv.mkDerivation (finalAttrs: {
  pname = "log4brains";
  version = "1.1.0";

  src = fetchFromGitHub {
    owner = "thomvaill";
    repo = "log4brains";
    tag = "v${finalAttrs.version}";
    hash = "sha256-2EAETbICK3XSjAEoLV0KP2xeOYlw8qgctit+shMp5Qs=";
  };

  yarnOfflineCache = fetchYarnDeps {
    yarnLock = finalAttrs.src + "/yarn.lock";
    hash = "sha256-HHiWlOYwR+PhfpQlUfuTXUiQ+6w1HATGlmflQvqdNlg=";
  };

  # generated from https://codeberg.org/tropf/log4brains
  patches = [
    # This replaces a version check by accessing package.json, which
    # in the nix packaging is not at the expected path
    (replaceVars ./0001-replace-version-check-using-package.json.patch {
      NIX_LOG4BRAINS_VERSION = finalAttrs.version;
    })

    ./0002-move-nextjs-build-into-temporary-directory.patch
  ];

  postPatch = ''
    # Top-level is just a workspace (actual packages reside in packages/
    # subdir), but w/o `version` the yarn hooks refuse to run.
    jq '.version = "${finalAttrs.version}"' < package.json | sponge package.json
  '';

  # = Notes =
  #
  # Not copying the full node_modules yields:
  # Error: Cannot find module 'chalk'
  #
  # The log4brains version in src/ and the default install differ,
  # hence remove the copied version and let installPhase handle it.
  #
  # An alternative approach is to bundle log4brains binary using (tested only in devshell):
  # npx pkg --target 'node*-linux-x64' .
  preInstall = ''
    mkdir -p $out/lib
    cp -aLrt $out/lib node_modules

    # will get installed by the installPhase, so avoid conflicts
    rm -r $out/lib/node_modules/log4brains

    # the desired final package is inside of a subdir; switch there
    pushd packages/global-cli
  '';

  # w/o yarn it just generated cryptic errors ENOENT
  #
  # There are some builds at runtime (marked as "hack" in the src),
  # hence we need node_modules set
  postInstall = ''
    popd

    wrapProgram $out/bin/log4brains \
      --suffix PATH : ${
        lib.makeBinPath [
          nodejs
          yarn
        ]
      } \
      --set NODE_PATH $out/lib/node_modules
  '';

  nativeBuildInputs = [
    yarnConfigHook
    yarnBuildHook
    yarnInstallHook
    # Needed for executing package.json scripts
    nodejs

    makeBinaryWrapper

    moreutils # sponge
    jq
  ];

  passthru.tests.basic-scenario = callPackage ./test-basic-scenario.nix {
    log4brains = finalAttrs.finalPackage;
  };

  meta = {
    description = "Architecture Decision Records (ADR) management and publication tool";
    longDescription = ''
      Log4brains is a docs-as-code knowledge base for your development and infrastructure projects.
      It enables you to log Architecture Decision Records (ADR) right from your IDE and to publish them automatically as a static website.
    '';
    homepage = "https://github.com/thomvaill/log4brains";
    license = lib.licenses.asl20;
    mainProgram = "log4brains";
    maintainers = with lib.maintainers; [ tropf ];
    platforms = lib.platforms.all;
  };
})
+33 −0
Original line number Diff line number Diff line
{
  testers,
  log4brains,
}:
testers.runCommand {
  name = "log4brains-test-basic-scenario";
  # the build runs for *quite* a while
  meta.timeout = 90;
  nativeBuildInputs = [ log4brains ];

  script = ''
    log4brains | grep 'Log4brains CLI'

    mkdir project && cd project

    log4brains init --defaults
    test -f docs/adr/index.md

    log4brains adr new --quiet 'Test ADR'
    grep -r 'Test ADR' docs/adr/ >/dev/null

    # Note: Preview is difficult to check (and hence not checked):
    # (1) It requires some timeout for the page to become ready.
    # (2) The signal & process handling is screwed; on kill the
    #     process serving in the background stays alive.

    log4brains build --out www
    test -f www/index.html
    grep -r 'Test ADR' www >/dev/null

    touch $out
  '';
}