From 2ee597191ab48a5e0592df4b6881bbe3019ddb5b Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 14:08:25 +0300 Subject: [PATCH 1/9] Issue #424 - add build info string literals --- .github/workflows/c-cpp.yml | 8 +++--- .github/workflows/release.yml | 12 ++++---- .gitignore | 3 ++ manpage | 34 ++++++++++++++++++++++ specs/docs/alu.md | 11 ++++++++ specs/docs/onepage.md | 6 ++++ specs/src/ALUUnitTest.vcxproj | 1 + specs/src/ProcessingTest.vcxproj | 1 + specs/src/TokenTest.vcxproj | 1 + specs/src/cacheTest.vcxproj | 1 + specs/src/cli/tokens.cc | 2 +- specs/src/generate_build_info.py | 48 ++++++++++++++++++++++++++++++++ specs/src/itemTest.vcxproj | 1 + specs/src/processing/Config.cc | 33 ++++++++++++++++++++++ specs/src/processing/Config.h | 2 ++ specs/src/readWriteTest.vcxproj | 1 + specs/src/setup.py | 15 ++++++++-- specs/src/specs.vcxproj | 1 + specs/src/timeTest.vcxproj | 1 + 19 files changed, 170 insertions(+), 12 deletions(-) create mode 100644 specs/src/generate_build_info.py diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 95a5cc02..7814de58 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -39,7 +39,7 @@ jobs: run: make all - name: Test specs executable - run: specs/exe/specs "@version" WRITE "@platform" + run: specs/exe/specs "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: make check working-directory: specs/src @@ -67,7 +67,7 @@ jobs: run: make all - name: Test specs executable - run: specs/exe/specs "@version" WRITE "@platform" + run: specs/exe/specs "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: make check working-directory: specs/src @@ -91,7 +91,7 @@ jobs: run: msbuild specs/specs.sln /p:Configuration=Release /p:Platform=x64 - name: Test specs executable - run: specs/bin/Release/specs.exe "@version" WRITE "@platform" + run: specs/bin/Release/specs.exe "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" build-windows-python: runs-on: windows-latest @@ -113,4 +113,4 @@ jobs: run: msbuild specs/specs.sln /p:Configuration=Release /p:Platform=x64 /p:EnablePython=true - name: Test specs executable - run: specs/bin/Release/specs.exe "@version" WRITE "@platform" + run: specs/bin/Release/specs.exe "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a161edcb..7a9eebf9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,8 @@ on: env: SPECS_VERSION: ${{ github.event.release.tag_name }} SPECS_BRANCH: ${{ github.event.release.target_commitish }} + SPECS_BUILD_SOURCE: github + SPECS_BUILD_NUMBER: ${{ github.run_number }} jobs: build-linux: @@ -46,7 +48,7 @@ jobs: run: make some - name: Verify binary - run: specs/exe/specs "@version" WRITE "@platform" + run: specs/exe/specs "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: Prepare manpage run: | @@ -121,7 +123,7 @@ jobs: run: make some - name: Verify binary - run: specs/exe/specs "@version" WRITE "@platform" + run: specs/exe/specs "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: Prepare manpage run: | @@ -205,7 +207,7 @@ jobs: run: msbuild specs/specs.sln /p:Configuration=Release /p:Platform=x64 /p:GitTag=${{ steps.version.outputs.display }} - name: Verify binary - run: specs\bin\Release\specs.exe "@version" WRITE "@platform" + run: specs\bin\Release\specs.exe "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: Prepare standalone executable shell: bash @@ -291,7 +293,7 @@ jobs: run: msbuild specs/specs.sln /p:Configuration=Release /p:Platform=x64 /p:GitTag=${{ steps.version.outputs.display }} /p:EnablePython=true - name: Verify binary - run: specs\bin\Release\specs.exe "@version" WRITE "@platform" + run: specs\bin\Release\specs.exe "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: Prepare standalone executable shell: bash @@ -366,7 +368,7 @@ jobs: run: make some - name: Verify binary - run: specs/exe/specs "@version" WRITE "@platform" + run: specs/exe/specs "Version:" 1 "@version" WRITE "Platform:" 1 "@platform" WRITE "Build info:" 1 "@build-info" - name: Prepare manpage run: | diff --git a/.gitignore b/.gitignore index fa0913d7..3ae0f584 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ specs/src/Release/ # GDB-related specs/src/.gdbinit specs/src/gdb/__pycache__ + +# Generated build info +specs/src/utils/build_info.h diff --git a/manpage b/manpage index 3d97907a..1cc582b2 100644 --- a/manpage +++ b/manpage @@ -2293,6 +2293,40 @@ depending on whether support for python function is available. contains a string describing this build. For example: .p POSIX (darwin) system using the g++ compiler and Python 3.9.6 - release variation +.IP "build-commit" 3 +contains the git commit hash (short form) of the build. For example: +.p + b74fcb1 +.IP "build-branch" 3 +contains the git branch name of the build. May be empty if not available. For example: +.p + dev-1.0.0 +.IP "build-time" 3 +contains the UTC timestamp of when the build was created. Format is +.B yyyy-MM-ddTHH:mm:ss. +For example: +.p + 2026-06-08T08:22:52 +.IP "build-source" 3 +contains either +.B local +or +.B github +depending on where the build was created. +.IP "build-number" 3 +contains the build number from GitHub Actions (github.run_number). Empty for local builds. +.IP "build-info" 3 +contains a composite string with all build information. For example: +.p + commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (local) +.p +or +.p + commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (github) - build 199 +.p +or if the branch is not available: +.p + commit b74fcb1 built on 2026-06-08T08:22:52 (local) .SH EXAMPLES `ls -l` yields this: diff --git a/specs/docs/alu.md b/specs/docs/alu.md index 222a9858..25ce2eb4 100644 --- a/specs/docs/alu.md +++ b/specs/docs/alu.md @@ -117,6 +117,17 @@ POSIX (darwin) system using the g++ compiler and Python 3.9.6 - release variatio ``` Others are `@cols`, which contains the number of columns in the terminal screen, and `@rows`, which contains the number of rows on that same screen. +Build information is also available via the following labels: +- `@build-commit` — the git commit hash (short form) of the build +- `@build-branch` — the git branch name (may be empty) +- `@build-time` — the UTC timestamp when the build was created (format: `yyyy-MM-ddTHH:mm:ss`) +- `@build-source` — either `local` or `github` +- `@build-number` — the GitHub Actions build number (empty for local builds) +- `@build-info` — a composite string with all build information, e.g.: + ``` + commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (local) + ``` + Additionally, the `@@` string stands for the entire input record. When rolling context is in effect (see [Streams and Records](streams.md#rolling-context)), `@@` always refers to the original input record. The `@!` string refers to the current record as affected by `CONTEXT`, which is the same as `@@` when no `CONTEXT` is active. The `@-n` and `@+n` syntax is an alternative to using that is effective within expressions. Note that reading beyond the input with `@+n` or `@-n` does not cause processing to stop, even if a `READSTOP` token is present in the specification. The following three specifications are equivalent: ``` diff --git a/specs/docs/onepage.md b/specs/docs/onepage.md index 0ee0ae13..3ac22897 100644 --- a/specs/docs/onepage.md +++ b/specs/docs/onepage.md @@ -200,6 +200,12 @@ There are some pre-configured labels that do not need to be explicitly defined: * platform - contains a string with the OS type, the compiler and the variation used to build *specs* * cols - contains the number of screen columns - useful for composed output placement. * rows - contains the number of screen rows. +* build-commit - contains the git commit hash (short form) of the build +* build-branch - contains the git branch name (may be empty) +* build-time - contains the UTC timestamp when the build was created (format: `yyyy-MM-ddTHH:mm:ss`) +* build-source - contains either `local` or `github` +* build-number - contains the GitHub Actions build number (empty for local builds) +* build-info - contains a composite string with all build information Examples ======== diff --git a/specs/src/ALUUnitTest.vcxproj b/specs/src/ALUUnitTest.vcxproj index a8248061..80cfad0f 100644 --- a/specs/src/ALUUnitTest.vcxproj +++ b/specs/src/ALUUnitTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/ProcessingTest.vcxproj b/specs/src/ProcessingTest.vcxproj index 3009b731..05a11b91 100644 --- a/specs/src/ProcessingTest.vcxproj +++ b/specs/src/ProcessingTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/TokenTest.vcxproj b/specs/src/TokenTest.vcxproj index 7fa3e9c3..e60ce18a 100644 --- a/specs/src/TokenTest.vcxproj +++ b/specs/src/TokenTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/cacheTest.vcxproj b/specs/src/cacheTest.vcxproj index 4709e89f..a57f66ca 100644 --- a/specs/src/cacheTest.vcxproj +++ b/specs/src/cacheTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/cli/tokens.cc b/specs/src/cli/tokens.cc index c627e1a6..405b951f 100644 --- a/specs/src/cli/tokens.cc +++ b/specs/src/cli/tokens.cc @@ -493,7 +493,7 @@ void parseSingleToken(std::vector *pVec, std::string arg, int argidx) /* Check for a configuration literal */ std::string key = arg.substr(1); - if ((arg[0]=='@') && (arg.length() > 1) && (configSpecLiteralExists(key))) { + if ((arg[0]=='@') && (arg.length() > 1) && (configSpecLiteralDefined(key))) { std::string literal = configSpecLiteralGet(key); pVec->insert(pVec->end(), Token(TokenListType__LITERAL, nullptr /* range */, diff --git a/specs/src/generate_build_info.py b/specs/src/generate_build_info.py new file mode 100644 index 00000000..ffdd61dd --- /dev/null +++ b/specs/src/generate_build_info.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Generate build_info.h with current build information.""" + +import datetime +import os +import subprocess + +# Get commit hash +build_commit = "" +try: + build_commit = subprocess.check_output( + ['git', 'rev-parse', '--short', 'HEAD'], + stderr=subprocess.DEVNULL + ).decode().strip() +except Exception: + pass + +# Get branch name +build_branch = "" +try: + build_branch = subprocess.check_output( + ['git', 'branch', '--show-current'], + stderr=subprocess.DEVNULL + ).decode().strip() +except Exception: + pass + +# Fall back to the SPECS_BRANCH environment variable (set by release.yml) +# since `git branch --show-current` is empty on a detached HEAD / tag checkout. +if build_branch == "": + build_branch = os.environ.get("SPECS_BRANCH", "") + +# Get UTC build time +build_time = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S") + +# Get build source and number from environment +build_source = os.environ.get("SPECS_BUILD_SOURCE", "local") +build_number = os.environ.get("SPECS_BUILD_NUMBER", "") + +# Write the header file +with open("utils/build_info.h", "w") as f: + f.write('#define SPECS_BUILD_COMMIT "{}"\n'.format(build_commit)) + f.write('#define SPECS_BUILD_BRANCH "{}"\n'.format(build_branch)) + f.write('#define SPECS_BUILD_TIME "{}"\n'.format(build_time)) + f.write('#define SPECS_BUILD_SOURCE "{}"\n'.format(build_source)) + f.write('#define SPECS_BUILD_NUMBER "{}"\n'.format(build_number)) + +print("Generated utils/build_info.h") diff --git a/specs/src/itemTest.vcxproj b/specs/src/itemTest.vcxproj index e6234ea9..228b4336 100644 --- a/specs/src/itemTest.vcxproj +++ b/specs/src/itemTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/processing/Config.cc b/specs/src/processing/Config.cc index 8a9e5a76..87e8f4e3 100644 --- a/specs/src/processing/Config.cc +++ b/specs/src/processing/Config.cc @@ -19,6 +19,7 @@ #include "utils/PythonIntf.h" #include "utils/aluRegex.h" #include "utils/aluFunctions.h" +#include "utils/build_info.h" #include "Config.h" #define STRINGIFY2(x) #x @@ -212,6 +213,32 @@ void readConfigurationFile() if (0==ExternalLiterals.count("rows")) { ExternalLiterals["rows"] = getTerminalRowsAndColumns(true); } + + // Build information + ExternalLiterals["build-commit"] = dequote(STRINGIFY(SPECS_BUILD_COMMIT)); + ExternalLiterals["build-branch"] = dequote(STRINGIFY(SPECS_BUILD_BRANCH)); + ExternalLiterals["build-time"] = dequote(STRINGIFY(SPECS_BUILD_TIME)); + ExternalLiterals["build-source"] = dequote(STRINGIFY(SPECS_BUILD_SOURCE)); + ExternalLiterals["build-number"] = dequote(STRINGIFY(SPECS_BUILD_NUMBER)); + + // Compose build-info + std::string build_info = "Built "; + if (ExternalLiterals["build-source"] == "github") { + build_info += "on github"; + if (!ExternalLiterals["build-number"].empty()) { + build_info += " (build " + ExternalLiterals["build-number"] + ")"; + } + } else { + build_info += "locally"; + } + if (!ExternalLiterals["build-commit"].empty()) { + build_info += " from commit " + ExternalLiterals["build-commit"]; + if (!ExternalLiterals["build-branch"].empty()) { + build_info += " on branch " + ExternalLiterals["build-branch"]; + } + } + build_info += " at " + ExternalLiterals["build-time"]; + ExternalLiterals["build-info"] = build_info; } bool configSpecLiteralExists(std::string& key) @@ -220,6 +247,12 @@ bool configSpecLiteralExists(std::string& key) return it != ExternalLiterals.end() && !it->second.empty(); } +bool configSpecLiteralDefined(std::string& key) +{ + auto it = ExternalLiterals.find(key); + return it != ExternalLiterals.end(); +} + std::string& configSpecLiteralGet(std::string& key) { return ExternalLiterals[key]; diff --git a/specs/src/processing/Config.h b/specs/src/processing/Config.h index 34f7afb2..85da620e 100644 --- a/specs/src/processing/Config.h +++ b/specs/src/processing/Config.h @@ -65,6 +65,8 @@ void readConfigurationFile(); bool configSpecLiteralExists(std::string& key); +bool configSpecLiteralDefined(std::string& key); + std::string& configSpecLiteralGet(std::string& key); std::string& configSpecLiteralGetWithDefault(std::string& key, std::string& _default); diff --git a/specs/src/readWriteTest.vcxproj b/specs/src/readWriteTest.vcxproj index e13b8714..13e3c4c5 100644 --- a/specs/src/readWriteTest.vcxproj +++ b/specs/src/readWriteTest.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/setup.py b/specs/src/setup.py index 3cac026f..83237925 100644 --- a/specs/src/setup.py +++ b/specs/src/setup.py @@ -186,10 +186,12 @@ def python_search(arg): LIBOBJS = $(CCSRC:.cc=.{}) TESTOBJS = $(TESTSRC:.cc=.{}) +BUILD_INFO = utils/build_info.h + #default goal -some: directories $(EXE_DIR)/specs $(EXE_DIR)/specs-autocomplete +some: directories $(BUILD_INFO) $(EXE_DIR)/specs $(EXE_DIR)/specs-autocomplete -all: directories $(TEST_EXES) +all: directories $(BUILD_INFO) $(TEST_EXES) %.obj : %.cc $(CXX) $(CPPFLAGS) /Fo$@ /c $< @@ -212,6 +214,11 @@ def python_search(arg): body2 = \ """ +.PHONY: utils/build_info.h + +utils/build_info.h: + @python3 generate_build_info.py + run_tests: $(TEST_EXES) $(EXE_DIR)/TokenTest $(EXE_DIR)/ProcessingTest @@ -762,6 +769,10 @@ def python_search(arg): "python3 $(TESTS_DIR)/recfm_tests.py\n\tpython3 $(TESTS_DIR)/pytest.py" ) +# Generate build_info.h (so it exists before the first compile; it is +# regenerated on every build by the utils/build_info.h Makefile target) +subprocess.call([sys.executable, "generate_build_info.py"]) + with open("Makefile", "w") as makefile: makefile.write("CXX={}\n".format(cxx)) makefile.write("LINKER={}\n".format("link.exe" if (compiler=="VS") else cxx)) diff --git a/specs/src/specs.vcxproj b/specs/src/specs.vcxproj index 33a40d06..a8145323 100644 --- a/specs/src/specs.vcxproj +++ b/specs/src/specs.vcxproj @@ -31,6 +31,7 @@ true + diff --git a/specs/src/timeTest.vcxproj b/specs/src/timeTest.vcxproj index 3c8f77f2..c24bd88b 100644 --- a/specs/src/timeTest.vcxproj +++ b/specs/src/timeTest.vcxproj @@ -31,6 +31,7 @@ true + From 3b09b45e406bfce036a52ed9c451cabce57d5cd8 Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 14:13:24 +0300 Subject: [PATCH 2/9] Issue #424 - set PR builds on github to show github, not local --- .github/workflows/c-cpp.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 7814de58..005db0c0 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -8,6 +8,7 @@ on: env: SPECS_BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} + SPECS_BUILD_SOURCE: github jobs: build-linux: From c3a2db894fa55a5c86893c54e83a5326d390a82d Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 14:17:35 +0300 Subject: [PATCH 3/9] Issue #424 - Add the build_info.targets file --- specs/src/build_info.targets | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 specs/src/build_info.targets diff --git a/specs/src/build_info.targets b/specs/src/build_info.targets new file mode 100644 index 00000000..4056702e --- /dev/null +++ b/specs/src/build_info.targets @@ -0,0 +1,42 @@ + + + + + + + $([System.DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss")) + local + $(SPECS_BUILD_SOURCE) + $(SPECS_BUILD_NUMBER) + + + + + + + + + + + + + + + $(BuildCommit.Trim()) + $(BuildBranch.Trim()) + + + + + + + + + + + + + + + + From 857f7025cfc2b6451a5ef673137049af59915e56 Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 14:43:39 +0300 Subject: [PATCH 4/9] Issue #424 - a more verbose generation of build_info.h --- specs/src/generate_build_info.py | 60 +++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/specs/src/generate_build_info.py b/specs/src/generate_build_info.py index ffdd61dd..567d396e 100644 --- a/specs/src/generate_build_info.py +++ b/specs/src/generate_build_info.py @@ -4,38 +4,66 @@ import datetime import os import subprocess +import sys + + +def report_success(name, value): + print('Setting {} to "{}"'.format(name, value)) + + +def report_failure(name, exc): + sys.stderr.write("Failed to determine {}: {}\n".format(name, repr(exc))) + # If the failure came from a subprocess, surface the command's stderr too, + # since that usually explains *why* (e.g. git's "dubious ownership" error). + output = getattr(exc, "output", None) + if output: + if isinstance(output, bytes): + output = output.decode(errors="replace") + sys.stderr.write(" stdout: {}\n".format(output.strip())) + stderr = getattr(exc, "stderr", None) + if stderr: + if isinstance(stderr, bytes): + stderr = stderr.decode(errors="replace") + sys.stderr.write(" stderr: {}\n".format(stderr.strip())) + + +def run_git(name, args): + """Run a git command, capturing stderr so failures can be reported.""" + try: + value = subprocess.check_output( + ['git'] + args, + stderr=subprocess.PIPE + ).decode().strip() + if value: + report_success(name, value) + return value + except Exception as exc: + report_failure(name, exc) + return "" + # Get commit hash -build_commit = "" -try: - build_commit = subprocess.check_output( - ['git', 'rev-parse', '--short', 'HEAD'], - stderr=subprocess.DEVNULL - ).decode().strip() -except Exception: - pass +build_commit = run_git("SPECS_BUILD_COMMIT", ['rev-parse', '--short', 'HEAD']) # Get branch name -build_branch = "" -try: - build_branch = subprocess.check_output( - ['git', 'branch', '--show-current'], - stderr=subprocess.DEVNULL - ).decode().strip() -except Exception: - pass +build_branch = run_git("SPECS_BUILD_BRANCH", ['branch', '--show-current']) # Fall back to the SPECS_BRANCH environment variable (set by release.yml) # since `git branch --show-current` is empty on a detached HEAD / tag checkout. if build_branch == "": build_branch = os.environ.get("SPECS_BRANCH", "") + if build_branch: + report_success("SPECS_BUILD_BRANCH (from SPECS_BRANCH env)", build_branch) # Get UTC build time build_time = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%S") +report_success("SPECS_BUILD_TIME", build_time) # Get build source and number from environment build_source = os.environ.get("SPECS_BUILD_SOURCE", "local") +report_success("SPECS_BUILD_SOURCE", build_source) build_number = os.environ.get("SPECS_BUILD_NUMBER", "") +report_success("SPECS_BUILD_NUMBER", build_number) # Write the header file with open("utils/build_info.h", "w") as f: From b3c06fb2b98c1930855e88c2f2735a4158fb5fbd Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 15:00:58 +0300 Subject: [PATCH 5/9] Issue #424 - add git to release building to get commit number and branch --- .github/workflows/release.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7a9eebf9..ef2821c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,11 @@ jobs: container: image: ubuntu:22.04 steps: + - name: Install git (so checkout creates a real repository in the container) + run: | + DEBIAN_FRONTEND=noninteractive apt-get update + DEBIAN_FRONTEND=noninteractive apt-get install -y git + - uses: actions/checkout@v4 with: fetch-depth: 0 @@ -339,6 +344,16 @@ jobs: runs-on: ${{ matrix.runner }} container: ${{ matrix.container || '' }} steps: + - name: Install git (so checkout creates a real repository in the container) + run: | + if [ "$(id -u)" -eq 0 ]; then + APT="apt-get" + else + APT="sudo apt-get" + fi + DEBIAN_FRONTEND=noninteractive $APT update + DEBIAN_FRONTEND=noninteractive $APT install -y git + - uses: actions/checkout@v4 with: fetch-depth: 0 From 6a431b8d538456a386fc55df83eaf01917854117 Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 15:10:54 +0300 Subject: [PATCH 6/9] Issue #424 - add safe.directory to linux in release.yml This avoids the dubious ownership error --- .github/workflows/release.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef2821c9..f8697d46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,6 +30,9 @@ jobs: with: fetch-depth: 0 + - name: Mark workspace as safe for git + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Dump event release payload env: EVENT: ${{ toJSON(github.event.release) }} @@ -358,6 +361,9 @@ jobs: with: fetch-depth: 0 + - name: Mark workspace as safe for git + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Install build tools and Python 3.12 run: | if [ "$(id -u)" -eq 0 ]; then From 8bd11da6c5ca378b87a664f2f6248c6af96bc8d4 Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 15:27:53 +0300 Subject: [PATCH 7/9] Issue #424 - fix branch detection on Windows --- specs/src/build_info.targets | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specs/src/build_info.targets b/specs/src/build_info.targets index 4056702e..7e1e6228 100644 --- a/specs/src/build_info.targets +++ b/specs/src/build_info.targets @@ -26,6 +26,11 @@ $(BuildBranch.Trim()) + + + $(SPECS_BRANCH) + + From c04d92f0ee569788d05aa33004b97e7e41a2c83d Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 16:06:57 +0300 Subject: [PATCH 8/9] Issue #424 - fix examples of @build-info --- manpage | 7 ++----- specs/docs/alu.md | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/manpage b/manpage index 1cc582b2..4924910c 100644 --- a/manpage +++ b/manpage @@ -2318,15 +2318,12 @@ contains the build number from GitHub Actions (github.run_number). Empty for loc .IP "build-info" 3 contains a composite string with all build information. For example: .p - commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (local) + Built locally from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T13:01:18 .p or .p - commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (github) - build 199 + Built on github (build 217) from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T12:40:01 .p -or if the branch is not available: -.p - commit b74fcb1 built on 2026-06-08T08:22:52 (local) .SH EXAMPLES `ls -l` yields this: diff --git a/specs/docs/alu.md b/specs/docs/alu.md index 25ce2eb4..0aa1fdae 100644 --- a/specs/docs/alu.md +++ b/specs/docs/alu.md @@ -125,7 +125,8 @@ Build information is also available via the following labels: - `@build-number` — the GitHub Actions build number (empty for local builds) - `@build-info` — a composite string with all build information, e.g.: ``` - commit b74fcb1 on branch dev-1.0.0 built on 2026-06-08T08:22:52 (local) + Built locally from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T13:01:18 + Built on github (build 217) from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T12:40:01 ``` Additionally, the `@@` string stands for the entire input record. When rolling context is in effect (see [Streams and Records](streams.md#rolling-context)), `@@` always refers to the original input record. The `@!` string refers to the current record as affected by `CONTEXT`, which is the same as `@@` when no `CONTEXT` is active. The `@-n` and `@+n` syntax is an alternative to using that is effective within expressions. Note that reading beyond the input with `@+n` or `@-n` does not cause processing to stop, even if a `READSTOP` token is present in the specification. The following three specifications are equivalent: From 4f4f3de329067b1571e64f0d156d50db8e6d52c8 Mon Sep 17 00:00:00 2001 From: niry1 Date: Mon, 8 Jun 2026 16:21:52 +0300 Subject: [PATCH 9/9] Issue #424 - final tweak to build-info --- manpage | 6 +++--- specs/docs/alu.md | 2 +- specs/src/processing/Config.cc | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/manpage b/manpage index 4924910c..3807d706 100644 --- a/manpage +++ b/manpage @@ -2272,11 +2272,11 @@ The system also defines some labels: .IP "version" 3 This returns the version of .B specs, -for example "v0.6" +for example "1.0.0" .P To find out the version of specs that you are using, use the following command: .P - specs @version 1 + specs @version .IP "cols" 3 contains the number of columns in the display. You can override this in the configuration file. For example, the following prints a right-justified string. .P @@ -2322,7 +2322,7 @@ contains a composite string with all build information. For example: .p or .p - Built on github (build 217) from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T12:40:01 + Built on github (build 217) from commit 8bd11da of version 1.0.0 at 2026-06-08T12:40:01 .p .SH EXAMPLES diff --git a/specs/docs/alu.md b/specs/docs/alu.md index 0aa1fdae..ca3c1c8e 100644 --- a/specs/docs/alu.md +++ b/specs/docs/alu.md @@ -126,7 +126,7 @@ Build information is also available via the following labels: - `@build-info` — a composite string with all build information, e.g.: ``` Built locally from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T13:01:18 - Built on github (build 217) from commit 8bd11da on branch dev-1.0.0 at 2026-06-08T12:40:01 + Built on github (build 217) from commit 8bd11da of version 1.0.0 at 2026-06-08T12:40:01 ``` Additionally, the `@@` string stands for the entire input record. When rolling context is in effect (see [Streams and Records](streams.md#rolling-context)), `@@` always refers to the original input record. The `@!` string refers to the current record as affected by `CONTEXT`, which is the same as `@@` when no `CONTEXT` is active. The `@-n` and `@+n` syntax is an alternative to using that is effective within expressions. Note that reading beyond the input with `@+n` or `@-n` does not cause processing to stop, even if a `READSTOP` token is present in the specification. The following three specifications are equivalent: diff --git a/specs/src/processing/Config.cc b/specs/src/processing/Config.cc index 87e8f4e3..a08d9f40 100644 --- a/specs/src/processing/Config.cc +++ b/specs/src/processing/Config.cc @@ -234,7 +234,11 @@ void readConfigurationFile() if (!ExternalLiterals["build-commit"].empty()) { build_info += " from commit " + ExternalLiterals["build-commit"]; if (!ExternalLiterals["build-branch"].empty()) { - build_info += " on branch " + ExternalLiterals["build-branch"]; + if (ExternalLiterals["build-branch"]=="dev" || ExternalLiterals["build-branch"]=="stable") { + build_info += " of version " + ExternalLiterals["version"]; + } else { + build_info += " on branch " + ExternalLiterals["build-branch"]; + } } } build_info += " at " + ExternalLiterals["build-time"];