Skip to content
Open
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
161 changes: 161 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Release

on:
push:
branches: [main]
workflow_dispatch:
inputs:
version_type:
description: 'Version bump type'
required: true
default: 'auto'
type: choice
options:
- auto
- patch
- minor
- major
custom_version:
description: 'Custom version (optional, overrides version_type)'
required: false
type: string

jobs:
release:
runs-on: ubuntu-latest
if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Determine version bump
id: version
run: |
# Get current version from CMakeLists.txt
CURRENT_VERSION=$(grep "project(c2pa-c VERSION" CMakeLists.txt | sed -n 's/.*VERSION \([0-9.]*\).*/\1/p')
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT

# Determine bump type based on trigger
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
# Manual trigger
if [ -n "${{ github.event.inputs.custom_version }}" ]; then
NEW_VERSION="${{ github.event.inputs.custom_version }}"
BUMP="custom"
else
MANUAL_BUMP="${{ github.event.inputs.version_type }}"
if [ "$MANUAL_BUMP" = "auto" ]; then
# Auto-detect from recent commits
COMMITS=$(git log HEAD~5..HEAD --oneline)
if echo "$COMMITS" | grep -qE "^[a-f0-9]+ (feat!|BREAKING CHANGE)"; then
BUMP="major"
elif echo "$COMMITS" | grep -qE "^[a-f0-9]+ feat"; then
BUMP="minor"
elif echo "$COMMITS" | grep -qE "^[a-f0-9]+ (fix|chore|docs)"; then
BUMP="patch"
else
BUMP="patch" # Default for manual
fi
else
BUMP="$MANUAL_BUMP"
fi
fi
else
# Automatic trigger from push
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
COMMITS=$(git log $LAST_TAG..HEAD --oneline)

if echo "$COMMITS" | grep -qE "^[a-f0-9]+ (feat!|BREAKING CHANGE)"; then
BUMP="major"
elif echo "$COMMITS" | grep -qE "^[a-f0-9]+ feat"; then
BUMP="minor"
elif echo "$COMMITS" | grep -qE "^[a-f0-9]+ (fix|chore|docs)"; then
BUMP="patch"
else
echo "No version bump needed"
exit 0
fi
fi

# Calculate new version if not custom
if [ "$BUMP" != "custom" ]; then
IFS='.' read -r major minor patch <<< "$CURRENT_VERSION"
case $BUMP in
major) NEW_VERSION="$((major + 1)).0.0" ;;
minor) NEW_VERSION="$major.$((minor + 1)).0" ;;
patch) NEW_VERSION="$major.$minor.$((patch + 1))" ;;
esac
fi

echo "bump_type=$BUMP" >> $GITHUB_OUTPUT
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "Version bump: $CURRENT_VERSION -> $NEW_VERSION ($BUMP)"

- name: Update version in CMakeLists.txt
if: steps.version.outputs.new_version != ''
run: |
NEW_VERSION=${{ steps.version.outputs.new_version }}
sed -i "s/project(c2pa-c VERSION [0-9.]*)/project(c2pa-c VERSION $NEW_VERSION)/" CMakeLists.txt
echo "Updated version to $NEW_VERSION"

- name: Install dependencies
if: steps.version.outputs.new_version != ''
run: |
sudo apt-get update
sudo apt-get install -y ninja-build

- name: Run tests
if: steps.version.outputs.new_version != ''
run: |
echo "Running tests before release..."
make test # Debug build and test
make test-release # Release build and test
echo "✅ All tests passed!"

- name: Commit version bump
if: steps.version.outputs.new_version != ''
run: |
NEW_VERSION=${{ steps.version.outputs.new_version }}

git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add CMakeLists.txt
git commit -m "chore(release): $NEW_VERSION [skip ci]"
git push

- name: Create tag and release
if: steps.version.outputs.new_version != ''
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
NEW_VERSION=${{ steps.version.outputs.new_version }}

# Create and push tag
git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION"
git push origin "v$NEW_VERSION"

# Generate release notes
LAST_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
if [ -n "$LAST_TAG" ]; then
COMMITS=$(git log $LAST_TAG..HEAD --oneline --no-merges)
COMPARE_URL="https://github.com/${{ github.repository }}/compare/$LAST_TAG...v$NEW_VERSION"
else
COMMITS=$(git log --oneline --no-merges -10)
COMPARE_URL="https://github.com/${{ github.repository }}/commits/main"
fi

