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

pull upstream ci updates #26

Merged
merged 6 commits into from
Sep 24, 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
37 changes: 37 additions & 0 deletions .github/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
BSD 2-Clause License

The code of Project Gluon may be distributed under the following terms, unless
noted otherwise in individual files or subtrees.

Copyright (c) Project Gluon
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


OpenWrt is licensed under the terms of the GNU General Public License Version 2,
which can be found at openwrt/LICENSE after the OpenWrt repository has been
obtained. This applies to the following repositories:

* openwrt
* packages/openwrt
* packages/routing
* packages/luci
16 changes: 16 additions & 0 deletions .github/build-meta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
set -euxo pipefail

SCRIPT_DIR="$(dirname "$0")"
UPSTREAM_REPO_NAME="freifunk-rhein-neckar/site-ffrn"

# Get Git short hash for repo at $SCRIPT_DIR
GIT_SHORT_HASH="$(git -C "$SCRIPT_DIR" rev-parse --short HEAD)"
Expand Down Expand Up @@ -159,6 +160,21 @@ if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
SIGN_MANIFEST="0"
fi

# Signing should only happen when pushed to the upstream repository.
# Skip this step for the pipeline to succeed but inform the user.
if [ "${GITHUB_REPOSITORY,,}" != "${UPSTREAM_REPO_NAME,,}" ] && [ "$SIGN_MANIFEST" != "0" ]; then
SIGN_MANIFEST="0"

echo "::warning::Skip manifest signature due to action running in fork."
fi

# We should neither deploy in a fork, as the workflow is hard-coding our firmware-server
if [ "$GITHUB_REPOSITORY" != "$UPSTREAM_REPO_NAME" ] && [ "$DEPLOY" != "0" ]; then
DEPLOY="0"

echo "::warning::Skip deployment due to action running in fork."
fi

# Determine Version to use
RELEASE_VERSION="${RELEASE_VERSION:-$DEFAULT_RELEASE_VERSION}"

Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ jobs:
runs-on: ubuntu-22.04
if: >
needs.targets.outputs.targets != '[]'
permissions:
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -271,6 +274,14 @@ jobs:
gluon-path: "gluon-gha-data/gluon"
hardware-target: ${{ matrix.target }}

- name: Attest Image Build Provenance
if: ${{ needs.build-meta.outputs.create-release != '0' }}
uses: actions/attest-build-provenance@v1
with:
subject-path: |
"gluon-gha-data/gluon/output/images/sysupgrade/*"
"gluon-gha-data/gluon/output/images/other/*"
"gluon-gha-data/gluon/output/images/factory/*"

manifest:
needs: [build, build-meta, targets]
Expand Down Expand Up @@ -547,6 +558,8 @@ jobs:
github.event_name == 'push'
permissions:
contents: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -590,6 +603,12 @@ jobs:
gluon-gha-data/release-artifacts/build-meta.txt
gluon-gha-data/release-notes.md

- name: Attest Release Artifact Build Provenance
uses: actions/attest-build-provenance@v1
with:
subject-path: |
gluon-gha-data/release-artifacts/*

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
Expand Down
80 changes: 80 additions & 0 deletions contrib/load-attestation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# SPDX-License-Identifier: MIT

import sys
import json
import os
import requests
import base64
import hashlib
import argparse

DEFAULT_OWNER = "freifunk-rhein-neckar"
DEFAULT_REPO = "site-ffrn"

def parse_arguments():
parser = argparse.ArgumentParser(description='Load and print attestation from a GitHub API.')
parser.add_argument('-o', '--owner', help='Owner of the repository', required=False, default=DEFAULT_OWNER)
parser.add_argument('-r', '--repo', help='Repository name', required=False, default=DEFAULT_REPO)
parser.add_argument('file_path', help='Path to the attestation file')
return parser.parse_args()

def get_file_sha256(file_path):
sha256 = hashlib.sha256()
with open(file_path, "rb") as f:
while True:
data = f.read(65536)
if not data:
break
sha256.update(data)
return sha256.hexdigest()

def load_attestation_from_gh_api(owner, repo, file_sha256):
url = f"https://api.github.com/repos/{owner}/{repo}/attestations/sha256:{file_sha256}"
headers = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
}
response = requests.get(url, headers=headers)

if response.status_code != 200:
print(f"Failed to load attestation from {url}")
sys.exit(1)

print("Got attestation from GitHub API")

return response.json()

def print_attestation(data):
dsse_envelope = data.get("attestations", [{}])[0].get("bundle", {}).get("dsseEnvelope", {})
if "payload" not in dsse_envelope:
print("No payload in attestation")
sys.exit(1)

decoded_dsse_payload = base64.b64decode(dsse_envelope["payload"])

dsse_object = json.loads(decoded_dsse_payload)
ci_filename = dsse_object["subject"][0]["name"]
ci_hashes = dsse_object["subject"][0]["digest"]
print(f"Artifact: {ci_filename}")
for hash in ci_hashes.keys():
print(f" {hash}: {ci_hashes[hash]}")

predicate = dsse_object["predicate"]
build_definition = predicate["buildDefinition"]
run_details = predicate["runDetails"]

build_commit = build_definition["resolvedDependencies"][0]["digest"]["gitCommit"]
print(f" Commit: {build_commit}")
invocation_id = run_details["metadata"]["invocationId"]
print(f" Run: {invocation_id}")

if __name__ == "__main__":
# Command: load-attestation.py [-o <owner> -r <repo>] <file-path>
args = parse_arguments()

print(f"Fetching attestation for {args.file_path} from {args.owner}/{args.repo}")
file_hash = get_file_sha256(args.file_path)
attestation = load_attestation_from_gh_api(args.owner, args.repo, file_hash)
print_attestation(attestation)
Loading