From 233708b651766c8747b29f4ec3130ba826cc3fdb Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 7 Oct 2022 15:38:18 -0500 Subject: [PATCH 01/11] Update controller.py --- lib/biokbase/catalog/controller.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/biokbase/catalog/controller.py b/lib/biokbase/catalog/controller.py index f219f10..19fada0 100644 --- a/lib/biokbase/catalog/controller.py +++ b/lib/biokbase/catalog/controller.py @@ -1226,6 +1226,7 @@ def is_admin(self, username, token): def version(self): return biokbase.catalog.version.CATALOG_VERSION + @log def log_exec_stats(self, username, token, user_id, app_module_name, app_id, func_module_name, func_name, git_commit_hash, creation_time, exec_start_time, finish_time, is_error, job_id): @@ -1236,6 +1237,10 @@ def log_exec_stats(self, username, token, user_id, app_module_name, app_id, func is_error, job_id) parts = datetime.fromtimestamp(creation_time).isocalendar() week_time_range = str(parts[0]) + "-W" + str(parts[1]) + + aesa1 = "".join(app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, "a", "*", "then", "w", week_time_range) + logging.info(aesa1) + self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, "a", "*") self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, From 7661ea9a54946b3759b096cc7d3e56eb0f58faed Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 7 Oct 2022 15:38:55 -0500 Subject: [PATCH 02/11] Create pr_build.yml --- .github/workflows/pr_build.yml | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/pr_build.yml diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml new file mode 100644 index 0000000..0fa1c46 --- /dev/null +++ b/.github/workflows/pr_build.yml @@ -0,0 +1,43 @@ +--- +name: Pull Request Build, Tag, & Push +on: + pull_request: + branches: + - develop + - main + - master + types: + - opened + - reopened + - synchronize + - closed +jobs: + build-develop-open: + if: github.base_ref == 'develop' && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_build.yml@main + secrets: inherit + build-develop-merge: + if: github.base_ref == 'develop' && github.event.pull_request.merged == true + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}-develop' + tags: pr-${{ github.event.number }},latest + secrets: inherit + build-main-open: + if: (github.base_ref == 'main' || github.base_ref == 'master') && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: pr-${{ github.event.number }} + secrets: inherit + build-main-merge: + if: (github.base_ref == 'main' || github.base_ref == 'master') && github.event.pull_request.merged == true + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: pr-${{ github.event.number }},latest-rc + secrets: inherit + trivy-scans: + if: (github.base_ref == 'develop' || github.base_ref == 'main' || github.base_ref == 'master' ) && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_trivy-scans.yml@main + secrets: inherit From cd61d0c114f7bcc34ec178e046a369be7cca63f8 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 7 Oct 2022 15:39:18 -0500 Subject: [PATCH 03/11] Create release-main.yml --- .github/workflows/release-main.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/release-main.yml diff --git a/.github/workflows/release-main.yml b/.github/workflows/release-main.yml new file mode 100644 index 0000000..a254678 --- /dev/null +++ b/.github/workflows/release-main.yml @@ -0,0 +1,25 @@ +--- +name: Release - Build & Push Image +on: + release: + branches: + - main + - master + types: [ published ] +jobs: + check-source-branch: + uses: kbase/.github/.github/workflows/reusable_validate-branch.yml@main + with: + build_branch: '${{ github.event.release.target_commitish }}' + validate-release-tag: + needs: check-source-branch + uses: kbase/.github/.github/workflows/reusable_validate-release-tag.yml@main + with: + release_tag: '${{ github.event.release.tag_name }}' + build-push: + needs: validate-release-tag + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: '${{ github.event.release.tag_name }},latest' + secrets: inherit From c701a39d49b801e17e148d3e99869f29cd05c4b0 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 7 Oct 2022 15:40:02 -0500 Subject: [PATCH 04/11] Create manual-build.yml --- .github/workflows/manual-build.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/manual-build.yml diff --git a/.github/workflows/manual-build.yml b/.github/workflows/manual-build.yml new file mode 100644 index 0000000..944f903 --- /dev/null +++ b/.github/workflows/manual-build.yml @@ -0,0 +1,11 @@ +--- +name: Manual Build & Push +on: + workflow_dispatch: +jobs: + build-push: + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}-develop' + tags: br-${{ github.ref_name }} + secrets: inherit From f7df4ac7b257f7525f1ddff2e318f7bac8ca5d2d Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 7 Oct 2022 18:22:03 -0500 Subject: [PATCH 05/11] Update db.py --- lib/biokbase/catalog/db.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/biokbase/catalog/db.py b/lib/biokbase/catalog/db.py index d3ba841..409a9bf 100644 --- a/lib/biokbase/catalog/db.py +++ b/lib/biokbase/catalog/db.py @@ -1116,7 +1116,9 @@ def add_exec_stats_raw(self, user_id, app_module_name, app_id, func_module_name, def add_exec_stats_apps(self, app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, type, time_range): + print("Going to return if no app id") if not app_id: + print("Sorry, not going to add exec stats apps for " + app_module_name) return full_app_id = app_id if app_module_name: From 7d47f2fed8a5191396e1ea5cbdceb73cd5b74362 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Mon, 10 Oct 2022 12:39:41 -0500 Subject: [PATCH 06/11] Update controller.py --- lib/biokbase/catalog/controller.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/biokbase/catalog/controller.py b/lib/biokbase/catalog/controller.py index 19fada0..6a41932 100644 --- a/lib/biokbase/catalog/controller.py +++ b/lib/biokbase/catalog/controller.py @@ -1238,9 +1238,6 @@ def log_exec_stats(self, username, token, user_id, app_module_name, app_id, func parts = datetime.fromtimestamp(creation_time).isocalendar() week_time_range = str(parts[0]) + "-W" + str(parts[1]) - aesa1 = "".join(app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, "a", "*", "then", "w", week_time_range) - logging.info(aesa1) - self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, "a", "*") self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, From 21139c64ec6e1c93fced192a7358e76526a0a5d2 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Mon, 10 Oct 2022 12:40:18 -0500 Subject: [PATCH 07/11] Update db.py --- lib/biokbase/catalog/db.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/biokbase/catalog/db.py b/lib/biokbase/catalog/db.py index 409a9bf..d3ba841 100644 --- a/lib/biokbase/catalog/db.py +++ b/lib/biokbase/catalog/db.py @@ -1116,9 +1116,7 @@ def add_exec_stats_raw(self, user_id, app_module_name, app_id, func_module_name, def add_exec_stats_apps(self, app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, type, time_range): - print("Going to return if no app id") if not app_id: - print("Sorry, not going to add exec stats apps for " + app_module_name) return full_app_id = app_id if app_module_name: From 7642a0c0737aa60057d552f2b0eb96ee43c2cd92 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Tue, 27 Dec 2022 14:23:33 -0600 Subject: [PATCH 08/11] Update pr_build.yml --- .github/workflows/pr_build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 0fa1c46..53b0d18 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -37,7 +37,7 @@ jobs: name: '${{ github.event.repository.name }}' tags: pr-${{ github.event.number }},latest-rc secrets: inherit - trivy-scans: - if: (github.base_ref == 'develop' || github.base_ref == 'main' || github.base_ref == 'master' ) && github.event.pull_request.merged == false - uses: kbase/.github/.github/workflows/reusable_trivy-scans.yml@main - secrets: inherit +# trivy-scans: +# if: (github.base_ref == 'develop' || github.base_ref == 'main' || github.base_ref == 'master' ) && github.event.pull_request.merged == false +# uses: kbase/.github/.github/workflows/reusable_trivy-scans.yml@main +# secrets: inherit From 75769b38e3c8464d3b8ae47a18425ffd8284de3f Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 1 Mar 2024 21:27:40 -0600 Subject: [PATCH 09/11] Update controller.py --- lib/biokbase/catalog/controller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/biokbase/catalog/controller.py b/lib/biokbase/catalog/controller.py index 6a41932..6272dbd 100644 --- a/lib/biokbase/catalog/controller.py +++ b/lib/biokbase/catalog/controller.py @@ -116,7 +116,6 @@ def __init__(self, config): 'specified in the config') self.nms = NarrativeMethodStore(self.nms_url, token=self.nms_token) - @log def register_repo(self, params, username, token): if 'git_url' not in params: From 2054b0da894eb7cc523b7a74adc578beff467b51 Mon Sep 17 00:00:00 2001 From: bio-boris Date: Fri, 1 Mar 2024 21:29:39 -0600 Subject: [PATCH 10/11] Update controller.py --- lib/biokbase/catalog/controller.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/biokbase/catalog/controller.py b/lib/biokbase/catalog/controller.py index 6272dbd..f219f10 100644 --- a/lib/biokbase/catalog/controller.py +++ b/lib/biokbase/catalog/controller.py @@ -116,6 +116,7 @@ def __init__(self, config): 'specified in the config') self.nms = NarrativeMethodStore(self.nms_url, token=self.nms_token) + @log def register_repo(self, params, username, token): if 'git_url' not in params: @@ -1225,7 +1226,6 @@ def is_admin(self, username, token): def version(self): return biokbase.catalog.version.CATALOG_VERSION - @log def log_exec_stats(self, username, token, user_id, app_module_name, app_id, func_module_name, func_name, git_commit_hash, creation_time, exec_start_time, finish_time, is_error, job_id): @@ -1236,7 +1236,6 @@ def log_exec_stats(self, username, token, user_id, app_module_name, app_id, func is_error, job_id) parts = datetime.fromtimestamp(creation_time).isocalendar() week_time_range = str(parts[0]) + "-W" + str(parts[1]) - self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, finish_time, is_error, "a", "*") self.db.add_exec_stats_apps(app_module_name, app_id, creation_time, exec_start_time, From dd630ce109c915c05e4f97d752eb16b4ff7669ed Mon Sep 17 00:00:00 2001 From: Sijie Xiang Date: Mon, 16 Dec 2024 16:51:36 -0800 Subject: [PATCH 11/11] add GHA test.yml, codeql, and dependabot.yml (#136) --- .github/codeql.yml | 52 ++++++++++++++++++ .github/dependabot.yml | 14 +++++ .github/workflows/test.yml | 88 ++++++++++++++++++++++++++++++ .travis.yml | 40 -------------- lib/biokbase/catalog/registrar.py | 2 +- requirements.txt | 2 +- test/core_registration_test.py | 1 + test/local_function_module_test.py | 10 ++-- 8 files changed, 162 insertions(+), 47 deletions(-) create mode 100644 .github/codeql.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml diff --git a/.github/codeql.yml b/.github/codeql.yml new file mode 100644 index 0000000..0f2f982 --- /dev/null +++ b/.github/codeql.yml @@ -0,0 +1,52 @@ +name: "Code scanning - action" + +on: + push: + pull_request: + schedule: + - cron: '0 19 * * 0' + +jobs: + CodeQL-Build: + + # CodeQL runs on ubuntu-latest and windows-latest + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..fe38181 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: +- package-ecosystem: docker + directory: "/" + schedule: + interval: weekly + time: '11:00' + open-pull-requests-limit: 10 +- package-ecosystem: pip + directory: "/" + schedule: + interval: weekly + time: '11:00' + open-pull-requests-limit: 10 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..6a4109b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,88 @@ +name: KBase Catalog test + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + push: + # run workflow when merging to main or develop + branches: + - main + - master + - develop + +jobs: + catalog_tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - python-version: '3.7' + mongo-version: '3.6' + # - python-version: '3.7' + # mongo-version: '7.0.4' + services: + mongo: + image: mongo:${{matrix.mongo-version}} + ports: + - 27017:27017 + options: --name mongo${{matrix.mongo-version}} + + steps: + - name: Repo checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{matrix.python-version}} + + - name: Install dependencies and set up test config + shell: bash + env: + KBASE_CI_TOKEN: ${{ secrets.KBASE_CI_TOKEN }} + ADMIN_USER: ${{ secrets.KBASE_BOT_USER_CI }} + + run: | + + # test mongo connection + curl http://localhost:27017 + returncode=$? + if [ $returncode != 0 ]; then exit $returncode; fi + + # set HOMEDIR + export HOMEDIR=`pwd` + + # move to parent dir to install binaries etc + cd .. + + # setup kb-sdk + mkdir -p $(pwd)/bin + docker run ghcr.io/kbase/kb_sdk_patch-develop:br-0.0.4 genscript > $(pwd)/bin/kb-sdk + chmod 755 $(pwd)/bin/kb-sdk + export PATH=$(pwd)/bin:$PATH + + # install catalog dependencies + cd $HOMEDIR + pip install -r requirements.txt + + # setup test config + cp -n test/test.cfg.example test/test.cfg + sed -i "s#^nms-admin-token.*#nms-admin-token=$KBASE_CI_TOKEN#" test/test.cfg + sed -i "s#^method-spec-admin-users.*#method-spec-admin-users=$ADMIN_USER#" test/test.cfg + + - name: Run tests + shell: bash + run: make test + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index beae4e4..0000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -sudo: required -language: python -python: - - '3.6' -services: - - docker - -before_install: - #- docker run -d -p 5000:5000 --name registry registry:2 - - docker run -p 27017:27017 --name mongo3.6 -d mongo:3.6 - - sleep 3 - - mongo --eval "printjson(db.serverStatus())" - - sudo apt install ant - - mkdir $(pwd)/bin - - docker run kbase/kb-sdk genscript > $(pwd)/bin/kb-sdk - - chmod 755 $(pwd)/bin/kb-sdk - -install: - - pip install -r requirements.txt - - pip install python-coveralls - - pip install coverage - - cd .. - - git clone https://github.com/kbase/jars - - docker images - - export PATH=$(pwd)/bin:$PATH - - cd catalog - -script: - - cp -n test/test.cfg.example test/test.cfg - - sed -i 's/^nms-admin-toke.*/nms-admin-token = '$NMS_ADMIN_TOKEN'/' test/test.cfg - - make test - -after_success: - - mv test/.coverage . - - coveralls - -env: - global: - - secure: "o0xBDxPBVpqmezRtuDf4gdFYUIlFReH3kV1BOx75taCqzMvsvNnIDHzLITFTvGhNBzOT/hG/eEVDiKx/bnFoq0HJWsKYeKahOsiMlFavIR5jTIdMLq2zbZDkxV/+e0HoRRArWj53NV9wx0pWTv3DYxqbzPR1uu5letxdWnY3DQXggspcnJuAVYGn6LtgNM7MV+h3jdHe/E61LkwMff8KwpoBF+64AKbsZv1ddcFo0gbo9Z9CjLeBq4le2TwziLeuUYV885mPsRCvhToRMzpeVlbiNkzf7w5oh5g3FFsPOOYFeu22a+RrmKoM0hv9/pTTYG0G8/ylzOMIKWJvVrOJYptRvyQKmpmdcN7/CPYIQkf6ZBp0rP6G30Q2xt49+ST40ko1L0jhL42FfwXSmuNjklRMZAjpMNRZM2fIazEhDw3ND9l4T6HZnIwr/SQvKCs4rYBjqmSLo/dMISiFDLjWpMor5ew9fpZSLwJcPglGT0Anh4OIZUY2JGlO4TuOkq3m5kvXjjKLBc3Domd10c+DLfkldwwt6uqShsDECqFwSMf/liPEtLfi+03djrWvP26QeiEKL93ujAMS4oXAYxdquOy2Ib9ihd3XWTJzYc4s1H7furYqAbQDAhU0Dx3nvcyEsu5djdRAFe0eKUdjdAqsMAxe84h/EHZHrlE+KOOZo8s=" - - MONGODB_VERSION=2.7 diff --git a/lib/biokbase/catalog/registrar.py b/lib/biokbase/catalog/registrar.py index b10d158..d8226cb 100644 --- a/lib/biokbase/catalog/registrar.py +++ b/lib/biokbase/catalog/registrar.py @@ -252,7 +252,7 @@ def sanity_checks_and_parse(self, basedir, git_commit_hash): with codecs.open(os.path.join(basedir, yaml_filename), 'r', "utf-8", errors='ignore') as kb_yaml_file: kb_yaml_string = kb_yaml_file.read() - self.kb_yaml = yaml.load(kb_yaml_string) + self.kb_yaml = yaml.safe_load(kb_yaml_string) self.log('=====kbase.yaml parse:') self.log(pprint.pformat(self.kb_yaml)) self.log('=====end kbase.yaml') diff --git a/requirements.txt b/requirements.txt index e319061..b94e0b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -pymongo==3.7 +pymongo==3.10 docker>=3.5 gitpython pyyaml diff --git a/test/core_registration_test.py b/test/core_registration_test.py index e222bb8..c1e63c7 100644 --- a/test/core_registration_test.py +++ b/test/core_registration_test.py @@ -37,6 +37,7 @@ def test_full_module_lifecycle(self): self.assertEqual(state['registration'], 'complete') # (3) check the log + sleep(3) # sleep to make sure the catalog db gets the final log messages parsed_log = self.catalog.get_parsed_build_log(self.cUtil.anonymous_ctx(), {'registration_id': registration_id})[0] self.assertEqual(parsed_log['registration'], 'complete') diff --git a/test/local_function_module_test.py b/test/local_function_module_test.py index bf510e5..0b17303 100644 --- a/test/local_function_module_test.py +++ b/test/local_function_module_test.py @@ -16,7 +16,7 @@ def test_local_function_module(self): # assume test user is already approved as a developer # (1) register the test repo giturl = self.cUtil.get_test_repo_1() - githash = 'a01e1a20b9c504a0136c75323b00b1cd4c7f7970' # branch local_method_module + githash = 'a8915afe6811de9199897d710348befad8f6f7ab' # branch local_method_module registration_id = self.catalog.register_repo(self.cUtil.user_ctx(), {'git_url': giturl, 'git_commit_hash': githash})[0] @@ -59,7 +59,7 @@ def test_local_function_module(self): self.assertEqual(len(specs), 1) info = specs[0]['info'] self.assertEqual(info['function_id'], 'powerpoint_to_genome') - self.assertEqual(info['git_commit_hash'], 'a01e1a20b9c504a0136c75323b00b1cd4c7f7970') + self.assertEqual(info['git_commit_hash'], 'a8915afe6811de9199897d710348befad8f6f7ab') self.assertEqual(info['module_name'], 'GenomeToPowerpointConverter') self.assertEqual(info['name'], 'Powerpoint to Genome') self.assertEqual(info['release_tag'], ['dev']) @@ -122,7 +122,7 @@ def test_local_function_module(self): self.assertEqual(len(specs), 1) info = specs[0]['info'] self.assertEqual(info['function_id'], 'powerpoint_to_genome') - self.assertEqual(info['git_commit_hash'], 'a01e1a20b9c504a0136c75323b00b1cd4c7f7970') + self.assertEqual(info['git_commit_hash'], 'a8915afe6811de9199897d710348befad8f6f7ab') self.assertEqual(info['module_name'], 'GenomeToPowerpointConverter') self.assertEqual(info['name'], 'Powerpoint to Genome') self.assertEqual(info['release_tag'], ['beta', 'dev']) @@ -179,12 +179,12 @@ def test_local_function_module(self): # make sure we can fetch it by commit hash specs = self.catalog.get_local_function_details(self.cUtil.user_ctx(), {'functions': [ {'module_name': 'GenomeTopowerpointConverter', 'function_id': 'powerpoint_to_genome', - 'git_commit_hash': 'a01e1a20b9c504a0136c75323b00b1cd4c7f7970'}]})[0] + 'git_commit_hash': 'a8915afe6811de9199897d710348befad8f6f7ab'}]})[0] self.assertEqual(len(specs), 1) info = specs[0]['info'] self.assertEqual(info['function_id'], 'powerpoint_to_genome') - self.assertEqual(info['git_commit_hash'], 'a01e1a20b9c504a0136c75323b00b1cd4c7f7970') + self.assertEqual(info['git_commit_hash'], 'a8915afe6811de9199897d710348befad8f6f7ab') self.assertEqual(info['module_name'], 'GenomeToPowerpointConverter') self.assertEqual(info['name'], 'Powerpoint to Genome') self.assertEqual(info['release_tag'], ['release', 'beta', 'dev'])