diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b05f795..bef3871 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,6 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.x" - name: lint run: make lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d57ce9f..3183fc3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,4 +24,3 @@ jobs: with: inputs: action.yml action.py release-signing-artifacts: true - bundle-only: true diff --git a/.github/workflows/schedule-selftest.yml b/.github/workflows/schedule-selftest.yml new file mode 100644 index 0000000..acb05b1 --- /dev/null +++ b/.github/workflows/schedule-selftest.yml @@ -0,0 +1,46 @@ +name: Scheduled self-test + +on: + schedule: + - cron: '0 12 * * *' # Every day at 1200 UTC + +jobs: + run-selftests: + permissions: + id-token: write + + uses: ./.github/workflows/selftest.yml + open-issue: + permissions: + issues: write + + runs-on: ubuntu-latest + if: ${{ failure() }} + needs: run-selftests + + steps: + - name: Generate issue text + run: | + cat <<- EOF >/tmp/issue.md + ## Self-test failure + + A scheduled test of the workflow has failed. + + This suggests one of three conditions: + * A backwards-incompatible change in a Sigstore component; + * A regression in \`gh-action-sigstore-python\`; + * A transient error. + + The full CI failure can be found here: + + ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/$GITHUB_RUN_ID + EOF + + - name: Open issue + uses: peter-evans/create-issue-from-file@433e51abf769039ee20ba1293a088ca19d573b7f # v4.0.1 + with: + title: "[CI] Self-test failure" + # created in the previous step + content-filepath: /tmp/issue.md + labels: bug + assignees: woodruffw,tetsuo-cpp,tnytown diff --git a/.github/workflows/selftest.yml b/.github/workflows/selftest.yml index 573a69e..06798f2 100644 --- a/.github/workflows/selftest.yml +++ b/.github/workflows/selftest.yml @@ -6,25 +6,35 @@ on: - main pull_request: workflow_dispatch: + workflow_call: permissions: id-token: write jobs: selftest: - runs-on: ubuntu-latest + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + runs-on: ${{ matrix.os }} if: (github.event_name != 'pull_request') || !github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + if: ${{ matrix.os != 'ubuntu-latest' }} + with: + python-version: "3.x" - name: Sign artifact and publish signature uses: ./ id: sigstore-python with: inputs: ./test/artifact.txt - name: Check outputs + shell: bash run: | - [[ -f ./test/artifact.txt.sig ]] || exit 1 - [[ -f ./test/artifact.txt.crt ]] || exit 1 [[ -f ./test/artifact.txt.sigstore ]] || exit 1 selftest-xfail-invalid-inputs: @@ -67,8 +77,6 @@ jobs: staging: true - name: Check outputs run: | - [[ -f ./test/artifact.txt.sig ]] || exit 1 - [[ -f ./test/artifact.txt.crt ]] || exit 1 [[ -f ./test/artifact.txt.sigstore ]] || exit 1 selftest-glob: @@ -102,8 +110,6 @@ jobs: - name: Verify presence of uploaded files run: | [[ -f ./artifact.txt ]] || exit 1 - [[ -f ./artifact.txt.sig ]] || exit 1 - [[ -f ./artifact.txt.crt ]] || exit 1 [[ -f ./artifact.txt.sigstore ]] || exit 1 working-directory: ./test/uploaded diff --git a/README.md b/README.md index 986ec30..ce986a7 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v3 - name: install run: python -m pip install . - - uses: sigstore/gh-action-sigstore-python@v1.2.3 + - uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt ``` @@ -53,7 +53,7 @@ provided. To sign one or more files: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file0.txt file1.txt file2.txt ``` @@ -61,7 +61,7 @@ To sign one or more files: The `inputs` argument also supports file globbing: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: ./path/to/inputs/*.txt ``` @@ -74,7 +74,7 @@ The `identity-token` setting controls the OpenID Connect token provided to Fulci workflow will use the credentials found in the GitHub Actions environment. ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt identity-token: ${{ IDENTITY_TOKEN }} # assigned elsewhere @@ -90,7 +90,7 @@ Server during OAuth2. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt oidc-client-id: alternative-sigstore-id @@ -106,7 +106,7 @@ Connect Server during OAuth2. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt oidc-client-secret: alternative-sigstore-secret @@ -122,7 +122,7 @@ when signing multiple input files. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt signature: custom-signature-filename.sig @@ -131,7 +131,7 @@ Example: However, this example is invalid: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file0.txt file1.txt file2.txt signature: custom-signature-filename.sig @@ -147,7 +147,7 @@ work when signing multiple input files. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt certificate: custom-certificate-filename.crt @@ -156,7 +156,7 @@ Example: However, this example is invalid: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file0.txt file1.txt file2.txt certificate: custom-certificate-filename.crt @@ -172,7 +172,7 @@ when signing multiple input files. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt bundle: custom-bundle.sigstore @@ -181,7 +181,7 @@ Example: However, this example is invalid: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file0.txt file1.txt file2.txt certificate: custom-bundle.sigstore @@ -197,7 +197,7 @@ from. This setting cannot be used in combination with the `staging` setting. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt fulcio-url: https://fulcio.sigstage.dev @@ -213,7 +213,7 @@ cannot be used in combination with the `staging` setting. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt rekor-url: https://rekor.sigstage.dev @@ -229,7 +229,7 @@ in combination with the `staging` setting. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt ctfe: ./path/to/ctfe.pub @@ -245,7 +245,7 @@ be used in combination with `staging` setting. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt ctfe: ./path/to/rekor.pub @@ -261,7 +261,7 @@ instead of the default production instances. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt staging: true @@ -284,7 +284,7 @@ and `verify-oidc-issuer` settings. Failing to pass these will produce an error. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt verify: true @@ -307,7 +307,7 @@ This setting may only be used in conjunction with `verify-oidc-issuer`. Supplying it without `verify-oidc-issuer` will produce an error. ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt verify: true @@ -332,7 +332,7 @@ Supplying it without `verify-cert-identity` will produce an error. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt verify: true @@ -354,7 +354,7 @@ workflow artifact retention period is used. Example: ```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt upload-signing-artifacts: true @@ -382,35 +382,12 @@ permissions: # ... -- uses: sigstore/gh-action-sigstore-python@v1.2.3 +- uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt release-signing-artifacts: true ``` -### `bundle-only` - -**Default**: `false` - -The `bundle-only` setting controls whether or not `sigstore-python` uploads `.crt` -or `.sig` artifacts. - -This setting affects the behavior of the `upload-signing-artifacts` and `release-signing-artifacts` -settings. If neither of those settings are specified, this setting has no effect. - -By default, `.crt` and `.sig` artifacts are uploaded. If enabled, only the `.sigstore` -signing artifact is uploaded. - -Example: - -```yaml -- uses: sigstore/gh-action-sigstore-python@v1.2.3 - with: - inputs: file.txt - upload-signing-artifacts: true - bundle-only: true -``` - ### Internal options
⚠️ Internal options ⚠️ @@ -432,7 +409,7 @@ Example: Example: ```yaml - - uses: sigstore/gh-action-sigstore-python@v1.2.3 + - uses: sigstore/gh-action-sigstore-python@v2.0.0 with: inputs: file.txt internal-be-careful-debug: true diff --git a/action.py b/action.py index a791b02..23044f5 100755 --- a/action.py +++ b/action.py @@ -62,7 +62,12 @@ def _download_ref_asset(ext): repo = os.getenv("GITHUB_REPOSITORY") ref = os.getenv("GITHUB_REF") - artifact = Path(f"/tmp/{os.getenv('GITHUB_REF_NAME')}.{ext}") + # NOTE: Branch names often have `/` in them (e.g. `feat/some-name`), + # which would break the artifact path we construct below. + # We "fix" these by lossily replacing all `/` with `-`. + ref_name_normalized = os.getenv("GITHUB_REF_NAME").replace("/", "-") + + artifact = Path(f"/tmp/{ref_name_normalized}.{ext}") # GitHub supports /:org/:repo/archive/:ref<.tar.gz|.zip>. r = requests.get(f"https://github.com/{repo}/archive/{ref}.{ext}", stream=True) @@ -190,7 +195,6 @@ def _fatal_help(msg): if artifact is not None: inputs.append(artifact) -bundle_only = os.getenv("GHA_SIGSTORE_PYTHON_BUNDLE_ONLY") == "true" for input_ in inputs: # Forbid things that look like flags. This isn't a security boundary; just # a way to prevent (less motivated) users from breaking the action on themselves. @@ -206,10 +210,6 @@ def _fatal_help(msg): # Also upload artifact being signed for. signing_artifact_paths.append(str(file_)) - if not bundle_only and "--certificate" not in sigstore_sign_args: - signing_artifact_paths.append(f"{file_}.crt") - if not bundle_only and "--signature" not in sigstore_sign_args: - signing_artifact_paths.append(f"{file_}.sig") if "--bundle" not in sigstore_sign_args: signing_artifact_paths.append(f"{file_}.sigstore") @@ -280,16 +280,16 @@ def _fatal_help(msg): with Path(_github_env).open("a") as gh_env: # Multiline values must match the following syntax: # - # {name}<<{delimiter} - # {value} - # {delimiter} - gh_env.write( - "GHA_SIGSTORE_PYTHON_INTERNAL_SIGNING_ARTIFACTS<