Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GH action for verifying manifest.yml #32

Merged
merged 5 commits into from
Jul 28, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
with:
path: coreMQTT
test-doxygen-zip-check:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
Expand All @@ -56,7 +56,7 @@ jobs:
libs_parent_dir_path: libraries/standard,libraries/aws
generate_zip: true
test-doxygen-non-zip-check:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v2
Expand Down Expand Up @@ -141,3 +141,24 @@ jobs:
path: ./
exclude-dirs: complexity,formatting
include-file-types: .c,.html
test-manifest-verifier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup python environment
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Checkout the FreeRTOS/FreeRTOS repository for testing action on.
uses: actions/checkout@v2
with:
repository: FreeRTOS/FreeRTOS
ref: '202107.00'
path: FreeRTOS
submodules: recursive
- name: Test manifest verifier
uses: ./manifest-verifier
with:
path: ./FreeRTOS
exclude-submodules: FreeRTOS-Plus/Test/CMock,FreeRTOS/Test/CMock/CMock,FreeRTOS/Test/litani

4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ FreeRTOS libraries.
library documentation. The memory estimates are generated by building the library with the ARM GCC
toolchain.
* **Link Verifier** - Verifies links present in source and Markdown files. Links verified include HTTP
URLs, and - for Markdown files - relative file path links and section anchors.
* **Manifest.yml Verifier** - Verifies that information of `manifest.yml` file matches the state of a repository for the presence of submodules and their commit IDs.

URLs, and - for Markdown files - relative file path links and section anchors.
30 changes: 30 additions & 0 deletions manifest-verifier/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: 'verify-manifest'
description: 'Verifies manifest.yml against missing submodule entires and stale version information'
inputs:
path:
description: 'Path to repository folder containing manifest.yml to verify.'
required: false
default: ./
exclude-submodules:
description: 'List of comma-separated relative path to submodules that should not be present in manifest.yml. Eg libraries/thirdparty/tinycbor,libraries/thirdparty/mbedtls'
required: false
default: ''
fail-on-incorrect-version:
description: 'Boolean flag to indicate if verification should fail if any submodule version in manifest.yml file is incorrect or stale.'
required: false
default: 'false'
runs:
using: "composite"
steps:
- name: Install dependencies
run: pip install -r $GITHUB_ACTION_PATH/requirements.txt
shell: bash
- name: Run verifier script
working-directory: ${{ inputs.path }}
run: |
if [[ "${{ inputs.fail-on-incorrect-version }}" == "true" ]]; then
python3 $GITHUB_ACTION_PATH/verify_manifest.py --ignore-submodule-path=${{ inputs.exclude-submodules }} --fail-on-incorrect-version
else
python3 $GITHUB_ACTION_PATH/verify_manifest.py --ignore-submodule-path=${{ inputs.exclude-submodules }}
fi
shell: bash
2 changes: 2 additions & 0 deletions manifest-verifier/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pyyaml
gitpython
118 changes: 118 additions & 0 deletions manifest-verifier/verify_manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/usr/bin/env python3

import os, sys
from yaml import load
from yaml import CLoader as Loader

from git import Repo
from argparse import ArgumentParser

REPO_PATH=''

# List of submodules excluded from manifest.yml file
IGNORE_SUBMODULES_LIST = []

# Obtain submodule path of all entries in manifest.yml file.
def read_manifest():
dict = {}

# Read YML file
path_manifest = os.path.join(REPO_PATH, 'manifest.yml')
assert os.path.exists(path_manifest), 'Missing manifest.yml'
with open(path_manifest, 'r') as fp:
manifest_data = fp.read()
yml = load(manifest_data, Loader=Loader)
assert 'dependencies' in yml, 'Manifest YML parsing error'

# Iterate over all the "dependencies" entries, verify that
# each contains entries for the following hierarchy:
# name: "<library-name>"
# version: "<version>"
# repository:
# type: "git"
# url: <library-github-url>
# path: <path-to-submodule-in-repository>
#
for dep in yml['dependencies']:
assert 'version' in dep, "Failed to parse 'version/tag' for submodule"
assert 'repository' in dep and 'path' in dep['repository'] and 'url' in dep['repository'], "Failed to parse 'repository' object for submodule"
dict[dep['name']] = (dep['repository']['path'], dep['version'])

return dict

# Generate list of submodules path in repository, excluding the
# path in IGNORES_SUBMODULES_LIST.
def get_all_submodules():
info_dict = {}
repo = Repo(REPO_PATH)
for submodule in repo.submodules:
path = submodule.abspath.replace(REPO_PATH+'/', '')
if path not in IGNORE_SUBMODULES_LIST:
#print(path,':',submodule.module().head.commit)
info_dict[path] = submodule.module().head.commit

return info_dict

if __name__ == '__main__':
parser = ArgumentParser(description='manifest.yml verifier')
parser.add_argument('--repo-root-path',
type=str,
required=None,
default=os.getcwd(),
help='Path to the repository root.')
parser.add_argument('--ignore-submodule-path',
type=str,
required=None,
help='Comma-separated list of submodules path to ignore.')
parser.add_argument('--fail-on-incorrect-versions',
action='store_true',
help='Flag to indicate script to fail for incorrect submodules versions in manifest.yml')

args = parser.parse_args()

if args.ignore_submodule_path != None:
IGNORE_SUBMODULES_LIST = args.ignore_submodule_path.split(',')

# Convert any relative path (like './') in passed argument to absolute path.
REPO_PATH = os.path.abspath(args.repo_root_path)

submodules_info_from_manifest = read_manifest()
submodule_path_from_manifest = [pair[0] for pair in submodules_info_from_manifest.values()]
submodule_path_from_manifest = sorted(submodule_path_from_manifest)

submodules_info_from_git = get_all_submodules()
submodule_path_from_git = sorted(submodules_info_from_git.keys())

print(REPO_PATH)
print('\nList of submoduled libraries being verified:', submodule_path_from_git)

# Check that manifest.yml contains entries for all submodules
# present in repository.
if submodule_path_from_manifest != submodule_path_from_git:
print('manifest.yml is missing entries for:')
# Find list of library submodules missing in manifest.yml
for git_path in submodule_path_from_git:
if git_path not in submodule_path_from_manifest:
print(git_path)
sys.exit(1)

# Verify that manifest contains correct versions of submodules pointers.
mismatch_flag = False
print('\nVerifying that manifest.yml versions are up-to-date.....')
for submodule_name, submodule_info in submodules_info_from_manifest.items():
relative_path = submodule_info[0]
manifest_commit = submodule_info[1]
submodule = Repo(REPO_PATH+'/'+relative_path)
submodule.remote('origin').fetch()
submodule.git.checkout(manifest_commit)
if (submodules_info_from_git[relative_path] != submodule.head.commit):
print('manifest.yml does not have correct commit ID for', submodule_name,'manifest Commit=(',manifest_commit, submodule.head.commit,') Actual Commit=',submodules_info_from_git[relative_path])
mismatch_flag = True

if mismatch_flag and args.fail_on_incorrect_versions:
sys.exit(1)

print('\nmanifest.yml file has been verified!')
sys.exit(0)