Skip to content

Commit b7589b7

Browse files
committed
Update tarantool if there is more fresh version
Once a version is installed it's cached. A user could drop the cache manually (by updating cache-key), but it should be automated. This patch changes the caching logics. The 'cache-key' input is deprecated. Instead, it includes precise deb package version which is obtained by parsing repo content manually: ```js http_get("https://download.tarantool.org/tarantool/release/2.6" + "/ubuntu/dists/focal/main/binary-amd64/Packages" ) ``` It doesn't waste too much time and allows us to reinstall tarantool from apt-get when the new verison is out. Resulting key looks like ```txt tarantool-setup-focal-2.8.0.0.gefc30ccf8-1 ```
1 parent 375df30 commit b7589b7

File tree

6 files changed

+182
-57
lines changed

6 files changed

+182
-57
lines changed

.github/workflows/test.yml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,41 @@ jobs:
99
fail-fast: false
1010
matrix:
1111
runs-on: [ubuntu-20.04]
12-
tarantool: ['1.10', '2.4', '2.5', '2.6', '2.7']
12+
tarantool:
13+
- '1.10'
14+
- '2.4'
15+
- '2.5'
16+
- '2.6'
17+
- '2.7'
18+
- '2.8'
1319
include:
1420
- {runs-on: ubuntu-18.04, tarantool: '1.10'}
1521
- {runs-on: ubuntu-16.04, tarantool: '1.10'}
1622
runs-on: ${{ matrix.runs-on }}
23+
env:
24+
TARANTOOL_CACHE_KEY_SUFFIX: -${{ github.run_id }}
1725
steps:
1826
- uses: actions/checkout@v2
1927

28+
- id: get-latest
29+
run: |
30+
node <<'SCRIPT'
31+
process.env["INPUT_TARANTOOL-VERSION"] = "${{ matrix.tarantool }}"
32+
require("./dist/main").latest_version().then(v => {
33+
console.log(v)
34+
console.log(`::set-output name=version::${v}`)
35+
})
36+
SCRIPT
37+
2038
- name: Setup from scratch
2139
uses: ./
2240
with:
2341
tarantool-version: ${{ matrix.tarantool }}
24-
cache-key: tarantool-${{ matrix.tarantool }}-${{ matrix.runs-on }}-${{ github.run_id }}
42+
43+
- name: Check precise version
44+
run: |
45+
dpkg -s tarantool | grep '^Version: ${{ steps.get-latest.outputs.version }}'
46+
# It'll also fail if tarantool is installed from cache but not from apt-get
2547
2648
- name: Uninstall tarantool
2749
run: sudo apt-get -y remove tarantool tarantool-dev tarantool-common
@@ -30,9 +52,8 @@ jobs:
3052
uses: ./
3153
with:
3254
tarantool-version: ${{ matrix.tarantool }}
33-
cache-key: tarantool-${{ matrix.tarantool }}-${{ matrix.runs-on }}-${{ github.run_id }}
3455

35-
- name: Check version
56+
- name: Check branch version
3657
run: |
3758
T=$(tarantool -e 'print(_TARANTOOL:match("%d+%.%d+")); os.exit()')
3859
if [ "$T" != "${{ matrix.tarantool }}" ]; then