# Create release
cat > release_notes.md << EOF
## What's Changed

$COMMITS

**Full Changelog**: $COMPARE_URL
EOF

gh release create "v$NEW_VERSION" \
--title "Release v$NEW_VERSION" \
--notes-file release_notes.md
20 changes: 20 additions & 0 deletions .github/workflows/update_c2pa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ jobs:
run: |
version="${{ github.event.inputs.c2pa_version }}"
sed -i "s/set(C2PA_VERSION \".*\")/set(C2PA_VERSION \"${version}\")/" CMakeLists.txt
echo "Updated C2PA_VERSION to $version"

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y ninja-build

- name: Test with new c2pa-rs version
run: |
echo "Testing with c2pa-rs version ${{ github.event.inputs.c2pa_version }}..."

# Test using our Makefile targets
make test # Debug build and test
make test-release # Release build and test

echo "✅ All tests passed with c2pa-rs ${{ github.event.inputs.c2pa_version }}"

- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
Expand All @@ -27,3 +43,7 @@ jobs:
title: "Bump C2PA_VERSION to ${{ github.event.inputs.c2pa_version }}"
body: |
This PR updates C2PA_VERSION in CMakeLists.txt to ${{ github.event.inputs.c2pa_version }}.

✅ **Tests Status**: All tests (debug and release builds) have passed with the new c2pa-rs version.

The new version should be compatible and ready for integration.
21 changes: 17 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,26 @@ release:
cmake: release

# Test targets

test: debug
cd $(DEBUG_BUILD_DIR) && ctest --output-on-failure

test-release: release
cd $(RELEASE_BUILD_DIR) && ctest --output-on-failure

# Demo targets
demo: release
demo: debug
cmake --build $(DEBUG_BUILD_DIR) --target demo
$(DEBUG_BUILD_DIR)/examples/demo

demo-release: release
cmake --build $(RELEASE_BUILD_DIR) --target demo
$(RELEASE_BUILD_DIR)/examples/demo

training: release
training: debug
cmake --build $(DEBUG_BUILD_DIR) --target training
$(DEBUG_BUILD_DIR)/examples/training

training-release: release
cmake --build $(RELEASE_BUILD_DIR) --target training
$(RELEASE_BUILD_DIR)/examples/training

Expand All @@ -42,5 +50,10 @@ examples: training demo
clean:
rm -rf $(BUILD_DIR)

.PHONY: all debug release cmake test test-release demo training examples clean
clean-debug:
rm -rf $(DEBUG_BUILD_DIR)

clean-release:
rm -rf $(RELEASE_BUILD_DIR)

