diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5c774..13f16c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.26.1] - 2026-10-21 + +### Fixed +- Installed wget in the decoder image so the compose healthcheck can probe /live. + ## [0.26.0] - 2026-10-20 ### Added diff --git a/Dockerfile b/Dockerfile index b31d29e..d081926 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,12 @@ RUN npm ci --omit=dev FROM node:22-bookworm-slim@sha256:c3de60bf2f9dd0ac6370e6117950ff62d6e339527e7472301c9c78a017978392 AS decoder WORKDIR /XChainDecoder +# wget is not in node:22-bookworm-slim. The compose healthcheck (owned by +# xchain-node) probes GET /live with wget, so without it every decoder reads +# unhealthy while /live answers 200 healthy. +RUN apt-get update \ + && apt-get install -y --no-install-recommends wget \ + && rm -rf /var/lib/apt/lists/* COPY ./package.json /XChainDecoder/package.json COPY ./package-lock.json /XChainDecoder/package-lock.json COPY --from=dependencies /XChainDecoder/node_modules /XChainDecoder/node_modules diff --git a/package-lock.json b/package-lock.json index 51de7f0..e813b36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "xchain-decoder", - "version": "0.26.0", + "version": "0.26.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "xchain-decoder", - "version": "0.26.0", + "version": "0.26.1", "license": "AGPL-3.0-or-later", "dependencies": { "axios": "^1.18.1", @@ -3256,9 +3256,9 @@ "license": "ISC" }, "node_modules/follow-redirects": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", - "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz", + "integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==", "funding": [ { "type": "individual", diff --git a/package.json b/package.json index 3c311d8..e9aa2d6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "xchain-decoder", "description": "xchain-decoder decodes XChain platform transactions from a given blockchain and populates a database with the decoded data.", - "version": "0.26.0", + "version": "0.26.1", "license": "AGPL-3.0-or-later", "repository": { "type": "git", diff --git a/test/unit/sql_no_timestamp_columns.test.js b/test/unit/sql_no_timestamp_columns.test.js index 3c09351..aac845e 100644 --- a/test/unit/sql_no_timestamp_columns.test.js +++ b/test/unit/sql_no_timestamp_columns.test.js @@ -17,12 +17,23 @@ const Database = require('../../src/db.js'); const ROOT_DIR = path.join(__dirname, '..', '..'); const SQL_DIR = path.join(ROOT_DIR, 'src', 'sql'); const MIGRATION_STATEMENTS = path.join(ROOT_DIR, 'src', 'db', 'migration_statements.js'); +const MIGRATION_LEDGER = path.join(ROOT_DIR, 'src', 'db', 'migration_ledger.js'); const FIRST_SEEN_MIGRATION = path.join( SQL_DIR, 'migrations', '2026-09-27-mempool-first-seen-datetime.sql' ); +function assertLedgerAlterDeclaresDatetime(source){ + const code = source + .replace(/\/\*[\s\S]*?\*\//g, '') + .replace(/^\s*\/\/.*$/gm, ''); + const alter = code.match(/ALTER\s+TABLE\s+schema_migrations\s+MODIFY\s+applied_at\s+([A-Za-z]+)/i); + + assert.ok(alter, 'missing ALTER TABLE schema_migrations MODIFY applied_at'); + assert.strictEqual(alter[1].toUpperCase(), 'DATETIME', `applied_at ALTER declares ${alter[1]}`); +} + describe('SQL DATETIME completeness', function () { it('declares no TIMESTAMP columns in top-level SQL definitions', function () { const offenders = []; @@ -75,3 +86,15 @@ describe('SQL DATETIME completeness', function () { assert.strictEqual(db.connectionParams.timezone, 'Z'); }); }); + +describe('migration ledger applied_at ALTER', function () { + it('declares the migration_ledger.js applied_at ALTER as DATETIME', function () { + assertLedgerAlterDeclaresDatetime(fs.readFileSync(MIGRATION_LEDGER, 'utf8')); + }); + + it('rejects a migration_ledger.js applied_at ALTER declared as TIMESTAMP', function () { + const fixture = "await conn.query('ALTER TABLE schema_migrations MODIFY applied_at TIMESTAMP NOT NULL');"; + + assert.throws(() => assertLedgerAlterDeclaresDatetime(fixture), /TIMESTAMP/); + }); +});