diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
index 2cb9e03..f5b8e3b 100644
--- a/.github/workflows/node.js.yml
+++ b/.github/workflows/node.js.yml
@@ -23,7 +23,8 @@ jobs:
include:
- exist-version: latest
experimental: true
-
+ - exist-version: 5.2.0
+ experimental: true
services:
# Label used to access the service container
exist:
diff --git a/package.json b/package.json
index 3876e61..3b48251 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,12 @@
{
"name": "tuttle",
- "version": "1.2.0",
+ "version": "2.0.0",
"description": "tuttle - a Git-integration for eXist-db",
"scripts": {
"start": "gulp",
"test": "gulp install && mocha --exit",
"test:watch": "mocha --watch",
- "test:build": "gulp test:install",
- "build": "gulp build",
- "build:all": "gulp build && gulp test:build",
+ "build": "gulp xar",
"deploy": "gulp install",
"copy": "gulp copyStatic"
},
diff --git a/src/api.json b/src/api.json
index fae0dd9..a3520e8 100644
--- a/src/api.json
+++ b/src/api.json
@@ -19,7 +19,7 @@
},
"cookieAuth": {
"type": "apiKey",
- "name": "eeditiones.org.login",
+ "name": "org.exist.login",
"in": "cookie"
}
}
@@ -29,7 +29,7 @@
"get": {
"summary": "Fetch git repo to staging collection",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:git-pull",
"parameters": [
@@ -71,7 +71,7 @@
"post": {
"summary": "Deploy repo to final collection",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:git-deploy",
"parameters": [
@@ -107,7 +107,7 @@
"get": {
"summary": "Fetch git repo to staging collection",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:git-pull-default",
"parameters": [
@@ -141,7 +141,7 @@
"post": {
"summary": "Deploy repo to final collection",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:git-deploy",
"responses": {
@@ -167,7 +167,7 @@
"post": {
"summary": "Trigger incremental update",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:incremental",
"parameters": [
@@ -215,7 +215,7 @@
"post": {
"summary": "Trigger incremental update",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:incremental",
"parameters": [
@@ -255,7 +255,7 @@
"get": {
"summary": "Get remote and local hash",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:get-hash",
"parameters": [
@@ -299,7 +299,7 @@
"get": {
"summary": "Get remote and local hash",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:get-hash",
"responses": {
@@ -333,7 +333,7 @@
"get": {
"summary": "Get commits",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:get-commits",
"parameters": [
@@ -373,7 +373,7 @@
"get": {
"summary": "Get commits",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:get-commits-default",
"parameters": [
@@ -461,7 +461,7 @@
"get": {
"summary": "Generate API-Webhook-Keys",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:api-keygen",
"parameters": [
@@ -497,7 +497,7 @@
"get": {
"summary": "Generate API-Webhook-Keys",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:api-keygen",
"responses": {
@@ -523,7 +523,7 @@
"get": {
"summary": "Get Tuttle configuration",
"x-constraints": {
- "user": "admin"
+ "groups": ["dba"]
},
"operationId": "api:get-status",
"responses": {
diff --git a/src/expath-pkg.xml b/src/expath-pkg.xml
index b1557a7..046b8d9 100644
--- a/src/expath-pkg.xml
+++ b/src/expath-pkg.xml
@@ -2,7 +2,7 @@
Tuttle - Git for eXist-db
-
+
-
+
diff --git a/src/modules/api.xql b/src/modules/api.xql
index 57ce29f..afb734a 100644
--- a/src/modules/api.xql
+++ b/src/modules/api.xql
@@ -25,19 +25,23 @@ declare variable $api:definitions := ("api.json");
:)
declare function api:get-status($request as map(*)) {
if (contains(request:get-header('Accept'), 'application/json'))
- then map {
- 'default': config:default-collection(),
- 'repos': array {
- config:list-collections() ! api:collection-info(.)
+ then
+ map {
+ 'default': config:default-collection(),
+ 'repos': array {
+ for $collection-info in config:list-collections()
+ return
+ api:collection-info($collection-info)
+ }
}
- }
else
{config:default-collection()}
{
- config:list-collections()
- ! api:collection-info(.)
- ! api:repo-xml(.)
+ for $collection-info in config:list-collections()
+ return
+ api:repo-xml(
+ api:collection-info($collection-info))
}
};
@@ -53,7 +57,9 @@ declare function api:repo-xml ($info as map(*)) as element(repo) {
declare function api:collection-info ($collection as xs:string) as map(*) {
let $collection-config := api:get-collection-config($collection)
(: hide passwords and tokens :)
- let $masked := map:remove($collection-config, ("hookpasswd", "token"))
+ let $masked :=
+ map:remove(
+ map:remove($collection-config, "hookpasswd"), "token")
return
try {
@@ -103,7 +109,7 @@ declare function api:get-hash($request as map(*)) as map(*) {
let $last-remote-commit := $actions?get-last-commit($collection-config)
return map {
- "remote-hash": $last-remote-commit?sha,
+ "remote-hash": app:shorten-sha($last-remote-commit?sha),
"local-hash": $collection-config?deployed,
"local-staging-hash": doc($collection-staging)/hash/value/text()
}
@@ -413,6 +419,8 @@ declare function api:hook($request as map(*)) as map(*) {
let $config := api:get-collection-config($request?parameters?collection)
let $apikey := doc(config:apikeys())//apikeys/collection[name = $config?collection]/key/string()
let $lockfile := $config?path || "/" || config:lock()
+ let $actions := vcs:get-actions($config?type)
+
return
if (empty($apikey)) then (
map { "message": "apikey does not exist" }
@@ -430,7 +438,7 @@ declare function api:hook($request as map(*)) as map(*) {
let $incremental := $actions?incremental($config)
- let $remove-lock := app:lock-remove($collection-path)
+ let $remove-lock := app:lock-remove($config?path)
return
map {
diff --git a/src/modules/app.xql b/src/modules/app.xql
index 4905480..ae27d09 100644
--- a/src/modules/app.xql
+++ b/src/modules/app.xql
@@ -151,7 +151,10 @@ declare function app:set-permission($collection as xs:string) {
};
declare function app:get-permissions ($collection as xs:string) {
- if (doc-available($collection || "/repo.xml")) then (
+ if (
+ doc-available($collection || "/repo.xml") and
+ exists(doc($collection || "/repo.xml")//repo:permissions)
+ ) then (
let $repo := doc($collection || "/repo.xml")//repo:permissions
return map {
"user": $repo/@user/string(),
diff --git a/src/modules/github.xql b/src/modules/github.xql
index 3fac5fd..5feafe5 100644
--- a/src/modules/github.xql
+++ b/src/modules/github.xql
@@ -120,8 +120,21 @@ declare function github:get-changes ($collection-config as map(*)) as map(*) {
return github:get-commit-files($collection-config, $sha)?*
(: aggregate file changes :)
- return fold-left($changes, map{}, github:aggregate-filechanges#2)
-
+ let $aggregated := fold-left($changes, map{}, github:aggregate-filechanges#2)
+ let $filtered := fold-left($aggregated?new, map{}, function($res, $next) {
+ if (
+ $next = ("build.xml", "repo.xml", "expath-pkg.xml")
+ or starts-with($next, ".git")
+ or ends-with($next, ".xconf")
+ )
+ then map:put($res, 'ignored', ($res?ignored, $next))
+ else map:put($res, 'new', ($res?new, $next))
+ })
+ return map {
+ "del": $aggregated?del,
+ "new": $filtered?new,
+ "ignored": $filtered?ignored
+ }
};
(:~
@@ -137,14 +150,18 @@ declare function github:remove-or-ignore ($changes as map(*), $filename as xs:st
else map:put($changes, "del", ($changes?del, $filename)) (: add document to be removed :)
};
+(: unhandled cases: "copied", "changed", "unchanged" :)
declare function github:aggregate-filechanges ($changes as map(*), $next as map(*)) as map(*) {
switch ($next?status)
case "added" (: fall-through :)
case "modified" return
- map:put($changes, "new", ($changes?new, $next?filename))
+ if ($next?filename = $changes?new) (: file already in new list :)
+ then $changes
+ else map:put($changes, "new", ($changes?new, $next?filename))
case "renamed" return
- github:remove-or-ignore($changes, $next?previous_filename)
- => map:put("new", ($changes?new, $next?filename))
+ github:remove-or-ignore(
+ map:put($changes, "new", ($changes?new, $next?filename)),
+ $next?previous_filename)
case "removed" return
github:remove-or-ignore($changes, $next?filename)
default return
@@ -158,7 +175,8 @@ declare function github:incremental-dry($config as map(*)) {
let $changes := github:get-changes($config)
return map {
'new': array{ $changes?new },
- 'del': array{ $changes?del }
+ 'del': array{ $changes?del },
+ 'ignored': array{ $changes?ignored }
}
};