|
1 | | -name: Build |
| 1 | +name: Build and Release |
2 | 2 |
|
3 | 3 | on: |
4 | 4 | push: |
5 | 5 | branches: [ "master" ] |
6 | 6 | pull_request: |
7 | 7 | branches: [ "master" ] |
| 8 | + workflow_dispatch: |
| 9 | + inputs: |
| 10 | + create_release: |
| 11 | + description: 'Create a new release' |
| 12 | + required: false |
| 13 | + type: boolean |
| 14 | + default: false |
| 15 | + schedule: |
| 16 | + # Check for updates daily at 2 AM UTC |
| 17 | + - cron: '0 2 * * *' |
8 | 18 |
|
9 | 19 | env: |
10 | 20 | BUILD_TYPE: Release |
11 | 21 |
|
12 | 22 | jobs: |
| 23 | + # First, check if there are new Binary Ninja versions |
| 24 | + check-versions: |
| 25 | + runs-on: ubuntu-latest |
| 26 | + outputs: |
| 27 | + should_build: ${{ steps.check.outputs.should_build }} |
| 28 | + versions_matrix: ${{ steps.check.outputs.versions_matrix }} |
| 29 | + steps: |
| 30 | + - uses: actions/checkout@v4 |
| 31 | + with: |
| 32 | + submodules: 'true' |
| 33 | + fetch-depth: 0 |
| 34 | + |
| 35 | + - name: Check for new versions |
| 36 | + id: check |
| 37 | + run: | |
| 38 | + cd binaryninjaapi |
| 39 | + git fetch --tags origin |
| 40 | + |
| 41 | + # Always include dev |
| 42 | + VERSIONS_JSON='[ |
| 43 | + {"name": "dev", "filename": "dev", "short_name": "dev", "full_version": "dev"} |
| 44 | + ]' |
| 45 | + |
| 46 | + # Parse stable versions and filter for build numbers >= 7290 |
| 47 | + MIN_BUILD=7290 |
| 48 | + |
| 49 | + # Get all tags that match either format: v*-stable or stable/* |
| 50 | + ALL_TAGS=$(git tag -l 'v*-stable' 'stable/*' | sort -V) |
| 51 | + |
| 52 | + for tag in $ALL_TAGS; do |
| 53 | + # Extract version number based on tag format |
| 54 | + if [[ $tag == v*-stable ]]; then |
| 55 | + # Old format: v5.0.7648-stable |
| 56 | + VERSION=$(echo $tag | sed 's/^v//' | sed 's/-stable$//') |
| 57 | + elif [[ $tag == stable/* ]]; then |
| 58 | + # New format: stable/5.0.7648 |
| 59 | + VERSION=$(echo $tag | sed 's|stable/||') |
| 60 | + else |
| 61 | + continue |
| 62 | + fi |
| 63 | + |
| 64 | + # Extract last 4 digits (build number) |
| 65 | + BUILD_NUM=$(echo $VERSION | grep -oE '[0-9]{4}$') |
| 66 | + |
| 67 | + # Only include if build number >= 7290 |
| 68 | + if [[ ! -z "$BUILD_NUM" ]] && [[ $BUILD_NUM -ge $MIN_BUILD ]]; then |
| 69 | + echo "Including version: $tag (build $BUILD_NUM, full version $VERSION)" |
| 70 | + VERSIONS_JSON=$(echo $VERSIONS_JSON | jq --arg name "$tag" --arg filename "v$VERSION-stable" --arg short "$BUILD_NUM" --arg fullver "$VERSION" '. += [{"name": $name, "filename": $filename, "short_name": $short, "full_version": $fullver}]') |
| 71 | + else |
| 72 | + echo "Skipping version: $tag (build $BUILD_NUM < $MIN_BUILD)" |
| 73 | + fi |
| 74 | + done |
| 75 | + |
| 76 | + echo "versions_matrix=$VERSIONS_JSON" >> $GITHUB_OUTPUT |
| 77 | + echo "Final versions matrix:" |
| 78 | + echo "$VERSIONS_JSON" | jq '.' |
| 79 | + |
| 80 | + # Check if this is a scheduled run or manual dispatch with create_release |
| 81 | + if [[ "${{ github.event_name }}" == "schedule" ]] || [[ "${{ inputs.create_release }}" == "true" ]]; then |
| 82 | + echo "should_build=true" >> $GITHUB_OUTPUT |
| 83 | + else |
| 84 | + echo "should_build=false" >> $GITHUB_OUTPUT |
| 85 | + fi |
| 86 | +
|
13 | 87 | build: |
14 | | - runs-on: ${{matrix.config.os}} |
| 88 | + needs: check-versions |
| 89 | + if: needs.check-versions.outputs.should_build == 'true' || github.event_name == 'push' || github.event_name == 'pull_request' |
| 90 | + runs-on: ${{ matrix.config.os }} |
15 | 91 | strategy: |
16 | 92 | matrix: |
17 | 93 | config: |
18 | 94 | - { |
19 | | - os: windows-2025, |
20 | | - name: windows |
| 95 | + os: windows-latest, |
| 96 | + name: windows, |
| 97 | + ext: dll |
21 | 98 | } |
22 | 99 | - { |
23 | 100 | os: macos-13, |
24 | | - name: macos |
| 101 | + name: macos, |
| 102 | + ext: dylib |
25 | 103 | } |
26 | 104 | - { |
27 | 105 | os: ubuntu-24.04, |
28 | | - name: ubuntu |
| 106 | + name: ubuntu, |
| 107 | + ext: so |
29 | 108 | } |
30 | | - version: |
31 | | - - name: v5.0.7290-stable |
32 | | - filename: v5.0.7290-stable |
33 | | - - name: v5.0.7648-stable |
34 | | - filename: v5.0.7648-stable |
35 | | - - name: stable/5.1.8005 |
36 | | - filename: v5.1.8005-stable |
37 | | - - name: stable/5.1.8104 |
38 | | - filename: v5.1.8104-stable |
39 | | - - name: dev |
40 | | - filename: dev |
| 109 | + version: ${{ fromJson(needs.check-versions.outputs.versions_matrix) }} |
| 110 | + |
41 | 111 | steps: |
42 | | - - uses: actions/checkout@v3 |
| 112 | + - uses: actions/checkout@v4 |
43 | 113 | with: |
44 | 114 | submodules: 'true' |
| 115 | + |
45 | 116 | - uses: seanmiddleditch/gha-setup-ninja@master |
| 117 | + |
46 | 118 | - uses: ilammy/msvc-dev-cmd@v1 |
| 119 | + if: matrix.config.name == 'windows' |
| 120 | + |
47 | 121 | - name: Update submodule |
48 | 122 | run: | |
49 | 123 | cd binaryninjaapi |
50 | 124 | git fetch --tags |
51 | | - git checkout --force ${{matrix.version.name}} |
| 125 | + git checkout --force ${{ matrix.version.name }} |
52 | 126 | git submodule update --init --recursive |
| 127 | + |
53 | 128 | - name: Configure CMake |
54 | 129 | run: cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} |
| 130 | + |
55 | 131 | - name: Build |
56 | 132 | run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} |
| 133 | + |
| 134 | + - name: Rename artifacts |
| 135 | + shell: bash |
| 136 | + run: | |
| 137 | + cd ${{github.workspace}}/build |
| 138 | + |
| 139 | + # Find the built library |
| 140 | + if [[ "${{ matrix.config.ext }}" == "dll" ]]; then |
| 141 | + ORIGINAL=$(find . -name "*NativePredicateSolver.dll" -o -name "*NativePredicateSolver*.dll" | head -n 1) |
| 142 | + elif [[ "${{ matrix.config.ext }}" == "so" ]]; then |
| 143 | + ORIGINAL=$(find . -name "libNativePredicateSolver.so" -o -name "libNativePredicateSolver*.so" | head -n 1) |
| 144 | + else |
| 145 | + ORIGINAL=$(find . -name "libNativePredicateSolver.dylib" -o -name "libNativePredicateSolver*.dylib" | head -n 1) |
| 146 | + fi |
| 147 | + |
| 148 | + if [[ -z "$ORIGINAL" ]]; then |
| 149 | + echo "Error: Could not find built library" |
| 150 | + exit 1 |
| 151 | + fi |
| 152 | + |
| 153 | + # Determine new name based on version (consistent across all platforms) |
| 154 | + if [[ "${{ matrix.version.full_version }}" == "dev" ]]; then |
| 155 | + NEW_NAME="NativePredicateSolver-dev.${{ matrix.config.ext }}" |
| 156 | + else |
| 157 | + NEW_NAME="NativePredicateSolver-${{ matrix.version.full_version }}.${{ matrix.config.ext }}" |
| 158 | + fi |
| 159 | + |
| 160 | + echo "Renaming $ORIGINAL to $NEW_NAME" |
| 161 | + cp "$ORIGINAL" "$NEW_NAME" |
| 162 | + echo "artifact_name=$NEW_NAME" >> $GITHUB_ENV |
| 163 | + |
57 | 164 | - name: Upload artifact |
58 | 165 | uses: actions/upload-artifact@v4 |
59 | 166 | with: |
60 | | - name: ${{matrix.config.name}}-${{matrix.version.filename}} |
61 | | - path: ${{github.workspace}}/build/*NativePredicateSolver* |
| 167 | + name: ${{ matrix.config.name }}-${{ matrix.version.filename }} |
| 168 | + path: ${{ github.workspace }}/build/${{ env.artifact_name }} |
| 169 | + |
| 170 | + create-release: |
| 171 | + needs: [check-versions, build] |
| 172 | + if: needs.check-versions.outputs.should_build == 'true' || github.event.inputs.create_release == 'true' |
| 173 | + runs-on: ubuntu-latest |
| 174 | + permissions: |
| 175 | + contents: write |
| 176 | + |
| 177 | + steps: |
| 178 | + - uses: actions/checkout@v4 |
| 179 | + |
| 180 | + - name: Download all artifacts |
| 181 | + uses: actions/download-artifact@v4 |
| 182 | + with: |
| 183 | + path: artifacts |
| 184 | + |
| 185 | + - name: Organize artifacts |
| 186 | + run: | |
| 187 | + mkdir -p release_files |
| 188 | + find artifacts -type f \( -name "*.dll" -o -name "*.so" -o -name "*.dylib" \) -exec cp {} release_files/ \; |
| 189 | + ls -la release_files/ |
| 190 | + |
| 191 | + - name: Generate release notes |
| 192 | + id: release_notes |
| 193 | + run: | |
| 194 | + RELEASE_DATE=$(date +'%Y-%m-%d %H:%M:%S UTC') |
| 195 | + cat > release_notes.md << 'EOF' |
| 196 | + ## 🤖 Automated Build |
| 197 | + |
| 198 | + This release was automatically generated by GitHub Actions. |
| 199 | + |
| 200 | + **Build Date:** $RELEASE_DATE |
| 201 | + **Trigger:** ${{ github.event_name }} |
| 202 | + |
| 203 | + ### 📦 Included Builds |
| 204 | + |
| 205 | + This release contains builds for the following Binary Ninja versions: |
| 206 | + |
| 207 | + EOF |
| 208 | + |
| 209 | + # Add version info |
| 210 | + echo "${{ needs.check-versions.outputs.versions_matrix }}" | jq -r '.[] | "- **Version \(.full_version)**: Build `\(.short_name)`"' >> release_notes.md |
| 211 | + |
| 212 | + cat >> release_notes.md << 'EOF' |
| 213 | + |
| 214 | + ### 📥 Installation |
| 215 | + |
| 216 | + 1. Download the appropriate file for your platform and Binary Ninja version |
| 217 | + 2. Place it in your Binary Ninja plugins directory |
| 218 | + 3. Restart Binary Ninja |
| 219 | + |
| 220 | + ### 🔧 File Naming Convention |
| 221 | + |
| 222 | + All platforms use the same naming format: |
| 223 | + |
| 224 | + - **Stable versions**: `NativePredicateSolver-[full-version].[ext]` |
| 225 | + - Example: `NativePredicateSolver-5.0.7290.dll`, `NativePredicateSolver-5.1.8104.so` |
| 226 | + - **Dev version**: `NativePredicateSolver-dev.[ext]` |
| 227 | + - Example: `NativePredicateSolver-dev.dll`, `NativePredicateSolver-dev.dylib` |
| 228 | + |
| 229 | + --- |
| 230 | + |
| 231 | + **Commit:** ${{ github.sha }} |
| 232 | + EOF |
| 233 | + |
| 234 | + cat release_notes.md |
| 235 | + |
| 236 | + - name: Create Release |
| 237 | + uses: softprops/action-gh-release@v1 |
| 238 | + with: |
| 239 | + tag_name: build-${{ github.run_number }}-${{ github.sha }} |
| 240 | + name: Automated Build ${{ github.run_number }} |
| 241 | + body_path: release_notes.md |
| 242 | + files: release_files/* |
| 243 | + draft: false |
| 244 | + prerelease: false |
| 245 | + env: |
| 246 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
0 commit comments