Files
hunfabric/tools/check_links.py
Ludovico Magnocavallo 725f7effce Initial MVP for CI/CD (#608)
* preliminary support for wif in stage 0

* IAM wif role

* IAM wif role TODO

* add support for external SA IAM to SA module

* add name output to SA module

* separate cicd SA

* tfdoc

* GITLAB principal (untested)

* make GCS name output static

* outputs bucket

* fix stage 1 test

* tweak outputs

* tfdoc

* move wif_pool to automation variable

* add support for top-level and repository providers

* add missing boilerplate

* fix branchless principal

* initial workflow

* symlink provider template in stages

* remove service accounts from stage 0 cicd tfvars

* add cicd interface variable to resman stage

* fix cicd variable in resman stage

* better condition on outputs_location

* fix last change

* change outputs_location type

* revert outputs_location change

* split outputs in stage 0

* update ci/cd temporary notes

* rename additive IAM resource in SA module

* split outputs in stage 1

* remove unused locals

* fix stage 1 tests

* tfdoc

* Upload action files to outputs_bucket

* Fix tests and README

* rename template, streamline outputs

* local templates and gcs output for all stage 2

* add workflows to local output files

* Use lowercase WIF providers everywhere

* Bring back suffix for workflow files

* Remove unused files

* Update READMEs

* preliminary CI/CD implementation for stage 1

* fix stage 1

* stage 1 cicd

* tfdoc

* fix tests

* readme and links for cicd and wif

* refactor wif providers

* refactor cicd for stage 1

* fix stage 1

* wif org policies

* split identity provider configuration from cicd

* add type attribute to cicd repositories

* valid cicd repositories have a workflow template

* refactor stage 01

* fix stage 01 tests

* minimal CI/CD documentation

* better check_links error reporting

* fix links

* Added Gitlab specific configurations

Set the default issuer_uri for Gitlab. Added allowed audiences to OIDC configuration.

* Fixed TF formatting in identity providers.

* Changing identity provider audience to null

Changing identity provider audience to default to null.

* add instructions for renaming workflows

* address Julio's comments

Co-authored-by: Julio Castillo <jccb@google.com>
Co-authored-by: alexmeissner <alexmeissner@google.com>
2022-04-12 08:17:27 +02:00

101 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''Recursively check link destination validity in Markdown files.
This tool recursively checks that local links in Markdown files point to valid
destinations. Its main use is in CI pipelines triggered by pull requests.
'''
import collections
import pathlib
import requests
import urllib.parse
import click
import marko
BASEDIR = pathlib.Path(__file__).resolve().parents[1]
DOC = collections.namedtuple('DOC', 'path relpath links')
LINK = collections.namedtuple('LINK', 'dest valid')
def check_link(link, readme_path, external):
'Checks if a link element has a valid destination.'
link_valid = None
url = urllib.parse.urlparse(link.dest)
# If the link is public, say the link is anyway valid
# if --external is not set; check the link otherwise
if url.scheme:
link_valid = True
if external:
try:
response = requests.get(link.dest)
link_valid = response.ok
except requests.exceptions.RequestException:
link_valid = False
# The link is private
else:
link_valid = (readme_path.parent / url.path).exists()
return LINK(link.dest, link_valid)
def check_docs(dir_name, external=False):
'Traverses dir_name and checks for all Markdown files.'
dir_path = BASEDIR / dir_name
parser = marko.parser.Parser()
for readme_path in sorted(dir_path.glob('**/*.md')):
if '.terraform' in str(readme_path) or '.pytest' in str(readme_path):
continue
root = parser.parse(readme_path.read_text())
elements = collections.deque([root])
links = []
while elements:
el = elements.popleft()
if isinstance(el, marko.inline.Link):
links.append(check_link(el, readme_path, external))
elif hasattr(el, 'children'):
elements.extend(el.children)
yield DOC(readme_path, str(readme_path.relative_to(dir_path)), links)
@click.command()
@click.argument('dirs', type=str, nargs=-1)
@click.option('-e', '--external', is_flag=True, default=False,
help='Whether to test external links.')
def main(dirs, external):
'Checks links in Markdown files contained in dirs.'
errors = []
for dir_name in dirs:
print(f'----- {dir_name} -----')
for doc in check_docs(dir_name, external):
state = '' if all(l.valid for l in doc.links) else ''
print(f'[{state}] {doc.relpath} ({len(doc.links)})')
if state == '':
error = [f'{dir_name}{doc.relpath}']
for l in doc.links:
if not l.valid:
error.append(f' - {l.dest}')
print(f' {l.dest}')
errors.append('\n'.join(error))
if errors:
raise SystemExit('Errors found:\n{}'.format('\n'.join(errors)))
if __name__ == '__main__':
main()