Skip to content

Commit 0260cca

Browse files
committed
Stabilize Docker CI dependencies
1 parent 79663c1 commit 0260cca

5 files changed

Lines changed: 185 additions & 5 deletions

File tree

‎ChangeLog‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
thanks @Hockenba
55
- require lua-resty-session 4.2.0-1, which provides the propagated
66
revocation-store failure behavior
7+
- update the Docker CI image to Ubuntu Jammy and vendor its test-only
8+
Serpent dependency, removing a flaky Ubuntu Focal APT/Git dependency
79
- release 1.9.1
810

911
07/01/2026

‎tests/Dockerfile‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
1-
FROM openresty/openresty:focal
1+
FROM openresty/openresty:jammy
22

33
# install dependencies
44
RUN ["luarocks", "install", "lua-resty-session", "4.2.0-1"]
55
RUN ["luarocks", "install", "lua-resty-http"]
66
RUN ["luarocks", "install", "lua-resty-jwt"]
77

88
# install test dependencies
9-
RUN apt-get update \
10-
&& apt-get install -y --no-install-recommends ca-certificates git \
11-
&& rm -rf /var/lib/apt/lists/*
129
RUN ["luarocks", "install", "busted"]
1310
RUN ["luarocks", "install", "LuaSocket"]
14-
RUN ["luarocks", "install", "serpent"]
1511
RUN ["luarocks", "install", "dkjson"]
1612
RUN ["luarocks", "install", "luacov"]
1713

1814
ADD lib/resty/openidc.lua /usr/local/openresty/lualib/resty/openidc.lua
15+
ADD tests/vendor/serpent.lua /usr/local/openresty/lualib/serpent.lua
1916

2017
# mount tests
2118
ADD tests/spec /spec

‎tests/vendor/README.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Test-only vendored dependencies
2+
3+
`serpent.lua` is Serpent 0.303 by Paul Kulchenko, obtained from
4+
the `serpent-0.30-2` LuaRocks source release. It is used only by the Docker
5+
test suite and is distributed under the MIT License in `SERPENT-LICENSE`.
6+
7+
The file is vendored so the test image does not need to install `git` through
8+
APT merely to fetch Serpent's Git-based LuaRocks source release.

‎tests/vendor/SERPENT-LICENSE‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Serpent source is released under the MIT License
2+
3+
Copyright (c) 2012-2018 Paul Kulchenko (paul@kulchenko.com)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

‎tests/vendor/serpent.lua‎

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
local n, v = "serpent", "0.303" -- (C) 2012-18 Paul Kulchenko; MIT License
2+
local c, d = "Paul Kulchenko", "Lua serializer and pretty printer"
3+
local snum = {[tostring(1/0)]='1/0 --[[math.huge]]',[tostring(-1/0)]='-1/0 --[[-math.huge]]',[tostring(0/0)]='0/0'}
4+
local badtype = {thread = true, userdata = true, cdata = true}
5+
local getmetatable = debug and debug.getmetatable or getmetatable
6+
local pairs = function(t) return next, t end -- avoid using __pairs in Lua 5.2+
7+
local keyword, globals, G = {}, {}, (_G or _ENV)
8+
for _,k in ipairs({'and', 'break', 'do', 'else', 'elseif', 'end', 'false',
9+
'for', 'function', 'goto', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
10+
'return', 'then', 'true', 'until', 'while'}) do keyword[k] = true end
11+
for k,v in pairs(G) do globals[v] = k end -- build func to name mapping
12+
for _,g in ipairs({'coroutine', 'debug', 'io', 'math', 'string', 'table', 'os'}) do
13+
for k,v in pairs(type(G[g]) == 'table' and G[g] or {}) do globals[v] = g..'.'..k end end
14+
15+
local function s(t, opts)
16+
local name, indent, fatal, maxnum = opts.name, opts.indent, opts.fatal, opts.maxnum
17+
local sparse, custom, huge = opts.sparse, opts.custom, not opts.nohuge
18+
local space, maxl = (opts.compact and '' or ' '), (opts.maxlevel or math.huge)
19+
local maxlen, metatostring = tonumber(opts.maxlength), opts.metatostring
20+
local iname, comm = '_'..(name or ''), opts.comment and (tonumber(opts.comment) or math.huge)
21+
local numformat = opts.numformat or "%.17g"
22+
local seen, sref, syms, symn = {}, {'local '..iname..'={}'}, {}, 0
23+
local function gensym(val) return '_'..(tostring(tostring(val)):gsub("[^%w]",""):gsub("(%d%w+)",
24+
-- tostring(val) is needed because __tostring may return a non-string value
25+
function(s) if not syms[s] then symn = symn+1; syms[s] = symn end return tostring(syms[s]) end)) end
26+
local function safestr(s) return type(s) == "number" and (huge and snum[tostring(s)] or numformat:format(s))
27+
or type(s) ~= "string" and tostring(s) -- escape NEWLINE/010 and EOF/026
28+
or ("%q"):format(s):gsub("\010","n"):gsub("\026","\\026") end
29+
-- handle radix changes in some locales
30+
if opts.fixradix and (".1f"):format(1.2) ~= "1.2" then
31+
local origsafestr = safestr
32+
safestr = function(s) return type(s) == "number"
33+
and (nohuge and snum[tostring(s)] or numformat:format(s):gsub(",",".")) or origsafestr(s)
34+
end
35+
end
36+
local function comment(s,l) return comm and (l or 0) < comm and ' --[['..select(2, pcall(tostring, s))..']]' or '' end
37+
local function globerr(s,l) return globals[s] and globals[s]..comment(s,l) or not fatal
38+
and safestr(select(2, pcall(tostring, s))) or error("Can't serialize "..tostring(s)) end
39+
local function safename(path, name) -- generates foo.bar, foo[3], or foo['b a r']
40+
local n = name == nil and '' or name
41+
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
42+
local safe = plain and n or '['..safestr(n)..']'
43+
return (path or '')..(plain and path and '.' or '')..safe, safe end
44+
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
45+
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
46+
local function padnum(d) return ("%0"..tostring(maxn).."d"):format(tonumber(d)) end
47+
table.sort(k, function(a,b)
48+
-- sort numeric keys first: k[key] is not nil for numerical keys
49+
return (k[a] ~= nil and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
50+
< (k[b] ~= nil and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
51+
local function val2str(t, name, indent, insref, path, plainindex, level)
52+
local ttype, level, mt = type(t), (level or 0), getmetatable(t)
53+
local spath, sname = safename(path, name)
54+
local tag = plainindex and
55+
((type(name) == "number") and '' or name..space..'='..space) or
56+
(name ~= nil and sname..space..'='..space or '')
57+
if seen[t] then -- already seen this element
58+
sref[#sref+1] = spath..space..'='..space..seen[t]
59+
return tag..'nil'..comment('ref', level)
60+
end
61+
-- protect from those cases where __tostring may fail
62+
if type(mt) == 'table' and metatostring ~= false then
63+
local to, tr = pcall(function() return mt.__tostring(t) end)
64+
local so, sr = pcall(function() return mt.__serialize(t) end)
65+
if (to or so) then -- knows how to serialize itself
66+
seen[t] = insref or spath
67+
t = so and sr or tr
68+
ttype = type(t)
69+
end -- new value falls through to be serialized
70+
end
71+
if ttype == "table" then
72+
if level >= maxl then return tag..'{}'..comment('maxlvl', level) end
73+
seen[t] = insref or spath
74+
if next(t) == nil then return tag..'{}'..comment(t, level) end -- table empty
75+
if maxlen and maxlen < 0 then return tag..'{}'..comment('maxlen', level) end
76+
local maxn, o, out = math.min(#t, maxnum or #t), {}, {}
77+
for key = 1, maxn do o[key] = key end
78+
if not maxnum or #o < maxnum then
79+
local n = #o -- n = n + 1; o[n] is much faster than o[#o+1] on large tables
80+
for key in pairs(t) do
81+
if o[key] ~= key then n = n + 1; o[n] = key end
82+
end
83+
end
84+
if maxnum and #o > maxnum then o[maxnum+1] = nil end
85+
if opts.sortkeys and #o > maxn then alphanumsort(o, t, opts.sortkeys) end
86+
local sparse = sparse and #o > maxn -- disable sparsness if only numeric keys (shorter output)
87+
for n, key in ipairs(o) do
88+
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
89+
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing
90+
or opts.keyallow and not opts.keyallow[key]
91+
or opts.keyignore and opts.keyignore[key]
92+
or opts.valtypeignore and opts.valtypeignore[type(value)] -- skipping ignored value types
93+
or sparse and value == nil then -- skipping nils; do nothing
94+
elseif ktype == 'table' or ktype == 'function' or badtype[ktype] then
95+
if not seen[key] and not globals[key] then
96+
sref[#sref+1] = 'placeholder'
97+
local sname = safename(iname, gensym(key)) -- iname is table for local variables
98+
sref[#sref] = val2str(key,sname,indent,sname,iname,true)
99+
end
100+
sref[#sref+1] = 'placeholder'
101+
local path = seen[t]..'['..tostring(seen[key] or globals[key] or gensym(key))..']'
102+
sref[#sref] = path..space..'='..space..tostring(seen[value] or val2str(value,nil,indent,path))
103+
else
104+
out[#out+1] = val2str(value,key,indent,nil,seen[t],plainindex,level+1)
105+
if maxlen then
106+
maxlen = maxlen - #out[#out]
107+
if maxlen < 0 then break end
108+
end
109+
end
110+
end
111+
local prefix = string.rep(indent or '', level)
112+
local head = indent and '{\n'..prefix..indent or '{'
113+
local body = table.concat(out, ','..(indent and '\n'..prefix..indent or space))
114+
local tail = indent and "\n"..prefix..'}' or '}'
115+
return (custom and custom(tag,head,body,tail,level) or tag..head..body..tail)..comment(t, level)
116+
elseif badtype[ttype] then
117+
seen[t] = insref or spath
118+
return tag..globerr(t, level)
119+
elseif ttype == 'function' then
120+
seen[t] = insref or spath
121+
if opts.nocode then return tag.."function() --[[..skipped..]] end"..comment(t, level) end
122+
local ok, res = pcall(string.dump, t)
123+
local func = ok and "((loadstring or load)("..safestr(res)..",'@serialized'))"..comment(t, level)
124+
return tag..(func or globerr(t, level))
125+
else return tag..safestr(t) end -- handle all other types
126+
end
127+
local sepr = indent and "\n" or ";"..space
128+
local body = val2str(t, name, indent) -- this call also populates sref
129+
local tail = #sref>1 and table.concat(sref, sepr)..sepr or ''
130+
local warn = opts.comment and #sref>1 and space.."--[[incomplete output with shared/self-references skipped]]" or ''
131+
return not name and body..warn or "do local "..body..sepr..tail.."return "..name..sepr.."end"
132+
end
133+
134+
local function deserialize(data, opts)
135+
local env = (opts and opts.safe == false) and G
136+
or setmetatable({}, {
137+
__index = function(t,k) return t end,
138+
__call = function(t,...) error("cannot call functions") end
139+
})
140+
local f, res = (loadstring or load)('return '..data, nil, nil, env)
141+
if not f then f, res = (loadstring or load)(data, nil, nil, env) end
142+
if not f then return f, res end
143+
if setfenv then setfenv(f, env) end
144+
return pcall(f)
145+
end
146+
147+
local function merge(a, b) if b then for k,v in pairs(b) do a[k] = v end end; return a; end
148+
return { _NAME = n, _COPYRIGHT = c, _DESCRIPTION = d, _VERSION = v, serialize = s,
149+
load = deserialize,
150+
dump = function(a, opts) return s(a, merge({name = '_', compact = true, sparse = true}, opts)) end,
151+
line = function(a, opts) return s(a, merge({sortkeys = true, comment = true}, opts)) end,
152+
block = function(a, opts) return s(a, merge({indent = ' ', sortkeys = true, comment = true}, opts)) end }

0 commit comments

Comments
 (0)