aaronsb opened a new issue, #2570:
URL: https://github.com/apache/age/issues/2570
**Describe the bug**
The official Docker images ship no extension update scripts, so `ALTER
EXTENSION age UPDATE` can never work inside them.
`Makefile` installs every tracked update script:
```make
# Git-tracked upgrade scripts shipped with the extension (e.g.,
age--1.6.0--1.7.0.sql).
# Excludes the upgrade template (y.y.y) and the synthetic stamped test file.
DATA = $(filter-out age--%--y.y.y.sql $(age_upgrade_test_sql),$(wildcard
age--*--*.sql))
```
but `docker/Dockerfile` enumerates the files it copies out of the build
stage individually, and lists only three:
```dockerfile
COPY --from=build /usr/lib/postgresql/18/lib/age.so
/usr/lib/postgresql/18/lib/
COPY --from=build /usr/share/postgresql/18/extension/age--1.8.0.sql
/usr/share/postgresql/18/extension/
COPY --from=build /usr/share/postgresql/18/extension/age.control
/usr/share/postgresql/18/extension/
```
`make install` in the build stage does place `age--1.7.0--1.8.0.sql` in the
extension directory, but the final-stage `COPY` list drops it.
This is the same class of problem as #2257 (`Makefile` not installing
`age--1.5.0--1.6.0.sql`), one layer further out: the Makefile is now correct,
but the image build discards what it produced.
**How are you accessing AGE (Command line, driver, etc.)?**
psql, inside the published `apache/age` Docker images.
**What data setup do we need to do?**
A cluster initialised under an older AGE, then started under a newer image.
**What is the command that caused the error?**
```
ALTER EXTENSION age UPDATE;
ERROR: extension "age" has no update path from version "1.7.0" to version
"1.8.0"
```
**Reproduction**
The images contain no update scripts at all:
```console
$ docker run --rm --entrypoint find apache/age:release_PG18_1.8.0 / -name
'age--*' 2>/dev/null
/usr/share/postgresql/18/extension/age--1.8.0.sql
$ docker run --rm --entrypoint find apache/age:release_PG18_1.7.0 / -name
'age--*' 2>/dev/null
/usr/share/postgresql/18/extension/age--1.7.0.sql
```
Full path to the failure:
```console
# 1. initialise a volume under 1.7.0 and create a graph
$ docker volume create agetest
$ docker run -d --name age17 -e POSTGRES_PASSWORD=t -e POSTGRES_DB=t \
-v agetest:/var/lib/postgresql apache/age:release_PG18_1.7.0
$ docker exec age17 psql -U postgres -d t -c "CREATE EXTENSION IF NOT EXISTS
age;" \
-c "LOAD 'age'; SET search_path=ag_catalog,\"\$user\",public;
SELECT create_graph('testgraph');
SELECT * FROM cypher('testgraph', \$\$
CREATE (a:Concept {label:'alpha'})-[:IMPLIES]->(b:Concept
{label:'beta'}) RETURN a
\$\$) AS (a agtype);"
# 2. stop it and start 1.8.0 on the same volume
$ docker rm -f age17
$ docker run -d --name age18 -e POSTGRES_PASSWORD=t -e POSTGRES_DB=t \
-v agetest:/var/lib/postgresql apache/age:release_PG18_1.8.0
```
The catalog is still 1.7.0 and cannot be updated:
```
SELECT extversion FROM pg_extension WHERE extname='age'; -- 1.7.0
ALTER EXTENSION age UPDATE;
ERROR: extension "age" has no update path from version "1.7.0" to version
"1.8.0"
```
Writes still succeed, but **every read fails**:
```
--- MATCH (c:Concept) RETURN c.label
ERROR: type with OID 0 does not exist
--- MATCH (c:Concept) RETURN count(c)
ERROR: type with OID 0 does not exist
--- MATCH (c:Concept) RETURN c
ERROR: cache lookup failed for type 0
--- MATCH ()-[r]->() RETURN type(r)
ERROR: type() argument must be an edge or null
```
That is consistent with the signature changes in `age--1.7.0--1.8.0.sql` —
`_agtype_build_vertex` and `_agtype_build_edge` now take `agtype` where they
took `cstring`, and `_label_name` now `RETURNS agtype` where it returned
`cstring`. The 1.8.0 library is being called through 1.7.0 catalog entries.
**Confirmation that the script itself is fine**
Copying the repo's own `age--1.7.0--1.8.0.sql` into the image's extension
directory makes everything work:
```console
$ docker cp age--1.7.0--1.8.0.sql age18:/usr/share/postgresql/18/extension/
$ docker exec age18 psql -U postgres -d t -c "ALTER EXTENSION age UPDATE;"
ALTER EXTENSION
```
```
SELECT extversion FROM pg_extension WHERE extname='age'; -- 1.8.0
--- MATCH (c:Concept) RETURN c.label "alpha", "beta"
--- MATCH (c:Concept) RETURN count(c) 2
--- MATCH (c:Concept) RETURN c {"id": 844424930131969, "label":
"Concept",
"properties": {"label":
"alpha"}}::vertex
--- MATCH ()-[r]->() RETURN type(r) "IMPLIES"
```
Pre-existing data is intact, original graphids preserved. So nothing is
wrong with the update script — it just isn't in the image.
**Expected behavior**
The published images should contain the `age--*--*.sql` update scripts that
`make install` produces, so `ALTER EXTENSION age UPDATE` works for users
upgrading an existing cluster to a new image of the same PostgreSQL major
version.
**Suggested fix**
Copy the extension directory rather than enumerating files, e.g.:
```dockerfile
COPY --from=build /usr/share/postgresql/18/extension/age*.sql
/usr/share/postgresql/18/extension/
COPY --from=build /usr/share/postgresql/18/extension/age.control
/usr/share/postgresql/18/extension/
```
**Environment**
- Image: `apache/age:release_PG18_1.8.0`
(`sha256:47a0b054c3663a3e64a25fc0c5a982f1b58348019274b326a691cdf77f78eb58`),
and `release_PG18_1.7.0`
- PostgreSQL 18.6 / 18.1 (Debian, from the images)
- Source checked at tag `PG18/v1.8.0-rc0`
**Additional context**
Same root shape as #2257, #1508 and #132, which were all about update paths
not being reachable. Those were fixed in the build; this one is in the image
packaging.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]