You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2023/10/18 13:14:45 UTC
[incubator-opendal] branch main updated: feat(bindings/java): Migrate behavior tests to new Workflow Planner (#3341)
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new e80e32c14 feat(bindings/java): Migrate behavior tests to new Workflow Planner (#3341)
e80e32c14 is described below
commit e80e32c14f3916dbcd592a14493d9603029cbce5
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Wed Oct 18 21:14:39 2023 +0800
feat(bindings/java): Migrate behavior tests to new Workflow Planner (#3341)
* Add java support
Signed-off-by: Xuanwo <gi...@xuanwo.io>
* Migrate redis
Signed-off-by: Xuanwo <gi...@xuanwo.io>
* Fix typo
Signed-off-by: Xuanwo <gi...@xuanwo.io>
* Fix binding java
Signed-off-by: Xuanwo <gi...@xuanwo.io>
* Fix redis
Signed-off-by: Xuanwo <gi...@xuanwo.io>
* Fix workflow changes
Signed-off-by: Xuanwo <gi...@xuanwo.io>
---------
Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
.../action.yaml | 15 +-
.github/actions/behavior_test_core/action.yaml | 1 -
.github/scripts/behavior_test/plan.py | 186 ++++++++++++++++-----
.github/scripts/behavior_test/test_plan.py | 12 +-
.../redis/redis/action.yml} | 45 ++---
.../redis/redis_with_cluster/action.yml} | 45 ++---
.github/workflows/behavior_test.yml | 13 ++
...est_core.yml => behavior_test_binding_java.yml} | 4 +-
.github/workflows/behavior_test_core.yml | 2 +-
.github/workflows/service_test_redis.yml | 68 --------
.github/workflows/service_test_s3.yml | 28 ----
11 files changed, 213 insertions(+), 206 deletions(-)
diff --git a/.github/actions/behavior_test_core/action.yaml b/.github/actions/behavior_test_binding_java/action.yaml
similarity index 78%
copy from .github/actions/behavior_test_core/action.yaml
copy to .github/actions/behavior_test_binding_java/action.yaml
index ca27b8d3f..635b109df 100644
--- a/.github/actions/behavior_test_core/action.yaml
+++ b/.github/actions/behavior_test_binding_java/action.yaml
@@ -31,20 +31,19 @@ runs:
- name: Setup
shell: bash
run: |
- mkdir -p ./dynamic_test_core &&
- cat <<EOF >./dynamic_test_core/action.yml
+ mkdir -p ./dynamic_test_binding_java &&
+ cat <<EOF >./dynamic_test_binding_java/action.yml
runs:
using: composite
steps:
- - name: Setup Test Core
+ - name: Setup Test
uses: ./.github/services/${{ inputs.service }}/${{ inputs.setup }}
- - name: Run Test Core
+ - name: Run Test Binding Java
shell: bash
- working-directory: core
- run: cargo nextest run behavior --features ${{ inputs.feature }}
+ working-directory: bindings/java
+ run: ./mvnw test -Dtest="behavior.*Test" -Dcargo-build.features=${{ inputs.feature }}
env:
OPENDAL_TEST: ${{ inputs.service }}
EOF
- name: Run
- id: run
- uses: ./dynamic_test_core
+ uses: ./dynamic_test_binding_java
diff --git a/.github/actions/behavior_test_core/action.yaml b/.github/actions/behavior_test_core/action.yaml
index ca27b8d3f..69674e0a7 100644
--- a/.github/actions/behavior_test_core/action.yaml
+++ b/.github/actions/behavior_test_core/action.yaml
@@ -46,5 +46,4 @@ runs:
OPENDAL_TEST: ${{ inputs.service }}
EOF
- name: Run
- id: run
uses: ./dynamic_test_core
diff --git a/.github/scripts/behavior_test/plan.py b/.github/scripts/behavior_test/plan.py
index 9040d1a60..ff3f5ae25 100755
--- a/.github/scripts/behavior_test/plan.py
+++ b/.github/scripts/behavior_test/plan.py
@@ -19,7 +19,9 @@
import sys
import json
import os
+import re
from pathlib import Path
+from dataclasses import dataclass, field
# The path for current script.
SCRIPT_PATH = Path(__file__).parent.absolute()
@@ -29,13 +31,14 @@ GITHUB_DIR = SCRIPT_PATH.parent.parent
PROJECT_DIR = GITHUB_DIR.parent
-def get_provided_cases():
+def provided_cases():
root_dir = f"{GITHUB_DIR}/services"
cases = [
{
"service": service,
"setup": setup,
+ "feature": "services-{}".format(service.replace("_", "-")),
"content": Path(
os.path.join(root_dir, service, setup, "action.yml")
).read_text(),
@@ -50,64 +53,158 @@ def get_provided_cases():
if not os.getenv("GITHUB_HAS_SECRETS") == "true":
cases[:] = [v for v in cases if "secrets" not in v["content"]]
- return cases
+ # Remove content from cases.
+ cases = [
+ {
+ "setup": v["setup"],
+ "service": v["service"],
+ "feature": v["feature"],
+ }
+ for v in cases
+ ]
+ # Make sure the order is stable.
+ sorted_cases = sorted(cases, key=lambda x: (x["service"], x["setup"]))
+ return sorted_cases
+
+
+@dataclass
+class Hint:
+ # Is core affected?
+ core: bool = field(default=False, init=False)
+ # Is binding java affected?
+ binding_java: bool = field(default=False, init=False)
+
+ # Should we run all services test?
+ all_service: bool = field(default=False, init=False)
+ # affected services set.
+ services: set = field(default_factory=set, init=False)
+
+
+def calculate_hint(changed_files):
+ hint = Hint()
+
+ # Remove all files that ends with `.md`
+ changed_files = [f for f in changed_files if not f.endswith(".md")]
+
+ service_pattern = r"core/src/services/([^/]+)/"
+ test_pattern = r".github/services/([^/]+)/"
+
+ for p in changed_files:
+ # workflow behavior tests affected
+ if p == ".github/workflows/behavior_test.yml":
+ hint.core = True
+ hint.binding_java = True
+ hint.all_service = True
+ if p == ".github/workflows/behavior_test_core.yml":
+ hint.core = True
+ hint.all_service = True
+ if p == ".github/workflows/behavior_test_binding_java.yml":
+ hint.binding_java = True
+ hint.all_service = True
+
+ # core affected
+ if p.startswith("core/") and not p.startswith("core/src/services/"):
+ hint.core = True
+ hint.binding_java = True
+ hint.all_service = True
+
+ # binding java affected.
+ if p.startswith("bindings/java/"):
+ hint.binding_java = True
+ hint.all_service = True
+
+ # core service affected
+ match = re.search(service_pattern, p)
+ if match:
+ hint.core = True
+ hint.binding_java = True
+ hint.services.add(match.group(1))
+
+ # core test affected
+ match = re.search(test_pattern, p)
+ if match:
+ hint.core = True
+ hint.binding_java = True
+ hint.services.add(match.group(1))
+
+ return hint
+
+
+# unique_cases is used to only one setup for each service.
+#
+# We need this because we have multiple setup for each service and they have already been
+# tested by `core` workflow. So we can only test unique setup for each service for bindings.
+#
+# We make sure that we return the first setup for each service in alphabet order.
+def unique_cases(cases):
+ ucases = {}
+ for case in cases:
+ service = case["service"]
+ if service not in ucases:
+ ucases[service] = case
+
+ # Convert the dictionary back to a list if needed
+ return list(ucases.values())
-def calculate_core_cases(cases, changed_files):
- # If any of the core workflow changed, we will run all cases.
- for p in [
- ".github/workflows/core_test.yml",
- ".github/workflows/test_planner.yml",
- ".github/actions/test-core",
- ]:
- if p in changed_files:
- return cases
+def generate_core_cases(cases, hint):
# Always run all tests if it is a push event.
if os.getenv("GITHUB_IS_PUSH") == "true":
return cases
- # If any of the core files changed, we will run all cases.
- if any(
- p.startswith("core/")
- and not p.startswith("core/src/services/")
- and not p.endswith(".md")
- for p in changed_files
- ):
+ # Return empty if core is False
+ if not hint.core:
+ return []
+
+ # Return all services if all_service is True
+ if hint.all_service:
+ return cases
+
+ # Filter all cases that not shown un in changed files
+ cases = [v for v in cases if v["service"] in hint.services]
+ return cases
+
+
+def generate_binding_java_cases(cases, hint):
+ cases = unique_cases(cases)
+
+ # Always run all tests if it is a push event.
+ if os.getenv("GITHUB_IS_PUSH") == "true":
return cases
- if any(p.startswith("core/tests/") for p in changed_files):
+
+ # Return empty if core is False
+ if not hint.binding_java:
+ return []
+
+ # Return all services if all_service is True
+ if hint.all_service:
return cases
# Filter all cases that not shown un in changed files
- cases = [v for v in cases if any(v["service"] in p for p in changed_files)]
+ cases = [v for v in cases if v["service"] in hint.services]
return cases
-# Context is the github context: https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
def plan(changed_files):
- # TODO: add bindings/java, bindings/python in the future.
- components = ["core"]
- cases = get_provided_cases()
+ cases = provided_cases()
+ hint = calculate_hint(changed_files)
- core_cases = calculate_core_cases(cases, changed_files)
+ core_cases = generate_core_cases(cases, hint)
+ binding_java_cases = generate_binding_java_cases(cases, hint)
- jobs = {}
+ jobs = {
+ "components": {
+ "core": False,
+ "binding_java": False,
+ },
+ "core": [],
+ "binding_java": [],
+ }
if len(core_cases) > 0:
- jobs["components"] = {"core": True}
- jobs["core"] = [
- {
- "os": "ubuntu-latest",
- "cases": [
- {
- "setup": v["setup"],
- "service": v["service"],
- "feature": "services-{}".format(v["service"].replace("_", "-")),
- }
- for v in core_cases
- ],
- },
- ]
+ jobs["components"]["core"] = True
+ jobs["core"].append({"os": "ubuntu-latest", "cases": core_cases})
# fs is the only services need to run upon windows, let's hard code it here.
if "fs" in [v["service"] for v in core_cases]:
@@ -120,12 +217,15 @@ def plan(changed_files):
}
)
+ if len(binding_java_cases) > 0:
+ jobs["components"]["binding_java"] = True
+ jobs["binding_java"].append(
+ {"os": "ubuntu-latest", "cases": binding_java_cases}
+ )
+
return jobs
-# For quick test:
-#
-# ./scripts/workflow_planner.py PATH
if __name__ == "__main__":
changed_files = sys.argv[1:]
result = plan(changed_files)
diff --git a/.github/scripts/behavior_test/test_plan.py b/.github/scripts/behavior_test/test_plan.py
index 090a56d14..021001e44 100644
--- a/.github/scripts/behavior_test/test_plan.py
+++ b/.github/scripts/behavior_test/test_plan.py
@@ -22,7 +22,10 @@ from plan import plan
class BehaviorTestPlan(unittest.TestCase):
def test_empty(self):
result = plan([])
- self.assertEqual(result, {})
+ self.assertEqual(result["components"]["core"], False)
+ self.assertEqual(result["components"]["binding_java"], False)
+ self.assertEqual(len(result["core"]), 0)
+ self.assertEqual(len(result["binding_java"]), 0)
def test_core_cargo_toml(self):
result = plan(["core/Cargo.toml"])
@@ -39,6 +42,13 @@ class BehaviorTestPlan(unittest.TestCase):
# Should not contain s3
self.assertFalse("s3" in cases)
+ def test_binding_java(self):
+ result = plan(["bindings/java/pom.xml"])
+ self.assertFalse(result["components"]["core"])
+ self.assertTrue(len(result["core"]) == 0)
+ self.assertTrue(result["components"]["binding_java"])
+ self.assertTrue(len(result["binding_java"]) > 0)
+
if __name__ == "__main__":
unittest.main()
diff --git a/.github/scripts/behavior_test/test_plan.py b/.github/services/redis/redis/action.yml
similarity index 50%
copy from .github/scripts/behavior_test/test_plan.py
copy to .github/services/redis/redis/action.yml
index 090a56d14..472329b33 100644
--- a/.github/scripts/behavior_test/test_plan.py
+++ b/.github/services/redis/redis/action.yml
@@ -15,30 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-import unittest
-from plan import plan
-
-
-class BehaviorTestPlan(unittest.TestCase):
- def test_empty(self):
- result = plan([])
- self.assertEqual(result, {})
-
- def test_core_cargo_toml(self):
- result = plan(["core/Cargo.toml"])
- self.assertTrue(result["components"]["core"])
-
- def test_core_services_fs(self):
- result = plan(["core/src/services/fs/mod.rs"])
- self.assertTrue(result["components"]["core"])
- self.assertTrue(len(result["core"]) > 0)
-
- cases = [v["service"] for v in result["core"][0]["cases"]]
- # Should not contain fs
- self.assertTrue("fs" in cases)
- # Should not contain s3
- self.assertFalse("s3" in cases)
-
-
-if __name__ == "__main__":
- unittest.main()
+name: redis
+description: 'Behavior test for redis'
+
+runs:
+ using: "composite"
+ steps:
+ - name: Setup Redis Server
+ shell: bash
+ working-directory: fixtures/redis
+ run: docker-compose -f docker-compose-redis.yml up -d
+ - name: Setup
+ shell: bash
+ run: |
+ cat << EOF >> $GITHUB_ENV
+ OPENDAL_REDIS_ENDPOINT=tcp://127.0.0.1:6379
+ OPENDAL_REDIS_ROOT=/
+ OPENDAL_REDIS_DB=0
+ EOF
diff --git a/.github/scripts/behavior_test/test_plan.py b/.github/services/redis/redis_with_cluster/action.yml
similarity index 50%
copy from .github/scripts/behavior_test/test_plan.py
copy to .github/services/redis/redis_with_cluster/action.yml
index 090a56d14..4caeb85c3 100644
--- a/.github/scripts/behavior_test/test_plan.py
+++ b/.github/services/redis/redis_with_cluster/action.yml
@@ -15,30 +15,21 @@
# specific language governing permissions and limitations
# under the License.
-import unittest
-from plan import plan
-
-
-class BehaviorTestPlan(unittest.TestCase):
- def test_empty(self):
- result = plan([])
- self.assertEqual(result, {})
-
- def test_core_cargo_toml(self):
- result = plan(["core/Cargo.toml"])
- self.assertTrue(result["components"]["core"])
-
- def test_core_services_fs(self):
- result = plan(["core/src/services/fs/mod.rs"])
- self.assertTrue(result["components"]["core"])
- self.assertTrue(len(result["core"]) > 0)
-
- cases = [v["service"] for v in result["core"][0]["cases"]]
- # Should not contain fs
- self.assertTrue("fs" in cases)
- # Should not contain s3
- self.assertFalse("s3" in cases)
-
-
-if __name__ == "__main__":
- unittest.main()
+name: redis_with_cluster
+description: 'Behavior test for redis with cluster'
+
+runs:
+ using: "composite"
+ steps:
+ - name: Setup Redis Cluster
+ shell: bash
+ working-directory: fixtures/redis
+ run: docker-compose -f docker-compose-redis-cluster.yml up -d
+ - name: Setup
+ shell: bash
+ run: |
+ cat << EOF >> $GITHUB_ENV
+ OPENDAL_REDIS_CLUSTER_ENDPOINTS=redis://127.0.0.1:6380/,redis://127.0.0.1:6381/,redis://127.0.0.1:6382/,redis://127.0.0.1:6383/,redis://127.0.0.1:6384/,redis://127.0.0.1:6385/
+ OPENDAL_REDIS_ROOT=/test/opendal
+ OPENDAL_REDIS_DB=0
+ EOF
diff --git a/.github/workflows/behavior_test.yml b/.github/workflows/behavior_test.yml
index a4b2b240d..364eba63b 100644
--- a/.github/workflows/behavior_test.yml
+++ b/.github/workflows/behavior_test.yml
@@ -89,3 +89,16 @@ jobs:
with:
os: ${{ matrix.os }}
cases: ${{ toJson(matrix.cases) }}
+
+ test_binding_java:
+ name: binding_java / ${{ matrix.os }}
+ needs: [plan]
+ if: fromJson(needs.plan.outputs.plan).components.binding_java
+ secrets: inherit
+ strategy:
+ matrix:
+ include: ${{ fromJson(needs.plan.outputs.plan).binding_java }}
+ uses: ./.github/workflows/behavior_test_binding_java.yml
+ with:
+ os: ${{ matrix.os }}
+ cases: ${{ toJson(matrix.cases) }}
diff --git a/.github/workflows/behavior_test_core.yml b/.github/workflows/behavior_test_binding_java.yml
similarity index 95%
copy from .github/workflows/behavior_test_core.yml
copy to .github/workflows/behavior_test_binding_java.yml
index 344fe62d7..9eae4ce7c 100644
--- a/.github/workflows/behavior_test_core.yml
+++ b/.github/workflows/behavior_test_binding_java.yml
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-name: Core
+name: Behavior Test Binding Java
on:
workflow_call:
@@ -53,7 +53,7 @@ jobs:
run: echo "OP_SERVICE_ACCOUNT_TOKEN=${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}" >> $GITHUB_ENV
- name: Test Core
- uses: ./.github/actions/behavior_test_core
+ uses: ./.github/actions/behavior_test_binding_java
with:
setup: ${{ matrix.cases.setup }}
service: ${{ matrix.cases.service }}
diff --git a/.github/workflows/behavior_test_core.yml b/.github/workflows/behavior_test_core.yml
index 344fe62d7..2df44b82f 100644
--- a/.github/workflows/behavior_test_core.yml
+++ b/.github/workflows/behavior_test_core.yml
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-name: Core
+name: Behavior Test Core
on:
workflow_call:
diff --git a/.github/workflows/service_test_redis.yml b/.github/workflows/service_test_redis.yml
index eae70466f..ef8cb682e 100644
--- a/.github/workflows/service_test_redis.yml
+++ b/.github/workflows/service_test_redis.yml
@@ -39,28 +39,6 @@ concurrency:
cancel-in-progress: true
jobs:
- redis:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Setup Redis Server
- shell: bash
- working-directory: fixtures/redis
- run: docker-compose -f docker-compose-redis.yml up -d
- - name: Setup Rust toolchain
- uses: ./.github/actions/setup
- with:
- need-nextest: true
- - name: Test
- shell: bash
- working-directory: core
- run: cargo nextest run behavior --features services-redis
- env:
- OPENDAL_TEST: redis
- OPENDAL_REDIS_ENDPOINT: tcp://127.0.0.1:6379
- OPENDAL_REDIS_ROOT: /
- OPENDAL_REDIS_DB: 0
-
redis-tls:
runs-on: ubuntu-latest
steps:
@@ -91,29 +69,6 @@ jobs:
OPENDAL_REDIS_ROOT: /
OPENDAL_REDIS_DB: 0
- redis-cluster:
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
- - name: Setup Rust toolchain
- uses: ./.github/actions/setup
- with:
- need-nextest: true
- - name: Setup Redis Cluster
- shell: bash
- working-directory: fixtures/redis
- run: docker-compose -f docker-compose-redis-cluster.yml up -d
- - name: Test
- shell: bash
- working-directory: core
- run: cargo nextest run behavior --features services-redis
- env:
- OPENDAL_TEST: redis
- OPENDAL_REDIS_CLUSTER_ENDPOINTS: redis://127.0.0.1:6380/,redis://127.0.0.1:6381/,redis://127.0.0.1:6382/,redis://127.0.0.1:6383/,redis://127.0.0.1:6384/,redis://127.0.0.1:6385/
- OPENDAL_REDIS_ROOT: /test/opendal
- OPENDAL_REDIS_DB: 0
-
redis-cluster-tls:
runs-on: ubuntu-latest
@@ -193,26 +148,3 @@ jobs:
OPENDAL_REDIS_ENDPOINT: tcp://127.0.0.1:6379
OPENDAL_REDIS_ROOT: /
OPENDAL_REDIS_DB: 0
-
- java:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Rust toolchain
- uses: ./.github/actions/setup
-
- - name: Setup Redis Server
- shell: bash
- working-directory: fixtures/redis
- run: docker-compose -f docker-compose-redis.yml up -d
-
- - name: Test
- shell: bash
- working-directory: bindings/java
- run: ./mvnw test -Dtest="behavior.*Test" -Dcargo-build.features=services-redis
- env:
- OPENDAL_TEST: redis
- OPENDAL_REDIS_ENDPOINT: tcp://127.0.0.1:6379
- OPENDAL_REDIS_ROOT: /
- OPENDAL_REDIS_DB: 0
diff --git a/.github/workflows/service_test_s3.yml b/.github/workflows/service_test_s3.yml
index 27d493bc7..247080584 100644
--- a/.github/workflows/service_test_s3.yml
+++ b/.github/workflows/service_test_s3.yml
@@ -71,34 +71,6 @@ jobs:
OPENDAL_S3_ROLE_ARN: arn:aws:iam::952853449216:role/opendal-testing
OPENDAL_S3_REGION: ap-northeast-1
- java:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Setup MinIO Server
- shell: bash
- working-directory: fixtures/s3
- run: docker-compose -f docker-compose-minio.yml up -d
- - name: Setup test bucket
- env:
- AWS_ACCESS_KEY_ID: "minioadmin"
- AWS_SECRET_ACCESS_KEY: "minioadmin"
- AWS_EC2_METADATA_DISABLED: "true"
- run: aws --endpoint-url http://127.0.0.1:9000/ s3 mb s3://test
- - name: Setup Rust toolchain
- uses: ./.github/actions/setup
- - name: Test
- shell: bash
- working-directory: bindings/java
- run: ./mvnw test -Dtest="behavior.*Test"
- env:
- OPENDAL_TEST: s3
- OPENDAL_S3_BUCKET: test
- OPENDAL_S3_ENDPOINT: "http://127.0.0.1:9000"
- OPENDAL_S3_ACCESS_KEY_ID: minioadmin
- OPENDAL_S3_SECRET_ACCESS_KEY: minioadmin
- OPENDAL_S3_REGION: us-east-1
-
python:
runs-on: ubuntu-latest
steps: