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

Feat: add pytest job to _Test-OCI-Factory workflow #224

Merged
merged 16 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 0 additions & 1 deletion .github/workflows/Announcements.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,3 @@ jobs:
do
MM_CHANNEL_ID="${channel}" ./src/notifications/send_to_mattermost.sh
done

4 changes: 2 additions & 2 deletions .github/workflows/Documentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
oci-image-name:
description: 'OCI image to generate the documentation for'
required: true
external_ref_id: #(1)
external_ref_id: # (1)
description: 'Optional ID for unique run detection'
required: false
type: string
Expand All @@ -34,7 +34,7 @@ jobs:
oci-img-path: ${{ steps.validate-image.outputs.img-path }}
oci-img-name: ${{ steps.validate-image.outputs.img-name }}
steps:
- name: ${{ inputs.external_ref_id }} #(2)
- name: ${{ inputs.external_ref_id }} # (2)
if: ${{ github.event_name == 'workflow_dispatch' }}
run: echo 'Started by ${{ inputs.external_ref_id }}' >> "$GITHUB_STEP_SUMMARY"

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/Image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ on:
required: true
type: boolean
default: false
external_ref_id: #(1)
external_ref_id: # (1)
description: 'Optional ID for unique run detection'
required: false
type: string
Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
oci-img-path: ${{ steps.validate-image.outputs.img-path }}
oci-img-name: ${{ steps.validate-image.outputs.img-name }}
steps:
- name: ${{ inputs.external_ref_id }} #(2)
- name: ${{ inputs.external_ref_id }} # (2)
if: ${{ github.event_name == 'workflow_dispatch' }}
run: echo 'Started by ${{ inputs.external_ref_id }}' >> "$GITHUB_STEP_SUMMARY"

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/Release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
description: 'Cache key (to fetch image trigger from cache)'
required: false
type: string
external_ref_id: #(1)
external_ref_id: # (1)
description: 'Optional ID for unique run detection'
required: false
type: string
Expand All @@ -34,7 +34,7 @@ jobs:
outputs:
oci-image-name: ${{ steps.get-image-name.outputs.img-name }}
steps:
- name: ${{ inputs.external_ref_id }} #(2)
- name: ${{ inputs.external_ref_id }} # (2)
run: echo 'Started by ${{ inputs.external_ref_id }}' >> "$GITHUB_STEP_SUMMARY"

- uses: actions/checkout@v4
Expand Down Expand Up @@ -174,8 +174,8 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ matrix.canonical-tag }}
fetch-depth: 0
ref: ${{ matrix.canonical-tag }}

- uses: dev-drprasad/[email protected]
# We force delete an existing tag because otherwise we won't get
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/Tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ on:
default: 'cache'
type: choice
options:
- cache
- registry
- cache
- registry
cache-key:
description: 'Cache key (when fetching from cache)'
required: false
Expand All @@ -51,7 +51,7 @@ on:
required: true
type: string
default: '.vulnerability-report.json'
external_ref_id: #(1)
external_ref_id: # (1)
description: 'Optional ID for unique run detection'
required: false
type: string
Expand All @@ -72,7 +72,7 @@ jobs:
outputs:
test-cache-key: ${{ steps.cache.outputs.key }}
steps:
- name: ${{ inputs.external_ref_id }} #(2)
- name: ${{ inputs.external_ref_id }} # (2)
run: echo 'Started by ${{ inputs.external_ref_id }}' >> "$GITHUB_STEP_SUMMARY"

- uses: actions/cache/restore@v4
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/_Test-OCI-Factory.yaml
clay-lake marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,58 @@ on:
- "examples/**"
- "oci/mock*"
- "src/**"
- "tools/**"
- "tests/**"
- "!tools/workflow-engine/**"
- "!tools/cli-client/**"

env:
# local path to clone the oci-factory to

# path of pytest junit output
PYTEST_RESULT_PATH: pytest_results.xml


jobs:

pytest:
# Trigger python unit tests across the repository
name: pytest
runs-on: ubuntu-22.04
steps:

# Job Setup
- uses: actions/checkout@v4
with:
fetch-depth: 1

- uses: actions/setup-python@v5
with:
python-version: "3.x"

# Note: Add additional dependency installation lines as required below
# test-oci-factory/pytest requirements
- run: pip install -r tests/etc/requirements.txt


- name: Run pytest
continue-on-error: true
run: |
python3 -m pytest --junit-xml "${{ env.PYTEST_RESULT_PATH }}"

- name: Generate Summary
if: ${{ !cancelled() }}
run: |
python3 -m tools.junit_to_markdown --input-junit "${{ env.PYTEST_RESULT_PATH }}" >> $GITHUB_STEP_SUMMARY

- name: Upload pytest Result
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: ${{ env.PYTEST_RESULT_PATH }}
path: ${{ env.PYTEST_RESULT_PATH }}
if-no-files-found: error

