diff --git a/.github/workflows/conventional-commit.yaml b/.github/workflows/conventional-commit.yaml new file mode 100644 index 0000000..eb23a97 --- /dev/null +++ b/.github/workflows/conventional-commit.yaml @@ -0,0 +1,117 @@ +name: โœ’๏ธ Conventional Commits + +on: + pull_request_target: + paths-ignore: + - 'doc/**' + - '*.md' + branches: + - master + - release/** + +permissions: + contents: read + pull-requests: write + +jobs: + conventional-commits: + name: ๐Ÿ“œ Parse PR commits + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ”Ž Check PR commit messages follow Conventional Commits + uses: actions/github-script@v8 + with: + script: | + const owner = context.repo.owner; + const repo = context.repo.repo; + const pull_number = context.payload.pull_request.number; + + const marker = ""; + + // Conventional Commits v1.0.0 summary line regex + const re = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([^)]+\))?(!)?:\s\S.+/; + + const commits = await github.paginate( + github.rest.pulls.listCommits, + { owner, repo, pull_number, per_page: 100 } + ); + + const invalid = []; + for (const c of commits) { + const summary = c.commit.message.split("\n")[0]; + if (!re.test(summary)) { + invalid.push({ + sha: c.sha.substring(0, 7), + message: summary, + }); + } + } + + // Find existing bot comment (if any) + const comments = await github.paginate( + github.rest.issues.listComments, + { owner, repo, issue_number: pull_number } + ); + + const existing = comments.find( + c => c.user?.type === "Bot" && c.body?.includes(marker) + ); + + if (invalid.length > 0) { + const body = + `${marker} + ### โŒ Conventional Commits check failed + + One or more commit messages in this PR do **not** follow the + [Conventional Commits v1.0.0](https://www.conventionalcommits.org/en/v1.0.0/) specification. + + **Invalid commits:** + ${invalid.map(i => `- \`${i.sha}\` โ€” ${i.message}`).join("\n")} + + **Expected format** + \`\`\` + type(scope?)!?: subject + \`\`\` + + **Examples** + - \`feat: add user login\` + - \`fix(api): handle null response\` + - \`chore!: drop node 16 support\` + + Please fix the commit messages (e.g. via \`git rebase -i\`) and push again.`; + + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: pull_number, + body, + }); + } + + core.setFailed( + `${invalid.length} commit(s) do not follow Conventional Commits` + ); + } else { + // If previously failed, clean up the comment + if (existing) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existing.id, + body: `${marker} + ### โœ… Conventional Commits check passed + + All commit messages in this PR now follow the Conventional Commits specification. ๐ŸŽ‰`, + }); + } + + core.info(`All ${commits.length} commit(s) follow Conventional Commits.`); + } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4fbebd0..4876ed7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,9 @@ -name: 020-Release +name: ๐Ÿ“ข Release on: workflow_run: workflows: - - 010-Test + - ๐Ÿงช Test types: [completed] branches: - master @@ -18,19 +18,17 @@ name: ๐Ÿค– Semantic release runs-on: ubuntu-latest if: "!contains(github.event.pull_request.labels.*.name, 'skip-release')" - # if: ${{ github.ref_name == 'master' && github.event_name == 'push' }} outputs: release: ${{ steps.tag_release.outputs.release }} version: ${{ steps.tag_release.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v6 with: node-version: latest - name: Install semantic-release run: | - npm i npx npm i semantic-release/changelog - name: Tag release id: tag_release @@ -51,7 +49,7 @@ needs: [semantic-release] if: ${{ needs.semantic-release.outputs.release == 'True' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: apt install deps run: | sudo apt-get update -y -q @@ -62,22 +60,22 @@ cmake -G "Ninja" ../ ninja - name: Upload linux filter - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-linux-filter path: build/src/filter/**/*.so - name: Upload linux mixer2 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-linux-mixer2 path: build/src/mixer2/**/*.so - name: Upload linux mixer3 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-linux-mixer3 path: build/src/mixer3/**/*.so - name: Upload linux generator - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-linux-generator path: build/src/generator/**/*.so @@ -88,34 +86,34 @@ needs: [semantic-release] if: ${{ needs.semantic-release.outputs.release == 'True' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: ilammy/msvc-dev-cmd@v1 - name: choco install deps - uses: crazy-max/ghaction-chocolatey@v2 + uses: crazy-max/ghaction-chocolatey@v3 with: args: install libopencv-dev - name: Build using nmake run: | mkdir build && cd build - cmake -G "NMake Makefiles" ../ + cmake -G "NMake Makefiles" -D WITHOUT_OPENCV=1 -D WITHOUT_CAIRO=1 -D WITHOUT_GAVL=1 ../ nmake - name: Upload win64 filter - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-win64-filter path: build/src/filter/**/*.dll - name: Upload win64 mixer2 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-win64-mixer2 path: build/src/mixer2/**/*.dll - name: Upload win64 mixer3 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-win64-mixer3 path: build/src/mixer3/**/*.dll - name: Upload win64 generator - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-win64-generator path: build/src/generator/**/*.dll @@ -126,7 +124,7 @@ needs: [semantic-release] if: ${{ needs.semantic-release.outputs.release == 'True' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Update Homebrew run: | brew update @@ -137,25 +135,25 @@ - name: Build using ninja run: | mkdir build && cd build - cmake -G "Ninja" ../ + cmake -G "Ninja" -D WITHOUT_OPENCV=1 -D WITHOUT_GAVL=1 ../ ninja - name: Upload osx filter - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-osx-filter path: build/src/filter/**/*.so - name: Upload osx mixer2 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-osx-mixer2 path: build/src/mixer2/**/*.so - name: Upload osx mixer3 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-osx-mixer3 path: build/src/mixer3/**/*.so - name: Upload osx generator - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-osx-generator path: build/src/generator/**/*.so @@ -166,9 +164,9 @@ if: ${{ needs.semantic-release.outputs.release == 'True' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: download binary artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v7 with: path: | frei0r-bin @@ -219,7 +217,7 @@ sha256sum *.zip *.tar.gz > SHA256SUMS.txt - name: release all archives - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: | *.zip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8943f4c..669bdba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: 010-Test +name: ๐Ÿงช Test on: push: @@ -22,20 +22,12 @@ cancel-in-progress: true jobs: - - # reuse: - # name: ๐Ÿšจ REUSE Compliance - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v4 - # - uses: fsfe/reuse-action@v1 - c-lint: name: ๐Ÿšจ C lint runs-on: ubuntu-latest if: "!contains(github.event.pull_request.labels.*.name, 'skip-lint')" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: reviewdog/action-cpplint@master env: REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -75,7 +67,7 @@ fail-fast: false runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: install dependencies run: | sudo apt-get update -qy @@ -91,7 +83,7 @@ run: | cd test && make - name: ${{ matrix.compiler }} upload plugin analysis - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: release-plugin-analysis path: test/*.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bb5b8c..dd0e14a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,15 +11,18 @@ option (WITHOUT_FACERECOGNITION "Disable facedetect plugin to avoid protobuf conflicts" OFF) if (NOT WITHOUT_OPENCV) - find_package (OpenCV) + find_package (OpenCV REQUIRED) endif () -find_package (Cairo) +option (WITHOUT_CAIRO "Disable plugins dependent upon gavl" OFF) +if (NOT WITHOUT_CAIRO) + find_package (Cairo REQUIRED) +endif () include(FindPkgConfig) option (WITHOUT_GAVL "Disable plugins dependent upon gavl" OFF) if (PKG_CONFIG_FOUND AND NOT WITHOUT_GAVL) - pkg_check_modules(GAVL gavl) + pkg_check_modules(GAVL REQUIRED gavl) endif () include_directories (AFTER include) diff --git a/README.md b/README.md index b6d42f6..c8238fb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Frei0r logo](https://github.com/dyne/frei0r/raw/gh_pages/pics/frei0r.png)](https://frei0r.dyne.org) +[![Frei0r logo](https://frei0r.dyne.org/pics/fla_name_lb.webp)](https://frei0r.dyne.org) diff --git a/src/filter/colorhalftone/colorhalftone.c b/src/filter/colorhalftone/colorhalftone.c index d2d74ba..1019e2f 100644 --- a/src/filter/colorhalftone/colorhalftone.c +++ b/src/filter/colorhalftone/colorhalftone.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "frei0r.h" #include "frei0r/math.h" @@ -73,6 +74,9 @@ int width = inst->width; int height = inst->height; + + // Copy input to output to preserve alpha channel + memcpy(outframe, inframe, width * height * sizeof(uint32_t)); double dotRadius = inst->dot_radius * 9.99; dotRadius = ceil(dotRadius); diff --git a/src/filter/curves/curves.c b/src/filter/curves/curves.c index f30181f..f72d066 100644 --- a/src/filter/curves/curves.c +++ b/src/filter/curves/curves.c @@ -573,11 +573,12 @@ int count = 0; char *input = strdup(string); char *result = NULL; - result = strtok_r(string, delimiter, &input); + char *saveptr; + result = strtok_r(input, delimiter, &saveptr); while (result != NULL) { *tokens = realloc(*tokens, (count + 1) * sizeof(char *)); (*tokens)[count++] = strdup(result); - result = strtok_r(NULL, delimiter, &input); + result = strtok_r(NULL, delimiter, &saveptr); } free(input); return count; diff --git a/src/filter/mirr0r/mirr0r.cpp b/src/filter/mirr0r/mirr0r.cpp index a6113db..f0526a9 100755 --- a/src/filter/mirr0r/mirr0r.cpp +++ b/src/filter/mirr0r/mirr0r.cpp @@ -17,9 +17,9 @@ * along with this program. If not, see . */ +#define _USE_MATH_DEFINES #include "frei0r.hpp" #include -#define _USE_MATH_DEFINES #include class Mirr0r : public frei0r::filter { @@ -133,4 +133,4 @@ "Johann JEG", 1, 0, F0R_COLOR_MODEL_RGBA8888); - \ No newline at end of file + diff --git a/src/filter/rgbsplit0r/rgbsplit0r.c b/src/filter/rgbsplit0r/rgbsplit0r.c index 0c57eae..c4116cb 100644 --- a/src/filter/rgbsplit0r/rgbsplit0r.c +++ b/src/filter/rgbsplit0r/rgbsplit0r.c @@ -207,7 +207,9 @@ // First make a blue layer shifted back if (((int)x >= (int)inst->shiftX) && - ((int)y >= (int)inst->shiftY)) + ((int)y >= (int)inst->shiftY) && + ((x - inst->shiftX) < inst->width) && + ((y - inst->shiftY) < inst->height)) { rgbsplit0r_extract_color((uint32_t *)(src + (x - inst->shiftX) +