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 staging to selftest #127

Merged
merged 6 commits into from
Feb 23, 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: 1 addition & 0 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ jobs:
id: sigstore-conformance
with:
entrypoint: ${{ github.workspace }}/sigstore-python-conformance
enable-staging: true
xfail: "test_verify_with_trust_root test_verify_dsse_bundle_with_trust_root"
50 changes: 28 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,34 @@ Some general testing principles for this suite are:

## Usage

Simply add `sigstore/sigstore-conformance` to one of your workflows:

```yaml
jobs:
conformance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: install
run: python -m pip install .
- uses: sigstore/[email protected]
with:
entrypoint: sigstore
```

The only required configuration is the `entrypoint` parameter which provides a
command to invoke the client. `sigstore-conformance` expects that the client
exposes a CLI that conforms to the protocol outlined [here](docs/cli_protocol.md).

In the example above, the workflow is installing [sigstore-python](https://github.com/sigstore/sigstore-python)
and providing `sigstore` as the `entrypoint` since this is the command used to
invoke the client.
1. Include an executable in your project that implements the
client-under-test [CLI protocol](docs/cli_protocol.md).
2. Use the `sigstore/sigstore-conformance` action in your test workflow:
```yaml
jobs:
conformance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# insert your client installation steps here
- uses: sigstore/[email protected]
with:
entrypoint: my-conformance-client
```

See [sigstore-python conformance test](https://github.com/sigstore/sigstore-python/blob/main/.github/workflows/conformance.yml)
for a complete example.

### `sigstore/sigstore-conformance` action inputs

The important action inputs are
* `entrypoint`: required string. A command that implements the client-under-test
[CLI protocol](docs/cli_protocol.md)
* `enable-staging`: optional boolean. When true, the test suite will run tests against
staging infrastructure in addition to running them against production infrastructure
* `xfail`: optional string. Whitespace separated test names that are expected to fail.

See [action.yml](action.yml) for full list of inputs.

## Development

Expand Down
42 changes: 25 additions & 17 deletions action.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
_RENDER_SUMMARY = os.getenv("GHA_SIGSTORE_CONFORMANCE_SUMMARY", "true") == "true"
_DEBUG = os.getenv("GHA_SIGSTORE_CONFORMANCE_INTERNAL_BE_CAREFUL_DEBUG", "false") != "false"
_ACTION_PATH = Path(os.getenv("GITHUB_ACTION_PATH")) # type: ignore
_ENABLE_STAGING = os.getenv("GHA_SIGSTORE_CONFORMANCE_ENABLE_STAGING", "false").lower() == "true"


def _summary(msg):
Expand All @@ -26,35 +27,42 @@ def _debug(msg):
print(f"\033[93mDEBUG: {msg}\033[0m", file=sys.stderr)


def _sigstore_conformance(*args) -> int:
return pytest.main([str(_ACTION_PATH / "test"), *args])
def _sigstore_conformance(staging: bool) -> int:
args = []

if _DEBUG:
args.extend(["-s", "-vv", "--showlocals"])

sigstore_conformance_args = []
entrypoint = os.getenv("GHA_SIGSTORE_CONFORMANCE_ENTRYPOINT")
if entrypoint:
args.extend(["--entrypoint", entrypoint])

if _DEBUG:
sigstore_conformance_args.extend(["-s", "-vv", "--showlocals"])
if staging:
args.append("--staging")

entrypoint = os.getenv("GHA_SIGSTORE_CONFORMANCE_ENTRYPOINT")
if entrypoint:
sigstore_conformance_args.extend(["--entrypoint", entrypoint])
skip_signing = os.getenv("GHA_SIGSTORE_CONFORMANCE_SKIP_SIGNING", "false").lower() == "true"
if skip_signing:
args.extend(["--skip-signing"])

skip_signing = os.getenv("GHA_SIGSTORE_CONFORMANCE_SKIP_SIGNING", "false").lower() == "true"
if skip_signing:
sigstore_conformance_args.extend(["--skip-signing"])
gh_token = os.getenv("GHA_SIGSTORE_GITHUB_TOKEN")
if gh_token:
args.extend(["--github-token", gh_token])

gh_token = os.getenv("GHA_SIGSTORE_GITHUB_TOKEN")
if gh_token:
sigstore_conformance_args.extend(["--github-token", gh_token])
infra = "staging" if staging else "production"
print(f"running sigstore-conformance against Sigstore {infra} infrastructure")
_debug(f"running: sigstore-conformance {[str(a) for a in args]}")

_debug(f"running: sigstore-conformance {[str(a) for a in sigstore_conformance_args]}")
return pytest.main([str(_ACTION_PATH / "test"), *args])

status = _sigstore_conformance(*sigstore_conformance_args)

# Run against production, then optionally against staging
status = _sigstore_conformance(staging=False)
if _ENABLE_STAGING:
status += _sigstore_conformance(staging=True)

if status == 0:
_summary("🎉 sigstore-conformance exited successfully")
else:
_summary("❌ sigstore-conformance found one or more test failures")


sys.exit(status)
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ inputs:
description: "skip tests that involve signing (default false)"
required: false
default: "false"
enable-staging:
description: "Test against staging infrastructure as well as production (default false)"
required: false
default: "false"
xfail:
description: "one or more tests that are expected to fail, whitespace-separated"
required: false
Expand All @@ -34,6 +38,7 @@ runs:
run: |
${{ github.action_path }}/action.py
env:
GHA_SIGSTORE_CONFORMANCE_ENABLE_STAGING: "${{ inputs.enable-staging }}"
GHA_SIGSTORE_CONFORMANCE_ENTRYPOINT: "${{ inputs.entrypoint }}"
GHA_SIGSTORE_CONFORMANCE_INTERNAL_BE_CAREFUL_DEBUG: "${{ inputs.internal-be-careful-debug }}"
GHA_SIGSTORE_CONFORMANCE_SKIP_SIGNING: "${{ inputs.skip-signing }}"
Expand Down
3 changes: 3 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ def pytest_addoption(parser) -> None:
def pytest_runtest_setup(item):
if "signing" in item.keywords and item.config.getoption("--skip-signing"):
pytest.skip("skipping test that requires signing support due to `--skip-signing` flag")
if "staging" not in item.keywords and item.config.getoption("--staging"):
pytest.skip("skipping test that does not support staging yet due to `--staging` flag")


def pytest_configure(config):
if not config.getoption("--github-token") and not config.getoption("--skip-signing"):
raise ConfigError("Please specify one of '--github-token' or '--skip-signing'")

config.addinivalue_line("markers", "signing: mark test as requiring signing functionality")
config.addinivalue_line("markers", "staging: mark test as supporting testing against staging")


def pytest_internalerror(excrepr, excinfo):
Expand Down
2 changes: 2 additions & 0 deletions test/test_signature_verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@


@pytest.mark.signing
@pytest.mark.staging
def test_verify_empty(client: SigstoreClient, make_materials: _MakeMaterials) -> None:
"""
Tests that verification fails with empty artifacts, certificates and
Expand Down Expand Up @@ -34,6 +35,7 @@ def test_verify_empty(client: SigstoreClient, make_materials: _MakeMaterials) ->


@pytest.mark.signing
@pytest.mark.staging
def test_verify_mismatch(client: SigstoreClient, make_materials: _MakeMaterials) -> None:
"""
Tests that verification fails with mismatching artifacts, certificates and
Expand Down
1 change: 1 addition & 0 deletions test/test_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


@pytest.mark.signing
@pytest.mark.staging
def test_simple(client: SigstoreClient, make_materials: _MakeMaterials) -> None:
"""
A simple test that signs and verifies an artifact for a given Sigstore
Expand Down
Loading