Loading validate-gitlab-yaml.py +39 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ def main(): help="""GitLab API URL endpoint, defaults to $CI_API_V4_URL environment or %(default)s if undefined""", ) parser.add_argument( "--project-id", default=os.environ.get("CI_PROJECT_ID"), help="""GitLab CI project namespace to validate the YAML against, defaults to $CI_PROJECT_ID environment variable""", ) parser.add_argument( "path", nargs="+", Loading @@ -73,29 +79,54 @@ def main(): help="GitLab CI YAML files to validate", ) args = parser.parse_args() if args.project_id is None: parser.error("missing CI_PROJECT_ID environment, use --project-id to specify") token = os.environ.get("GITLAB_PRIVATE_TOKEN") if token is None: logging.error("missing GITLAB_PRIVATE_TOKEN environment, aborting") sys.exit(1) headers = { "Content-Type": "application/json", "PRIVATE-TOKEN": token, } # XXX: this doesn't actually work. The CI_JOB_TOKEN variable # *does* exist, but it doesn't have the privileges necessary to # run the API. This is just too bad, and should probably be # reported upstream so that we don't have to go through the hoops # of creating the project-level access token once a year. see: # https://docs.gitlab.com/ee/api/rest/#job-tokens ci_job_token = os.environ.get("CI_JOB_TOKEN") if ci_job_token: headers['JOB-TOKEN'] = ci_job_token gitlab_private_token = os.environ.get("GITLAB_PRIVATE_TOKEN") if gitlab_private_token: headers['PRIVATE-TOKEN'] = gitlab_private_token if gitlab_private_token is None and ci_job_token is None: parser.error("missing GITLAB_PRIVATE_TOKEN or CI_JOB_TOKEN environment") success = True for path in args.path: logging.info("linting GitLab CI YAML file: %s", path.name) payload = { "content": path.read(), "dry_run": True, } logging.debug("sending paylod: %r", payload) r = requests.post( args.api_url + "/ci/lint", args.api_url + f"/projects/{args.project_id}/ci/lint", headers=headers, json=payload, ) # XXX: a bit rough, we should handle errors here better try: r.raise_for_status() except requests.RequestException as e: # if this happens, you need to recreate the token here: # https://gitlab.torproject.org/tpo/tpa/ci-templates/-/settings/access_tokens # with "maintainer" role and "api" scope then copy it over # to the project's CI/CD variable as GITLAB_PRIVATE_TOKEN # # see also https://gitlab.torproject.org/tpo/tpa/ci-templates/-/issues/17 logging.error("failed to call API endpoint: %s, is the token valid?", e) sys.exit(3) j = r.json() logging.debug("response: %r", j) if j["valid"]: Loading Loading
validate-gitlab-yaml.py +39 −8 Original line number Diff line number Diff line Loading @@ -66,6 +66,12 @@ def main(): help="""GitLab API URL endpoint, defaults to $CI_API_V4_URL environment or %(default)s if undefined""", ) parser.add_argument( "--project-id", default=os.environ.get("CI_PROJECT_ID"), help="""GitLab CI project namespace to validate the YAML against, defaults to $CI_PROJECT_ID environment variable""", ) parser.add_argument( "path", nargs="+", Loading @@ -73,29 +79,54 @@ def main(): help="GitLab CI YAML files to validate", ) args = parser.parse_args() if args.project_id is None: parser.error("missing CI_PROJECT_ID environment, use --project-id to specify") token = os.environ.get("GITLAB_PRIVATE_TOKEN") if token is None: logging.error("missing GITLAB_PRIVATE_TOKEN environment, aborting") sys.exit(1) headers = { "Content-Type": "application/json", "PRIVATE-TOKEN": token, } # XXX: this doesn't actually work. The CI_JOB_TOKEN variable # *does* exist, but it doesn't have the privileges necessary to # run the API. This is just too bad, and should probably be # reported upstream so that we don't have to go through the hoops # of creating the project-level access token once a year. see: # https://docs.gitlab.com/ee/api/rest/#job-tokens ci_job_token = os.environ.get("CI_JOB_TOKEN") if ci_job_token: headers['JOB-TOKEN'] = ci_job_token gitlab_private_token = os.environ.get("GITLAB_PRIVATE_TOKEN") if gitlab_private_token: headers['PRIVATE-TOKEN'] = gitlab_private_token if gitlab_private_token is None and ci_job_token is None: parser.error("missing GITLAB_PRIVATE_TOKEN or CI_JOB_TOKEN environment") success = True for path in args.path: logging.info("linting GitLab CI YAML file: %s", path.name) payload = { "content": path.read(), "dry_run": True, } logging.debug("sending paylod: %r", payload) r = requests.post( args.api_url + "/ci/lint", args.api_url + f"/projects/{args.project_id}/ci/lint", headers=headers, json=payload, ) # XXX: a bit rough, we should handle errors here better try: r.raise_for_status() except requests.RequestException as e: # if this happens, you need to recreate the token here: # https://gitlab.torproject.org/tpo/tpa/ci-templates/-/settings/access_tokens # with "maintainer" role and "api" scope then copy it over # to the project's CI/CD variable as GITLAB_PRIVATE_TOKEN # # see also https://gitlab.torproject.org/tpo/tpa/ci-templates/-/issues/17 logging.error("failed to call API endpoint: %s, is the token valid?", e) sys.exit(3) j = r.json() logging.debug("response: %r", j) if j["valid"]: Loading