diff --git a/test/images.test.js b/test/images.test.js index c381695..861d66d 100644 --- a/test/images.test.js +++ b/test/images.test.js @@ -1,7 +1,174 @@ -//const ImagesCalculator = require("../utils/ImagesCalculator.js") +const ImagesCalculator = require("../utils/ImagesCalculator.js") -test('Images calculator works with normal images', () => { +function mockRelease({tag_name, created_at, prerelease}){ + + return { + + "url": "https://api.github.com/repos/octocat/Hello-World/releases/1", + "html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets", + "upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}", + "tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0", + "id": 1, + "node_id": "MDc6UmVsZWFzZTE=", + tag_name, + "target_commitish": "master", + "name": "v1.0.0", + "body": "Description of the release", + "draft": false, + prerelease, + created_at, + "published_at": "2013-02-27T19:35:32Z", + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + } +} + +test("Images calculator works with prereleases", async () => { + + const MOCK_OCKTOKIT = { + + rest: { + + repos: { + + async listReleases(){ + + return { + + data: [ + + mockRelease({tag_name: "v1.0.2-pre", prerelease: true, created_at: "2013-02-25T19:35:32Z"}), + mockRelease({tag_name: "v2.0", prerelease: false, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v1.0.5-pre", prerelease: true, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v1.0.5-pre-1", prerelease: true, created_at: "2013-02-25T19:45:32Z"}), + mockRelease({tag_name: "v0.0.5-pre", prerelease: true, created_at: "2013-01-27T19:35:32Z"}), + + ] + } + + } + + } + + } + + } + + return ImagesCalculator({ + + action_type: "last_prerelease", + + }, MOCK_OCKTOKIT, true) + + .then(tag => expect(tag).toEqual("v1.0.5-pre_default")) + + .catch(e => console.error(e)) + + +}) + +test('Images calculator works with filter for prereleases', () => { + + const MOCK_OCKTOKIT = { + + rest: { + + repos: { + + async listReleases(){ + + return { + + data: [ + + mockRelease({tag_name: "v1.0.2-pre", prerelease: true, created_at: "2013-02-25T19:35:32Z"}), + mockRelease({tag_name: "v2.0", prerelease: false, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v1.0.5-pre", prerelease: true, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v0.0.5-pre", prerelease: true, created_at: "2013-01-27T19:35:32Z"}), + + ] + } + + } + + } + + } + + } + + ImagesCalculator({ + + action_type: "last_prerelease_v1.0.x", + + }, MOCK_OCKTOKIT, true) + + .then(tag => expect(tag).toEqual("v1.0.5-pre_default")) + + .catch(e => console.error(e)) }) +test('Images calculator works with filter for releases', () => { + + const MOCK_OCKTOKIT = { + + rest: { + + repos: { + + async listReleases(){ + + return { + + data: [ + + mockRelease({tag_name: "v2.1", prerelease: false, created_at: "2013-02-28T19:35:32Z"}), + mockRelease({tag_name: "v1.0.2-pre", prerelease: true, created_at: "2013-02-25T19:35:32Z"}), + mockRelease({tag_name: "v2.0", prerelease: false, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v1.0.5-pre", prerelease: true, created_at: "2013-02-27T19:35:32Z"}), + mockRelease({tag_name: "v0.0.5-pre", prerelease: true, created_at: "2013-01-27T19:35:32Z"}), + + ] + } + + } + + } + + } + + } + + ImagesCalculator({ + + action_type: "last_release_v2.x", + + }, MOCK_OCKTOKIT, true) + + .then(tag => expect(tag).toEqual("v2.1_default")) + + .catch(e => console.error(e)) + +}) diff --git a/utils/ImagesCalculator.js b/utils/ImagesCalculator.js index dad0197..470a109 100644 --- a/utils/ImagesCalculator.js +++ b/utils/ImagesCalculator.js @@ -1,8 +1,23 @@ const github = require("@actions/github") -module.exports = async function({action_type, flavour="default"}, ctx){ +// String regexps +const FILTERED_RELEASE = new RegExp(/^last_release_(v)?\d+\.([\d.-\w])*x/) - const image = await __calculateImage(action_type, ctx) +const FILTERED_PRERELEASE = new RegExp(/^last_prerelease_(v)?\d+\.([\d.-\w])*x/) + +// is the action a filter? +function isFilteredReleaseOrPrerelease(action_type){ + return new RegExp(/^(last_release_|last_prerelease_)/).test(action_type) +} + +// Utility function to escape special chars and compile into a RegExp dynamically +function utilRegEscape(string) { + return string.replace(/[-/^$*+?.()|[\]{}]/g, '\\$&') +} + +module.exports = async function({action_type, flavour="default"}, ctx, mock){ + + const image = await __calculateImage(action_type, ctx, mock) if(flavour){ return `${image}_${flavour}` @@ -13,83 +28,158 @@ module.exports = async function({action_type, flavour="default"}, ctx){ } - function __calculateImage(action_type, ctx){ - - const octokit = github.getOctokit(ctx.github_token) - - switch(action_type){ - - case "last_prerelease": - return __last_prerelease(octokit, ctx) - case "last_release": - return __last_release(octokit, ctx) - default: - if(action_type.match(/^branch_/)){ - - return __last_branch_commit(action_type, octokit, ctx) +function __calculateImage(action_type, ctx, mock){ + + const octokit = (mock) ? ctx : github.getOctokit(ctx.github_token) + + switch(action_type){ + + case "last_prerelease": + return __last_prerelease(octokit, ctx) + + case "last_release": + return __last_release(octokit, ctx) + + default: + if(isFilteredReleaseOrPrerelease(action_type)){ + if(FILTERED_PRERELEASE.test(action_type)){ + return __last_prerelease_filtered(octokit, ctx, action_type) + } + else if(FILTERED_RELEASE.test(action_type)){ + return __last_release_filtered(octokit, ctx, action_type) } else{ - - return action_type + throw `Syntax error on action_type: ${action_type}` } - } + } + if(action_type.match(/^branch_/)){ + + return __last_branch_commit(action_type, octokit, ctx) + } + else{ + + return action_type + } } +} - function __last_release(octokit, ctx){ +function __last_release(octokit, ctx){ - return octokit.rest.repos.getLatestRelease({ - - owner: ctx.owner, + return octokit.rest.repos.getLatestRelease({ - repo: ctx.repo + owner: ctx.owner, - }).then((r) => { - - return r.data.tag_name + repo: ctx.repo - }) - - } + }).then((r) => { - function __last_prerelease(octokit, ctx){ + return r.data.tag_name - return octokit.rest.repos.listReleases({ - - owner: ctx.owner, + }) - repo: ctx.repo +} + +function __last_prerelease(octokit, ctx){ + + return __getReleases(octokit, ctx) + + .then(rr => rr.data.filter(r => r.prerelease)) // by prereleases - }).then((rr) => { - - return rr.data.filter(r => r.prerelease)[0] + .then((prereleases) =>{ + + return __sortReleasesByTime(prereleases)[0] + }) // order by time (get the latest) + + .then(prerelease => prerelease ? prerelease.tag_name: null) // get the tag name + +} - }).then((r) => { - - if( r ) return r.tag_name +function __last_release_filtered(octokit, ctx, action_type){ + + // we prepare the filter + // is a regexp with the special part of .x replaced with .+ (any char) + // thus last_prerelease_1.x => /^1.\.+/ + const filter_reg = new RegExp('^' + utilRegEscape(action_type.replace(/last_release_/, '').replace(/x/, ''))) + + return __getReleases(octokit, ctx) + + .then(rr => rr.data.filter(r => !r.prerelease)) // by prereleases + + // match the filter + .then((releases) => { + + return releases.filter(r => filter_reg.test(r.tag_name)) - return null }) - - } - function __last_branch_commit(branch, octokit, ctx){ + .then(releases => __sortReleasesByTime(releases)[0]) // order by time (get the latest) - return octokit.rest.repos.getBranch({ - - owner: ctx.owner, + .then(release => release.tag_name) // get the tag name - repo: ctx.repo, +} - branch: branch.replace(/^branch_/, "") - - }).then((b) => { - - // - // we only use the first 8 chars of the commit's SHA for tagging - // - return b.data.commit.sha.substring(0, 7) +function __last_prerelease_filtered(octokit, ctx, action_type){ + + // we prepare the filter + // is a regexp with the special part of .x replaced with .+ (any char) + // thus last_prerelease_1.x => /^1.\.+/ + const filter_reg = new RegExp('^' + utilRegEscape(action_type.replace(/last_prerelease_/, '').replace(/x/, ''))) + + return __getReleases(octokit, ctx) + + .then(rr => rr.data.filter(r => r.prerelease)) // by prereleases + + // match the filter + .then((prereleases) => { + + return prereleases.filter(pr => filter_reg.test(pr.tag_name)) }) - } + .then(prereleases => __sortReleasesByTime(prereleases)[0]) // order by time (get the latest) + + .then(prerelease => prerelease.tag_name) // get the tag name +} + +function __getReleases(octokit, ctx){ + + return octokit.rest.repos.listReleases({ + + owner: ctx.owner, + + repo: ctx.repo + + }) +} + +function __sortReleasesByTime(releases){ + + return releases.sort((a, b) => { + + return Date.parse(a.created_at) <= Date.parse(b.created_at) ? 1 : -1 + + }) + +} + +function __last_branch_commit(branch, octokit, ctx){ + + return octokit.rest.repos.getBranch({ + + owner: ctx.owner, + + repo: ctx.repo, + + branch: branch.replace(/^branch_/, "") + + }).then((b) => { + + // + // we only use the first 8 chars of the commit's SHA for tagging + // + return b.data.commit.sha.substring(0, 7) + + }) + +}