test-workflows:
name: Trigger internal tests for mock-rock
uses: ./.github/workflows/Image.yaml
Expand Down
4 changes: 1 addition & 3 deletions src/docs/generate_oci_doc_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,7 @@ def build_releases_data(
# Set the support date
if all_tracks.get(track_base):
eol = parser.parse(all_tracks[track_base])
release_data["support"] = {
"until": eol.strftime("%m/%Y")
}
release_data["support"] = {"until": eol.strftime("%m/%Y")}

releases.append(release_data)

Expand Down
15 changes: 11 additions & 4 deletions src/image/prepare_single_image_build_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,21 @@ def validate_image_trigger(data: dict) -> None:

if args.infer_image_track:
import sys

sys.path.append("src/")
from git import Repo
from tempfile import TemporaryDirectory as tempdir
from uploads.infer_image_track import get_base_and_track

with tempdir() as d:
url = f"https://github.com/{builds[img_number]['source']}.git"
repo = Repo.clone_from(url, d)
repo.git.checkout(builds[img_number]["commit"])
# get the base image from the rockcraft.yaml file
with open(f"{d}/{builds[img_number]['directory']}/rockcraft.yaml", encoding="UTF-8") as rockcraft_file:
with open(
f"{d}/{builds[img_number]['directory']}/rockcraft.yaml",
encoding="UTF-8",
) as rockcraft_file:
rockcraft_yaml = yaml.load(rockcraft_file, Loader=yaml.BaseLoader)

base_release, track = get_base_and_track(rockcraft_yaml)
Expand All @@ -86,14 +91,16 @@ def validate_image_trigger(data: dict) -> None:
with open(
f"{args.revision_data_dir}/{builds[img_number]['revision']}",
"w",
encoding="UTF-8"
encoding="UTF-8",
) as data_file:
json.dump(builds[img_number], data_file)

# Add dir_identifier to assemble the cache key and artefact path
# No need to write it to rev data file since it's only used in matrix
builds[img_number]["dir_identifier"] = builds[img_number]["directory"].rstrip("/").replace("/", "_")

builds[img_number]["dir_identifier"] = (
builds[img_number]["directory"].rstrip("/").replace("/", "_")
)

# set an output as a marker for later knowing if we need to release
if "release" in builds[img_number]:
release_to = "true"
Expand Down
4 changes: 1 addition & 3 deletions src/tests/get_released_revisions.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,7 @@ def get_image_name_in_registry(img_name: str, revision: str) -> str:
)
continue
elif not risks.get("end-of-life"):
logging.warning(
f"Track {track} is missing its end-of-life field"
)
logging.warning(f"Track {track} is missing its end-of-life field")

for key, targets in risks.items():
if key == "end-of-life":
Expand Down
1 change: 0 additions & 1 deletion src/uploads/infer_image_track.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ def get_base_and_track(rockcraft_yaml) -> tuple[str, str]:
) as rockcraft_file:
rockcraft_yaml = yaml.load(rockcraft_file, Loader=yaml.BaseLoader)


base_release, track = get_base_and_track(rockcraft_yaml)

print(f"rock track: {track}")
Expand Down
3 changes: 3 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from pathlib import Path

DATA_DIR = Path(__file__).parent / "data"
18 changes: 18 additions & 0 deletions tests/data/junit_xml_failure.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite name="pytest" errors="0" failures="1" skipped="0" tests="6" time="0.127" timestamp="2024-08-13T11:57:19.793644+00:00" hostname="fv-az1756-954">
<testcase classname="oci-factory.src.build-rock.configure.test.test_generate_matrix" name="test_get_target_archs" time="0.001" />
<testcase classname="oci-factory.src.build-rock.configure.test.test_generate_matrix" name="test_configure_matrices" time="0.000" />
<testcase classname="oci-factory.src.build-rock.configure.test.test_generate_matrix" name="test_configure_matrices_fallback_exception" time="0.000" />
<testcase classname="oci-factory.src.build-rock.configure.test.test_generate_matrix" name="test_configure_matrices_lpci_fallback" time="0.000" />
<testcase classname="oci-factory.src.build-rock.configure.test.test_generate_matrix" name="test_set_build_config_outputs" time="0.001" />
<testcase classname="oci-factory.src.docs.test.test_generate_oci_doc_yaml" name="test_example_failure" time="0.001">
<failure message="AssertionError: This is to exemplify the output of a failed unit test&#10;assert False">def test_example_failure():
&gt; assert False, "This is to exemplify the output of a failed unit test"
E AssertionError: This is to exemplify the output of a failed unit test
E assert False
oci-factory/src/docs/test/test_generate_oci_doc_yaml.py:8: AssertionError
</failure>
</testcase>
</testsuite>
</testsuites>
1 change: 1 addition & 0 deletions tests/etc/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest==8.3.2
Empty file added tests/fixtures/__init__.py
Empty file.
9 changes: 9 additions & 0 deletions tests/fixtures/buffers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import pytest
from io import StringIO


@pytest.fixture
def str_buff():
"""String IO fixture for simulating a file object"""
with StringIO() as buffer:
yield buffer
13 changes: 13 additions & 0 deletions tests/fixtures/junit_et.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest
import xml.etree.ElementTree as ET
from .. import DATA_DIR


@pytest.fixture
def junit_with_failure():
"""Load ET of junit xml report with failure"""
sample = DATA_DIR / "junit_xml_failure.xml"

tree = ET.parse(sample)
root = tree.getroot()
return root
Empty file added tests/integration/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions tests/integration/test_junit_to_markdown_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from ..fixtures.buffers import str_buff
from ..fixtures.junit_et import junit_with_failure
import tools.junit_to_markdown.convert as report


def test_print_redirection(junit_with_failure, str_buff, capsys):
"""Ensure that the report is entirely redirected when needed"""

report.print_junit_report(junit_with_failure, str_buff)
report.print_junit_report(junit_with_failure, None) # print report to stdout

str_buff.seek(0)
str_buff_content = str_buff.read()

captured = capsys.readouterr()
stdout_content = captured.out

assert stdout_content == str_buff_content, "Printing to multiple locations."
Empty file added tests/unit/__init__.py
Empty file.
Loading
Loading