diff --git a/.github/workflows/oui_filepull.yml b/.github/workflows/oui_filepull.yml index 35474317..aac03fc6 100644 --- a/.github/workflows/oui_filepull.yml +++ b/.github/workflows/oui_filepull.yml @@ -4,6 +4,7 @@ name: "OUI-Updates" on: # yamllint disable-line rule:truthy schedule: - cron: "0 2 1 * *" + workflow_dispatch: {} jobs: data_gathering: @@ -11,32 +12,51 @@ jobs: env: BRANCH_NAME: "OUI_Updates" steps: - # Checkout repo - name: "Check out code" uses: "actions/checkout@v4" with: ref: "develop" - # Delete old branch if it exists + fetch-depth: 0 + + - name: "Authenticate git remote" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + run: | + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + - name: "Delete existing branch" - run: "git branch -D $BRANCH_NAME || true" - # Create branch for Flatbot - - name: "Create Flatbot branch" - run: "git checkout -b $BRANCH_NAME" - # Push new branch so Flatbot can make its commit - - name: "Push Flatbot branch" - run: "git push -f --set-upstream origin $BRANCH_NAME" - # This step installs Deno, which is a new Javascript runtime that improves on Node. Can be used for an optional postprocessing step - - name: "Setup deno" - uses: "denoland/setup-deno@main" - with: - deno-version: "v1.10.x" - # The Flat Action step. We fetch the data in the http_url and save it as downloaded_filename - - name: "Fetch data" - uses: "githubocto/flat@v3" - with: - http_url: "https://standards-oui.ieee.org" - downloaded_filename: "./netutils/data_files/oui_mappings.py" - postprocess: "./flat_postprocess/oui_postprocess.ts" + run: | + git branch -D "$BRANCH_NAME" || true + + - name: "Create branch" + run: | + git checkout -b "$BRANCH_NAME" + + - name: "Push branch" + run: | + git push -f --set-upstream origin "$BRANCH_NAME" + + # Fetch data via curl as IEEE has blocked requests/urllib library requests + - name: "Download IEEE OUI data" + run: | + curl -fsSL "https://standards-oui.ieee.org/oui/oui.csv" \ + -o "./netutils/data_files/oui_mappings.py" + + - name: "Generate oui_mappings.py" + run: "python ./flat_postprocess/oui_postprocess.py ./netutils/data_files/oui_mappings.py" + + - name: "Commit changes" + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + git add ./netutils/data_files/oui_mappings.py + git diff --cached --quiet || git commit -m "Update OUI mappings" + + - name: "Push changes" + run: | + git push origin "$BRANCH_NAME" + pr_creation: runs-on: "ubuntu-latest" needs: "data_gathering" diff --git a/changes/745.fixed b/changes/745.fixed new file mode 100644 index 00000000..53f2c363 --- /dev/null +++ b/changes/745.fixed @@ -0,0 +1 @@ +Fix OUI GitHub Actions workflow to correctly fetch and generate OUI mappings \ No newline at end of file diff --git a/flat_postprocess/oui_postprocess.py b/flat_postprocess/oui_postprocess.py index 0720f39b..19a905af 100644 --- a/flat_postprocess/oui_postprocess.py +++ b/flat_postprocess/oui_postprocess.py @@ -1,26 +1,46 @@ """Python code used to postprocess Flat github action data related to OUI mappings.""" import re +import subprocess import sys -from urllib.request import urlopen -HEX_RE = r"^(?P[A-Fa-f0-9]{6})\s+\(.*\)[^a-zA-Z0-9]+(?P.*)$" +HEX_RE = r"^(?P[0-9A-Fa-f]{6})\s*\(base 16\)\s+(?P.+?)\s*$" + OUI_MAPPINGS = {} +URL = "https://standards-oui.ieee.org/oui/oui.txt" + + +def download_csv_text(url: str = URL) -> str: + """Download the CSV text from the given URL.""" + proc = subprocess.run( # noqa: S603 + ["curl", "-fsSL", url], # noqa: S607 + check=True, + capture_output=True, + text=True, + ) + return proc.stdout + if __name__ == "__main__": - if len(sys.argv) == 3: - with urlopen("https://standards-oui.ieee.org").read().decode("utf-8") as oui_textfile: # nosec B310 - with open(sys.argv[1], "w", encoding="utf-8") as oui_mappings: - oui_mappings.write(oui_textfile) + if len(sys.argv) < 2: + raise SystemExit("Usage: python oui_postprocess.py []") + + output_path = sys.argv[1] + download = "--download" in sys.argv[2:] + + if download: + csv_text = download_csv_text(URL) + with open(output_path, "w", encoding="utf-8", newline="") as oui_textfile: + oui_textfile.write(csv_text) - with open(sys.argv[1], "r", encoding="utf-8") as oui_file: + with open(output_path, "r", encoding="utf-8", newline="") as oui_file: for line in oui_file: if re.search(HEX_RE, line): group_regex_values = re.search(HEX_RE, line).groupdict() if group_regex_values.get("hex") and group_regex_values.get("company"): OUI_MAPPINGS.update({group_regex_values.get("hex").lower(): group_regex_values.get("company")}) - with open(sys.argv[1], "w", encoding="utf-8") as oui_mappings: + with open(output_path, "w", encoding="utf-8") as oui_mappings: oui_mappings.write('"""Dictionary object to store OUI information."""\n') oui_mappings.write("# pylint: disable=too-many-lines\n") oui_mappings.write("import typing\n\n")