README.md

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This action will set up [Tarantool](https://www.tarantool.io) environment and **
77
- When cached, it takes \~1-2s to finish.
88
- The first run takes \~40s.
99
- Cache size is \~20MB.
10-
- Runs on `ubuntu-*` only.
10+
- Runs on GitHub-hosted `ubuntu-*` runners only.
1111

1212
# Usage
1313

@@ -18,28 +18,12 @@ steps:
1818
- uses: actions/checkout@v2
1919
- uses: tarantool/setup-tarantool@v1
2020
with:
21-
tarantool-version: '2.5'
21+
tarantool-version: '2.6'
2222
- run: tarantoolctl rocks install luatest
2323
- run: tarantoolctl rocks make
2424
- run: .rocks/bin/luatest -v
2525
```
2626
27-
### Custom cache key
28-
29-
By default, the action caches installed apt packages with the key:
30-
31-
```tarantool-setup-${tarantool-version}-${ubuntu-version}```
32-
33-
If you need to drop the cache, it's customizable:
34-
35-
```yaml
36-
steps:
37-
- uses: tarantool/setup-tarantool@v1
38-
with:
39-
tarantool-version: 2.5
40-
cache-key: some-other-key
41-
```
42-
4327
# License
4428
4529
The scripts and documentation in this project are released under the [MIT License](LICENSE).

action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ inputs:
77
tarantool-version:
88
description: Tarantool version
99
cache-key:
10-
description: Custom key used for APT packages caching
10+
description: Deprecated. Custom key used for APT packages caching
1111
required: false
1212
runs:
1313
using: 'node12'
14-
main: dist/main/index.js
14+
main: dist/index.js

dist/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require("./main").run()

dist/main/index.js

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3392,13 +3392,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
33923392
return result;
33933393
};
33943394
Object.defineProperty(exports, "__esModule", { value: true });
3395+
exports.run = exports.latest_version = void 0;
33953396
const httpm = __importStar(__webpack_require__(539));
33963397
const cache = __importStar(__webpack_require__(692));
33973398
const core = __importStar(__webpack_require__(470));
33983399
const exec = __importStar(__webpack_require__(986));
33993400
const io = __importStar(__webpack_require__(1));
34003401
const path = __importStar(__webpack_require__(622));
34013402
const fs = __importStar(__webpack_require__(747));
3403+
const baseUrl = 'https://download.tarantool.org/tarantool/release/' +
3404+
core.getInput('tarantool-version', { required: true });
34023405
async function capture(cmd, options) {
34033406
let output = '';
34043407
await exec.exec(cmd, [], {
@@ -3411,21 +3414,84 @@ async function capture(cmd, options) {
34113414
});
34123415
return output.trim();
34133416
}
3417+
let _lsb_release;
3418+
async function lsb_release() {
3419+
if (!_lsb_release) {
3420+
_lsb_release = capture('lsb_release -c -s', { silent: true });
3421+
}
3422+
return _lsb_release;
3423+
}
3424+
let _httpc;
3425+
async function http_get(url) {
3426+
if (!_httpc) {
3427+
_httpc = new httpm.HttpClient('httpc');
3428+
}
3429+
core.info('HTTP GET ' + url);
3430+
return _httpc.get(url);
3431+
}
34143432
async function dpkg_list() {
34153433
const cmd = 'sudo dpkg-query -W -f "${binary:Package}\\n"';
34163434
const output = await capture(cmd, { silent: true });
34173435
let ret = new Set();
34183436
output.split('\n').forEach(l => ret.add(l));
34193437
return ret;
34203438
}
3439+
function semver_max(a, b) {
3440+
const re = /[.-]/;
3441+
var pa = a.split(re);
3442+
var pb = b.split(re);
3443+
for (var i = 0;; i++) {
3444+
var na = Number(pa[i]);
3445+
var nb = Number(pb[i]);
3446+
if (na > nb)
3447+
return a;
3448+
if (nb > na)
3449+
return b;
3450+
if (!isNaN(na) && isNaN(nb))
3451+
return a;
3452+
if (isNaN(na) && !isNaN(nb))
3453+
return b;
3454+
if (isNaN(na) && isNaN(nb))
3455+
return pa[i] >= pb[i] ? a : b;
3456+
}
3457+
}
3458+
async function latest_version() {
3459+
const repo = baseUrl + '/ubuntu/dists/' + (await lsb_release());
3460+
return http_get(`${repo}/main/binary-amd64/Packages`)
3461+
.then(response => {
3462+
if (response.message.statusCode !== 200) {
3463+
throw new Error(`server replied ${response.message.statusCode}`);
3464+
}
3465+
return response.readBody();
3466+
})
3467+
.then(output => {
3468+
let ret = '';
3469+
output
3470+
.split('\n\n')
3471+
.filter(paragraph => paragraph.startsWith('Package: tarantool\n'))
3472+
.forEach(paragraph => {
3473+
const match = paragraph.match(/^Version: (.+)$/m);
3474+
const version = match ? match[1] : ret;
3475+
ret = semver_max(ret, version);
3476+
});
3477+
return ret;
3478+
});
3479+
}
3480+
exports.latest_version = latest_version;
34213481
async function run_linux() {
34223482
try {
3423-
const httpc = new httpm.HttpClient('httpc');
3424-
const t_version = core.getInput('tarantool-version', { required: true });
3425-
const lsb_release = await capture('lsb_release -c -s', { silent: true });
3483+
const distro = await lsb_release();
34263484
const cache_dir = 'cache-tarantool';
3427-
const cache_key = core.getInput('cache-key') ||
3428-
`tarantool-setup-${t_version}-${lsb_release}`;
3485+
core.startGroup('Checking latest tarantool version');
3486+
const version = await latest_version();
3487+
core.info(`${version}`);
3488+
core.endGroup();
3489+
if (core.getInput('cache-key')) {
3490+
core.warning("Setup-tarantool input 'cache-key' is deprecated");
3491+
}
3492+
let cache_key = `tarantool-setup-${distro}-${version}`;
3493+
// This for testing only
3494+
cache_key += process.env['TARANTOOL_CACHE_KEY_SUFFIX'] || '';
34293495
if (await cache.restoreCache([cache_dir], cache_key)) {
34303496
core.info(`Cache restored from key: ${cache_key}`);
34313497
await exec.exec(`sudo rsync -aK "${cache_dir}/" /`);
@@ -3435,20 +3501,17 @@ async function run_linux() {
34353501
else {
34363502
core.info(`Cache not found for input key: ${cache_key}`);
34373503
}
3438-
const baseUrl = 'https://download.tarantool.org/tarantool/release/' + t_version;
34393504
await core.group('Adding gpg key', async () => {
3440-
const url = baseUrl + '/gpgkey';
3441-
core.info('curl ' + url);
3442-
const response = await httpc.get(url);
3505+
const response = await http_get(baseUrl + '/gpgkey');
34433506
if (response.message.statusCode !== 200) {
3444-
throw new Error('server replied ${response.message.statusCode}');
3507+
throw new Error(`server replied ${response.message.statusCode}`);
34453508
}
34463509
const gpgkey = Buffer.from(await response.readBody());
34473510
await exec.exec('sudo apt-key add - ', [], { input: gpgkey });
34483511
});
34493512
await core.group('Setting up repository', async () => {
34503513
await exec.exec('sudo tee /etc/apt/sources.list.d/tarantool.list', [], {
3451-
input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${lsb_release} main\n`)
3514+
input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${distro} main\n`)
34523515
});
34533516
});
34543517
await core.group('Running apt-get update', async () => {
@@ -3495,8 +3558,7 @@ async function run() {
34953558
}
34963559
await exec.exec('tarantool --version');
34973560
}
3498-
run();
3499-
exports.default = run;
3561+
exports.run = run;
35003562

35013563

35023564
/***/ }),

src/main.ts

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import * as io from '@actions/io'
77
import * as path from 'path'
88
import * as fs from 'fs'
99

10+
const baseUrl =
11+
'https://download.tarantool.org/tarantool/release/' +
12+
core.getInput('tarantool-version', {required: true})
13+
1014
interface CaptureOptions {
1115
/** optional. defaults to false */
1216
silent?: boolean
@@ -27,6 +31,24 @@ async function capture(cmd: string, options?: CaptureOptions): Promise<string> {
2731
return output.trim()
2832
}
2933

34+
let _lsb_release: Promise<string>
35+
async function lsb_release(): Promise<string> {
36+
if (!_lsb_release) {
37+
_lsb_release = capture('lsb_release -c -s', {silent: true})
38+
}
39+
40+
return _lsb_release
41+
}
42+
43+
let _httpc: httpm.HttpClient
44+
async function http_get(url: string): Promise<httpm.HttpClientResponse> {
45+
if (!_httpc) {
46+
_httpc = new httpm.HttpClient('httpc')
47+
}
48+
core.info('HTTP GET ' + url)
49+
return _httpc.get(url)
50+
}
51+
3052
async function dpkg_list(): Promise<Set<string>> {
3153
const cmd = 'sudo dpkg-query -W -f "${binary:Package}\\n"'
3254
const output: string = await capture(cmd, {silent: true})
@@ -36,15 +58,60 @@ async function dpkg_list(): Promise<Set<string>> {
3658
return ret
3759
}
3860

61+
function semver_max(a: string, b: string): string {
62+
const re = /[.-]/
63+
var pa = a.split(re)
64+
var pb = b.split(re)
65+
for (var i = 0; ; i++) {
66+
var na = Number(pa[i])
67+
var nb = Number(pb[i])
68+
if (na > nb) return a
69+
if (nb > na) return b
70+
if (!isNaN(na) && isNaN(nb)) return a
71+
if (isNaN(na) && !isNaN(nb)) return b
72+
if (isNaN(na) && isNaN(nb)) return pa[i] >= pb[i] ? a : b
73+
}
74+
}
75+
76+
export async function latest_version(): Promise<string> {
77+
const repo = baseUrl + '/ubuntu/dists/' + (await lsb_release())
78+
return http_get(`${repo}/main/binary-amd64/Packages`)
79+
.then(response => {
80+
if (response.message.statusCode !== 200) {
81+
throw new Error(`server replied ${response.message.statusCode}`)
82+
}
83+
return response.readBody()
84+
})
85+
.then(output => {
86+
let ret = ''
87+
output
88+
.split('\n\n')
89+
.filter(paragraph => paragraph.startsWith('Package: tarantool\n'))
90+
.forEach(paragraph => {
91+
const match = paragraph.match(/^Version: (.+)$/m)
92+
const version = match ? match[1] : ret
93+
ret = semver_max(ret, version)
94+
})
95+
return ret
96+
})
97+
}
98+
3999
async function run_linux(): Promise<void> {
40100
try {
41-
const httpc = new httpm.HttpClient('httpc')
42-
const t_version = core.getInput('tarantool-version', {required: true})
43-
const lsb_release = await capture('lsb_release -c -s', {silent: true})
101+
const distro = await lsb_release()
44102
const cache_dir = 'cache-tarantool'
45-
const cache_key =
46-
core.getInput('cache-key') ||
47-
`tarantool-setup-${t_version}-${lsb_release}`
103+
104+
core.startGroup('Checking latest tarantool version')
105+
const version = await latest_version()
106+
core.info(`${version}`)
107+
core.endGroup()
108+
109+
if (core.getInput('cache-key')) {
110+
core.warning("Setup-tarantool input 'cache-key' is deprecated")
111+
}
112+
let cache_key = `tarantool-setup-${distro}-${version}`
113+
// This for testing only
114+
cache_key += process.env['TARANTOOL_CACHE_KEY_SUFFIX'] || ''
48115

49116
if (await cache.restoreCache([cache_dir], cache_key)) {
50117
core.info(`Cache restored from key: ${cache_key}`)
@@ -55,16 +122,10 @@ async function run_linux(): Promise<void> {
55122
core.info(`Cache not found for input key: ${cache_key}`)
56123
}
57124

58-
const baseUrl =
59-
'https://download.tarantool.org/tarantool/release/' + t_version
60-
61125
await core.group('Adding gpg key', async () => {
62-
const url = baseUrl + '/gpgkey'
63-
core.info('curl ' + url)
64-
65-
const response = await httpc.get(url)
126+
const response = await http_get(baseUrl + '/gpgkey')
66127
if (response.message.statusCode !== 200) {
67-
throw new Error('server replied ${response.message.statusCode}')
128+
throw new Error(`server replied ${response.message.statusCode}`)
68129
}
69130

70131
const gpgkey = Buffer.from(await response.readBody())
@@ -73,7 +134,7 @@ async function run_linux(): Promise<void> {
73134

74135
await core.group('Setting up repository', async () => {
75136
await exec.exec('sudo tee /etc/apt/sources.list.d/tarantool.list', [], {
76-
input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${lsb_release} main\n`)
137+
input: Buffer.from(`deb ${baseUrl}/ubuntu/ ${distro} main\n`)
77138
})
78139
})
79140

@@ -121,7 +182,7 @@ async function run_linux(): Promise<void> {
121182
}
122183
}
123184

124-
async function run(): Promise<void> {
185+
export async function run(): Promise<void> {
125186
if (process.platform === 'linux') {
126187
await run_linux()
127188
} else {
@@ -130,7 +191,3 @@ async function run(): Promise<void> {
130191

131192
await exec.exec('tarantool --version')
132193
}
133-
134-
run()
135-
136-
export default run

0 commit comments

Comments
 (0)