.PHONY: all debug release cmake test test-release demo training examples clean
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,21 @@ make release
```

The Makefile has a number of other targets; for example:
- `unit-tests` to run C++ unit tests
- `examples` to build and run the C++ examples.
- `all` to run everything.
- `debug` to build in debug mode
- `release` to build in optimized release mode
- `test` to run all tests (debug build)
- `test-release` to run all tests (release build)
- `examples` to build and run the C++ examples
- `all` to run tests and examples

Results are saved in the `build` directory.
Results are saved in the `build/debug` and `build/release` directories.

### Testing

Build the [unit tests](https://github.com/contentauth/c2pa-c/tree/main/tests) by entering this `make` command:

```
make unit-test
make test
```

## License
Expand Down
28 changes: 1 addition & 27 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,6 @@ function(setup_c2pa_runtime_deps target_name)
COMMAND ${CMAKE_COMMAND} -E echo "Copied ${C2PA_C_LIB} to $<TARGET_FILE_DIR:${target_name}>"
COMMENT "Copying c2pa_c library to ${target_name} directory"
)

# On Windows, copy all DLLs from the prebuilt lib directory
if(WIN32)
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "=== Windows DLL Debug Info for ${target_name} ==="
COMMAND ${CMAKE_COMMAND} -E echo "Listing prebuilt lib directory contents:"
COMMAND ${CMAKE_COMMAND} -E echo "Skipping directory listing due to Windows path issues"
COMMAND ${CMAKE_COMMAND} -E echo "Target directory contents:"
COMMAND cmd /c "dir \"$<TARGET_FILE_DIR:${target_name}>\"" || echo "Failed to list target directory"
COMMENT "Windows DLL debugging for ${target_name}"
)
else()
add_custom_command(TARGET ${target_name} POST_BUILD
COMMAND ls -la $<TARGET_FILE_DIR:${target_name}> || echo "Failed to list directory"
)
endif()
endif()

# On Linux, set RPATH to look in the executable's directory
Expand Down Expand Up @@ -74,17 +58,7 @@ setup_c2pa_runtime_deps(c2pa_c_tests)

include(GoogleTest)

# Add debug commands to check what's happening on Linux
if(UNIX AND NOT APPLE)
add_test(NAME debug_rpath_info
COMMAND bash -c "echo '=== RPATH Debug Info ===' && echo 'Working dir:' && pwd && echo 'Library files in tests dir:' && ls -la ${CMAKE_BINARY_DIR}/tests/ && echo 'RPATH of c2pa_c_tests:' && readelf -d ${CMAKE_BINARY_DIR}/tests/c2pa_c_tests | grep -E '(RPATH|RUNPATH)' && echo 'RPATH of ctest:' && readelf -d ${CMAKE_BINARY_DIR}/tests/ctest | grep -E '(RPATH|RUNPATH)' && echo 'ldd output for c2pa_c_tests:' && ldd ${CMAKE_BINARY_DIR}/tests/c2pa_c_tests"
)

add_test(NAME debug_library_location
COMMAND bash -c "echo '=== Library Location Debug ===' && echo 'Current dir:' && pwd && echo 'Contents of build/debug:' && ls -la ${CMAKE_BINARY_DIR}/ && echo 'Contents of _deps:' && ls -la ${CMAKE_BINARY_DIR}/_deps/ && echo 'Contents of prebuilt lib:' && ls -la ${CMAKE_BINARY_DIR}/_deps/c2pa_prebuilt-src/lib/ && echo 'Does the relative path exist from tests dir?' && ls -la ${CMAKE_BINARY_DIR}/tests/../_deps/c2pa_prebuilt-src/lib/"
)
endif()

# C++ test registration
# For better reliability, especially on Linux, manually add tests instead of auto-discovery
# This avoids the working directory and library path issues during discovery
if(WIN32)
Expand Down
17 changes: 11 additions & 6 deletions tests/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@

int main(void)
{
// Clean up any existing test output files
remove("build/tmp/earth1.jpg");
remove("build/tmp/earth2.jpg");
remove("build/tmp/earth3.jpg");
remove("build/tmp/earth1.pem");
remove("build/tmp/archive.zip");
remove("build/thumb_c.jpg");

char *version = c2pa_version();
assert_contains("version", version, "c2pa-c-ffi/0.");

Expand Down Expand Up @@ -71,12 +79,10 @@ int main(void)
// create a sign_info struct (using positional initialization to avoid designated initializers)
C2paSignerInfo sign_info = {"es256", certs, private_key, "http://timestamp.digicert.com"};

// Remove the file if it exists
remove("build/tmp/earth.jpg");
result = c2pa_sign_file("tests/fixtures/C.jpg", "build/tmp/earth.jpg", manifest, &sign_info, "tests/fixtures");
result = c2pa_sign_file("tests/fixtures/C.jpg", "build/tmp/earth1.jpg", manifest, &sign_info, "tests/fixtures");
assert_not_null("c2pa_sign_file_ok", result);

remove("build/tmp/earth2.jpg");

result = c2pa_sign_file("tests/fixtures/foo.jpg", "build/tmp/earth2.jpg", manifest, &sign_info, "tests/fixtures");
assert_null("c2pa_sign_file_not_found", result, "FileNotFound");

Expand All @@ -101,8 +107,7 @@ int main(void)
assert_not_null("c2pa_signer_create", signer);

C2paStream *source = open_file_stream("tests/fixtures/C.jpg", "rb");
remove("build/tmp/earth4.jpg");
C2paStream *dest = open_file_stream("build/tmp/earth4.jpg", "wb");
C2paStream *dest = open_file_stream("build/tmp/earth3.jpg", "wb");

const unsigned char *manifest_bytes = NULL; // todo: test passing NULL instead of a pointer
int result2 = c2pa_builder_sign(builder2, "image/jpeg", source, dest, signer, &manifest_bytes);
Expand Down