Packaging: the binary and package are inbuxa, INBUXA_* settings with STALWART_* fallback
- crates/main: package and [[bin]] renamed to inbuxa; homepage inbuxa.org; license AGPL-3.0-only (upstream is dual; the fork takes the AGPL). - types::branding::env_var reads INBUXA_<name>, falling back to STALWART_<name> with a warning, for all nine server settings. STALWART_APP_ and STALWART_SPAM_* storage keys are unchanged. - New-install default paths /var/lib/inbuxa and /var/log/inbuxa. - Dockerfiles, systemd unit, launchd plist and AppArmor profile renamed. - Upstream's .github moved to .github-upstream so none of it runs. - install.sh stubbed: upstream's would install Stalwart. - Two missed brand strings: the SMTP Received header and the utils user agent.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
> [!IMPORTANT]
|
||||
> **Stalwart support has moved to [support.stalw.art](https://support.stalw.art).**
|
||||
>
|
||||
> For an official response from the Stalwart maintainers, please post your question on the support portal. You can sign in there with your existing GitHub account; no separate registration is required.
|
||||
>
|
||||
> You are welcome to start a discussion here and other community members may still reply, but the maintainers no longer answer support questions through GitHub Discussions, so your question may go unanswered unless you also post it at [support.stalw.art](https://support.stalw.art).
|
||||
>
|
||||
> Before opening a new report, please review the [documentation](https://stalw.art/docs/) and the [FAQ](https://stalw.art/docs/faq). Most reported issues turn out to be configuration problems rather than actual bugs.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Topic
|
||||
description: Describe the question, problem, or topic you want to discuss with the community.
|
||||
placeholder: |
|
||||
I am trying to configure SMTP relay with Stalwart and I am running into ...
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Acknowledgement
|
||||
options:
|
||||
- label: I have reviewed the [documentation](https://stalw.art/docs/) and the [FAQ](https://stalw.art/docs/faq) and confirm that my question is not addressed there.
|
||||
required: true
|
||||
- label: I understand that maintainers no longer answer support questions through GitHub Discussions, and that for an official response from the Stalwart team I need to post my question at [support.stalw.art](https://support.stalw.art).
|
||||
required: true
|
||||
- label: I agree to follow the project's [Code of Conduct](https://github.com/stalwartlabs/.github/blob/main/CODE_OF_CONDUCT.md).
|
||||
required: true
|
||||
@@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Report an Issue
|
||||
url: https://support.stalw.art
|
||||
about: Report a potential bug at support.stalw.art. Confirmed bugs will be converted to Issues. Sign in with your GitHub account.
|
||||
- name: Questions & Support
|
||||
url: https://support.stalw.art
|
||||
about: Get help with configuration, troubleshooting, or general questions at support.stalw.art. Sign in with your GitHub account.
|
||||
- name: Feature Requests
|
||||
url: https://support.stalw.art
|
||||
about: Suggest new features or improvements at support.stalw.art. Sign in with your GitHub account.
|
||||
- name: Join Stalwart's Reddit
|
||||
url: https://www.reddit.com/r/stalwartlabs
|
||||
about: Join our subreddit for community discussions and release announcements.
|
||||
- name: Join Stalwart's Discord
|
||||
url: https://discord.com/servers/stalwart-923615863037390889
|
||||
about: Join our Discord server for community chat and release announcements.
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Bug Report (auto-closed)
|
||||
description: Issues opened here are automatically closed. Please report bugs at support.stalw.art instead.
|
||||
labels: ["bug"]
|
||||
title: "🪲: "
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
> [!CAUTION]
|
||||
> **Issues opened directly in this repository are automatically closed and locked.**
|
||||
>
|
||||
> All bug reports must first be triaged at our support portal: **[support.stalw.art](https://support.stalw.art)**. If a maintainer confirms that your report is a genuine bug, they will create an Issue on your behalf; you do not need to (and should not) open one yourself.
|
||||
>
|
||||
> You can sign in to support.stalw.art with your existing GitHub account, so no separate registration is required.
|
||||
>
|
||||
> **What to do instead:**
|
||||
> - Suspected bug, question, or feature request? Post it at [support.stalw.art](https://support.stalw.art).
|
||||
>
|
||||
> If you proceed and submit this form anyway, your issue will be closed automatically and a comment will be posted explaining this policy.
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Acknowledgement
|
||||
options:
|
||||
- label: I understand that this issue will be automatically closed and that I should post my report at [support.stalw.art](https://support.stalw.art) instead.
|
||||
required: true
|
||||
@@ -0,0 +1,2 @@
|
||||
# GitHub usernames allowed to open pull requests directly.
|
||||
mdecimus
|
||||
@@ -0,0 +1,19 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "cargo" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
# Workflow files stored in the default location of `.github/workflows`
|
||||
# You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Auto-close untriaged issues
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
auto-close:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Close issues from non-allowed authors
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Users allowed to open issues directly. All other authors will have
|
||||
// their issues auto-closed. Add GitHub usernames (lowercase) here to
|
||||
// grant additional contributors permission to open issues.
|
||||
const allowedAuthors = [
|
||||
'mdecimus',
|
||||
];
|
||||
|
||||
const issue = context.payload.issue;
|
||||
const author = (issue.user && issue.user.login) || '';
|
||||
|
||||
if (allowedAuthors.includes(author.toLowerCase())) {
|
||||
core.info(`Issue #${issue.number} opened by allowed author '${author}'. Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const comment = [
|
||||
`Hi @${author}, thanks for taking the time to file this report.`,
|
||||
``,
|
||||
`This issue is being **automatically closed** because all bug reports must first be triaged at our support portal: **[support.stalw.art](https://support.stalw.art)**. Please re-post this report there so that a maintainer can review it; once confirmed as a bug, an Issue will be created on your behalf.`,
|
||||
``,
|
||||
`You can sign in to support.stalw.art with your existing GitHub account, so no separate registration is required.`,
|
||||
``,
|
||||
`Thank you for understanding.`,
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
body: comment,
|
||||
});
|
||||
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
state: 'closed',
|
||||
state_reason: 'not_planned',
|
||||
});
|
||||
|
||||
try {
|
||||
await github.rest.issues.lock({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
lock_reason: 'off-topic',
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(`Could not lock issue #${issue.number}: ${err.message}`);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
name: Auto-close PRs from non-allowed authors
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
auto-close:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
sparse-checkout: .github/allowed-pr-authors.txt
|
||||
sparse-checkout-cone-mode: false
|
||||
|
||||
- name: Close PRs from non-allowed authors
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
let allowedAuthors = [];
|
||||
try {
|
||||
allowedAuthors = fs.readFileSync('.github/allowed-pr-authors.txt', 'utf8')
|
||||
.split('\n')
|
||||
.map(line => line.trim())
|
||||
.filter(line => line && !line.startsWith('#'))
|
||||
.map(line => line.toLowerCase());
|
||||
} catch (err) {
|
||||
core.warning(`Could not read allowed-pr-authors.txt: ${err.message}`);
|
||||
}
|
||||
|
||||
const pr = context.payload.pull_request;
|
||||
const author = (pr.user && pr.user.login) || '';
|
||||
const login = author.toLowerCase();
|
||||
|
||||
if (author.endsWith('[bot]')) {
|
||||
core.info(`PR #${pr.number} opened by bot '${author}'. Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowedAuthors.includes(login)) {
|
||||
core.info(`PR #${pr.number} opened by allowed author '${author}'. Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const actor = (context.payload.sender && context.payload.sender.login) || '';
|
||||
|
||||
const isCollaborator = async (username) => {
|
||||
if (!username) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username,
|
||||
});
|
||||
return perm.permission === 'admin' || perm.permission === 'write';
|
||||
} catch (err) {
|
||||
core.info(`Could not resolve collaborator permission for '${username}': ${err.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
if (await isCollaborator(author)) {
|
||||
core.info(`PR #${pr.number} author '${author}' is a collaborator. Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (actor.toLowerCase() !== login && await isCollaborator(actor)) {
|
||||
core.info(`PR #${pr.number} action triggered by collaborator '${actor}'. Skipping.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const contributingUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/blob/HEAD/CONTRIBUTING.md`;
|
||||
|
||||
const haystack = `${pr.title || ''}\n${pr.body || ''}`;
|
||||
const aiPatterns = [
|
||||
/[—―]/,
|
||||
];
|
||||
const looksAiGenerated = aiPatterns.some(re => re.test(haystack));
|
||||
|
||||
const aiMessage = [
|
||||
`Hi @${author}, thanks for your interest in contributing.`,
|
||||
``,
|
||||
`This pull request is being **automatically closed and locked**. The description contains strong indicators of AI-generated content, and this project does not accept AI-generated code or unsolicited machine-authored contributions.`,
|
||||
``,
|
||||
`Please read [CONTRIBUTING.md](${contributingUrl}) to learn what kinds of contributions are currently accepted. If this is a genuine hand-written change that fits those guidelines, please open a discussion at **[support.stalw.art](https://support.stalw.art)** before submitting.`,
|
||||
].join('\n');
|
||||
|
||||
const standardMessage = [
|
||||
`Hi @${author}, thanks for taking the time to open this pull request.`,
|
||||
``,
|
||||
`This PR is being **automatically closed** because it was submitted by an author who is not on the list of approved contributors. This policy helps us keep review capacity focused and filter out unsolicited or low-quality contributions.`,
|
||||
``,
|
||||
`Please read [CONTRIBUTING.md](${contributingUrl}) to learn what kinds of contributions are currently accepted. If your change fits those guidelines, please first discuss it at our support portal: **[support.stalw.art](https://support.stalw.art)**. You can sign in with your existing GitHub account.`,
|
||||
``,
|
||||
`Thank you for understanding.`,
|
||||
].join('\n');
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: looksAiGenerated ? aiMessage : standardMessage,
|
||||
});
|
||||
|
||||
await github.rest.pulls.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed',
|
||||
});
|
||||
|
||||
if (looksAiGenerated) {
|
||||
try {
|
||||
await github.rest.issues.lock({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
lock_reason: 'spam',
|
||||
});
|
||||
} catch (err) {
|
||||
core.warning(`Could not lock PR #${pr.number}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Redirect new discussions to the support portal
|
||||
|
||||
on:
|
||||
discussion:
|
||||
types: [created]
|
||||
|
||||
permissions:
|
||||
discussions: write
|
||||
|
||||
jobs:
|
||||
redirect:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Post support portal redirect
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const discussion = context.payload.discussion;
|
||||
const author = (discussion.user && discussion.user.login) || '';
|
||||
|
||||
const body = [
|
||||
`Hi @${author}, thanks for posting!`,
|
||||
``,
|
||||
`Stalwart support has moved to **[support.stalw.art](https://support.stalw.art)**. The support portal is now the canonical place to ask questions, request help, and report issues for triage. Other community members may still reply here, but the maintainers no longer answer support questions through GitHub Discussions, so your question may go unanswered unless you also post it on the portal.`,
|
||||
``,
|
||||
`You can sign in to support.stalw.art with your existing GitHub account, so no separate registration is required. Google, Discord, LinkedIn, and email/password sign-in are also available.`,
|
||||
``,
|
||||
`**Why we are unifying our support channels**`,
|
||||
``,
|
||||
`Until now, Stalwart support has been spread across GitHub Discussions, Discord, Matrix, and Reddit. As the project has grown, tracking parallel inboxes and deduplicating threads has become unsustainable; the result has been slower answers, repeated work for the people helping out, and good information buried in chat scrollback where the next person with the same question would never find it.`,
|
||||
``,
|
||||
`[support.stalw.art](https://support.stalw.art) is a Discourse instance that we operate ourselves, hosted at Hetzner in Germany and GDPR-compliant.`,
|
||||
``,
|
||||
`Thank you for helping us keep the conversation in one place.`,
|
||||
].join('\n');
|
||||
|
||||
await github.graphql(
|
||||
`mutation($discussionId: ID!, $body: String!) {
|
||||
addDiscussionComment(input: { discussionId: $discussionId, body: $body }) {
|
||||
comment { id }
|
||||
}
|
||||
}`,
|
||||
{
|
||||
discussionId: discussion.node_id,
|
||||
body,
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,29 @@
|
||||
name: "CI retry"
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["CI"]
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
rerun:
|
||||
name: Re-run failed jobs
|
||||
if: >
|
||||
github.event.workflow_run.conclusion == 'failure' &&
|
||||
github.event.workflow_run.run_attempt < 3
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Re-run failed jobs
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.CI_RETRY_TOKEN || github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
RUN_ATTEMPT: ${{ github.event.workflow_run.run_attempt }}
|
||||
run: |
|
||||
set -eu
|
||||
echo "Run $RUN_ID failed on attempt $RUN_ATTEMPT, re-running failed jobs"
|
||||
sleep 60
|
||||
gh run rerun "$RUN_ID" --failed
|
||||
@@ -0,0 +1,567 @@
|
||||
name: "CI"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
Docker:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
Release:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
push:
|
||||
tags: ["v*.*.*"]
|
||||
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: true
|
||||
RUSTC_WRAPPER: sccache
|
||||
CARGO_TERM_COLOR: always
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
||||
AWS_LC_SYS_PREBUILT_NASM: 1
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
multiarch:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- variant: gnu
|
||||
- variant: musl
|
||||
name: Merge image / ${{matrix.variant}}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
attestations: write
|
||||
packages: write
|
||||
needs: [linux]
|
||||
if: github.event_name == 'push' || inputs.Docker
|
||||
steps:
|
||||
- name: Install Cosign
|
||||
uses: sigstore/[email protected]
|
||||
- name: Log In to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{github.repository_owner}}
|
||||
password: ${{github.token}}
|
||||
|
||||
- name: Log In to DockerHub
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
password: ${{secrets.DOCKERHUB_TOKEN}}
|
||||
|
||||
- name: Download ${{matrix.variant}} meta bake definition
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: bake-meta-${{matrix.variant}}
|
||||
path: ${{ runner.temp }}/${{matrix.variant}}
|
||||
|
||||
- name: Download ${{matrix.variant}} digests
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: ${{ runner.temp }}/${{matrix.variant}}/digests
|
||||
pattern: digests-${{matrix.variant}}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create ${{matrix.variant}} manifest list and push
|
||||
working-directory: ${{ runner.temp }}/${{matrix.variant}}/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.target."docker-metadata-action".tags | map(select(startswith("ghcr.io/${{github.repository}}")) | "-t " + .) | join(" ")' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json) \
|
||||
$(printf 'ghcr.io/${{github.repository}}@sha256:%s ' *)
|
||||
docker buildx imagetools create $(jq -cr '.target."docker-metadata-action".tags | map(select(startswith("index.docker.io/${{github.repository}}")) | "-t " + .) | join(" ")' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json) \
|
||||
$(printf 'index.docker.io/${{github.repository}}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect ${{matrix.variant}} image
|
||||
id: manifest-digest
|
||||
run: |
|
||||
docker buildx imagetools inspect --format '{{json .Manifest}}' ghcr.io/${{github.repository}}:$(jq -r '.target."docker-metadata-action".args.DOCKER_META_VERSION' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json) | jq -r '.digest' > GHCR_DIGEST_SHA
|
||||
echo "GHCR_DIGEST_SHA=$(cat GHCR_DIGEST_SHA)" | tee -a "${GITHUB_ENV}"
|
||||
docker buildx imagetools inspect --format '{{json .Manifest}}' index.docker.io/${{github.repository}}:$(jq -r '.target."docker-metadata-action".args.DOCKER_META_VERSION' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json) | jq -r '.digest' > DOCKERHUB_DIGEST_SHA
|
||||
echo "DOCKERHUB_DIGEST_SHA=$(cat DOCKERHUB_DIGEST_SHA)" | tee -a "${GITHUB_ENV}"
|
||||
cosign sign --yes $(jq --arg GHCR_DIGEST_SHA "$(cat GHCR_DIGEST_SHA)" -cr '.target."docker-metadata-action".tags | map(select(startswith("ghcr.io/${{github.repository}}")) | . + "@" + $GHCR_DIGEST_SHA) | join(" ")' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json)
|
||||
cosign sign --yes $(jq --arg DOCKERHUB_DIGEST_SHA "$(cat DOCKERHUB_DIGEST_SHA)" -cr '.target."docker-metadata-action".tags | map(select(startswith("index.docker.io/${{github.repository}}")) | . + "@" + $DOCKERHUB_DIGEST_SHA) | join(" ")' ${{ runner.temp }}/${{matrix.variant}}/bake-meta.json)
|
||||
|
||||
- name: Attest GHCR
|
||||
uses: actions/attest-build-provenance@v4
|
||||
with:
|
||||
subject-name: ghcr.io/${{github.repository}}
|
||||
subject-digest: ${{ env.GHCR_DIGEST_SHA }}
|
||||
push-to-registry: true
|
||||
|
||||
- name: Attest Dockerhub
|
||||
uses: actions/attest-build-provenance@v4
|
||||
with:
|
||||
subject-name: index.docker.io/${{github.repository}}
|
||||
subject-digest: ${{ env.DOCKERHUB_DIGEST_SHA }}
|
||||
push-to-registry: true
|
||||
|
||||
linux:
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
attestations: write
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
platform: linux/amd64
|
||||
suffix: ""
|
||||
build_env: ""
|
||||
- target: x86_64-unknown-linux-musl
|
||||
platform: linux/amd64
|
||||
suffix: "-alpine"
|
||||
build_env: ""
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
platform: linux/arm64
|
||||
suffix: ""
|
||||
build_env: "JEMALLOC_SYS_WITH_LG_PAGE=16 "
|
||||
- target: aarch64-unknown-linux-musl
|
||||
platform: linux/arm64
|
||||
suffix: "-alpine"
|
||||
build_env: "JEMALLOC_SYS_WITH_LG_PAGE=16 "
|
||||
- target: armv7-unknown-linux-gnueabihf
|
||||
platform: linux/arm/v7
|
||||
suffix: ""
|
||||
build_env: "JEMALLOC_SYS_WITH_LG_PAGE=16 "
|
||||
- target: armv7-unknown-linux-musleabihf
|
||||
platform: linux/arm/v7
|
||||
suffix: "-alpine"
|
||||
build_env: "JEMALLOC_SYS_WITH_LG_PAGE=16 "
|
||||
- target: arm-unknown-linux-gnueabihf
|
||||
platform: linux/arm/v6
|
||||
suffix: ""
|
||||
build_env: ""
|
||||
- target: arm-unknown-linux-musleabihf
|
||||
platform: linux/arm/v6
|
||||
suffix: "-alpine"
|
||||
build_env: ""
|
||||
name: Build / ${{matrix.target}}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Free disk space (heavy ARM targets)
|
||||
if: contains(matrix.target, 'arm') || contains(matrix.target, 'aarch64')
|
||||
run: |
|
||||
df -h /mnt /
|
||||
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android /usr/local/.ghcup /usr/local/share/powershell /usr/share/swift /opt/hostedtoolcache/CodeQL
|
||||
sudo docker image prune --all --force || true
|
||||
df -h /mnt /
|
||||
|
||||
- name: Add swap (heavy ARM targets)
|
||||
if: contains(matrix.target, 'arm') || contains(matrix.target, 'aarch64')
|
||||
run: |
|
||||
mnt_avail=$(df --output=avail -k /mnt | tail -1)
|
||||
if [ "$mnt_avail" -lt 18874368 ]; then
|
||||
echo "Insufficient space on /mnt (${mnt_avail}K available), aborting swap setup"
|
||||
exit 1
|
||||
fi
|
||||
sudo fallocate -l 16G /mnt/swapfile
|
||||
sudo chmod 600 /mnt/swapfile
|
||||
sudo mkswap /mnt/swapfile
|
||||
sudo swapon /mnt/swapfile
|
||||
sudo sysctl vm.swappiness=80
|
||||
free -h
|
||||
swapon --show
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v4
|
||||
with:
|
||||
platforms: "arm64,arm"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
with:
|
||||
buildkitd-config-inline: |
|
||||
[registry."docker.io"]
|
||||
mirrors = ["https://mirror.gcr.io"]
|
||||
driver-opts: |
|
||||
network=host
|
||||
|
||||
- name: Log In to GitHub Container Registry
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{github.repository_owner}}
|
||||
password: ${{github.token}}
|
||||
|
||||
- name: Log In to DockerHub
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
username: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
password: ${{secrets.DOCKERHUB_TOKEN}}
|
||||
|
||||
- name: Calculate shasum of external deps
|
||||
id: cal-dep-shasum
|
||||
run: |
|
||||
echo "checksum=$(yq -p toml -oy '.package[] | select((.source | contains("")) or (.checksum | contains("")))' Cargo.lock | sha256sum | awk '{print $1}')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache apt
|
||||
uses: actions/[email protected]
|
||||
id: apt-cache
|
||||
with:
|
||||
path: |
|
||||
var-cache-apt
|
||||
var-lib-apt
|
||||
key: apt-cache-${{ hashFiles('Dockerfile.build') }}
|
||||
|
||||
- name: Cache Cargo
|
||||
uses: actions/[email protected]
|
||||
id: cargo-cache
|
||||
with:
|
||||
path: |
|
||||
usr-local-cargo-registry
|
||||
usr-local-cargo-git
|
||||
key: cargo-cache-${{ steps.cal-dep-shasum.outputs.checksum }}
|
||||
|
||||
- name: Inject cache into docker
|
||||
uses: reproducible-containers/[email protected]
|
||||
with:
|
||||
cache-map: |
|
||||
{
|
||||
"var-cache-apt": "/var/cache/apt",
|
||||
"var-lib-apt": "/var/lib/apt",
|
||||
"usr-local-cargo-registry": "/usr/local/cargo/registry",
|
||||
"usr-local-cargo-git": "/usr/local/cargo/git"
|
||||
}
|
||||
skip-extraction: ${{ steps.cargo-cache.outputs.cache-hit }} && ${{ steps.apt-cache.outputs.cache-hit }}
|
||||
|
||||
- name: Extract Metadata for Docker
|
||||
uses: docker/metadata-action@v6
|
||||
id: meta
|
||||
with:
|
||||
images: |
|
||||
index.docker.io/${{github.repository}}
|
||||
ghcr.io/${{github.repository}}
|
||||
flavor: |
|
||||
suffix=${{matrix.suffix}},onlatest=true
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=ref,event=branch,prefix=branch-
|
||||
type=edge,branch=main
|
||||
type=semver,pattern=v{{major}}.{{minor}}
|
||||
|
||||
- name: Build Artifact
|
||||
id: bake
|
||||
uses: docker/bake-action@v7
|
||||
env:
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
TARGET: ${{matrix.target}}
|
||||
GHCR_REPO: ghcr.io/${{github.repository}}
|
||||
BUILD_ENV: ${{matrix.build_env}}
|
||||
DOCKER_PLATFORM: ${{matrix.platform}}
|
||||
SUFFIX: ${{matrix.suffix}}
|
||||
with:
|
||||
source: .
|
||||
set: |
|
||||
*.tags=
|
||||
image.output=type=image,"name=ghcr.io/${{github.repository}},index.docker.io/${{github.repository}}",push-by-digest=true,name-canonical=true,push=true,compression=zstd,compression-level=9,force-compression=true,oci-mediatypes=true
|
||||
files: |
|
||||
docker-bake.hcl
|
||||
${{ steps.meta.outputs.bake-file }}
|
||||
targets: ${{(github.event_name == 'push' || inputs.Docker) && 'build,image' || 'build'}}
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
name: artifact-${{matrix.target}}
|
||||
path: |
|
||||
artifact
|
||||
!artifact/*.json
|
||||
|
||||
- name: Export digest & Rename meta bake definition file
|
||||
if: github.event_name == 'push' || inputs.Docker
|
||||
run: |
|
||||
mv "${{ steps.meta.outputs.bake-file }}" "${{ runner.temp }}/bake-meta.json"
|
||||
mkdir -p ${{ runner.temp }}/digests
|
||||
digest="${{ fromJSON(steps.bake.outputs.metadata).image['containerimage.digest'] }}"
|
||||
touch "${{ runner.temp }}/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
if: github.event_name == 'push' || inputs.Docker
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
name: digests-${{matrix.suffix == '' && 'gnu' || 'musl'}}-${{ matrix.target }}
|
||||
path: ${{ runner.temp }}/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload GNU meta bake definition
|
||||
uses: actions/[email protected]
|
||||
if: (github.event_name == 'push' || inputs.Docker) && endsWith(matrix.target,'gnu') && startsWith(matrix.target,'x86')
|
||||
with:
|
||||
name: bake-meta-gnu
|
||||
path: ${{ runner.temp }}/bake-meta.json
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload musl meta bake definition
|
||||
uses: actions/[email protected]
|
||||
if: (github.event_name == 'push' || inputs.Docker) && endsWith(matrix.target,'musl') && startsWith(matrix.target,'x86')
|
||||
with:
|
||||
name: bake-meta-musl
|
||||
path: ${{ runner.temp }}/bake-meta.json
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
windows:
|
||||
name: Build / ${{matrix.target}}
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# - target: aarch64-pc-windows-msvc
|
||||
- target: x86_64-pc-windows-msvc
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/[email protected]
|
||||
with:
|
||||
disable_annotations: true
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
rustup target add ${{matrix.target}}
|
||||
cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"
|
||||
mkdir -p artifacts
|
||||
mv ./target/${{matrix.target}}/release/stalwart.exe ./artifacts/stalwart.exe
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
name: artifact-${{matrix.target}}
|
||||
path: artifacts
|
||||
|
||||
macos:
|
||||
name: Build / ${{matrix.target}}
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64-apple-darwin
|
||||
- target: x86_64-apple-darwin
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/[email protected]
|
||||
with:
|
||||
disable_annotations: true
|
||||
|
||||
#- name: Build FoundationDB Edition
|
||||
# env:
|
||||
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# run: |
|
||||
# rustup target add ${{matrix.target}}
|
||||
# # Pin FoundationDB 7.4.x (Apple publishes these as prereleases)
|
||||
# curl --retry 5 -Lso foundationdb.pkg "$(gh api -X GET /repos/apple/foundationdb/releases --jq '[.[] | select(.tag_name | startswith("7.4."))] | sort_by(.tag_name | split(".") | map(tonumber)) | reverse | .[0].assets[] | select(.name | test("${{startsWith(matrix.target, 'x86') && 'x86_64' || 'arm64'}}" + ".pkg$")) | .browser_download_url')"
|
||||
# echo "=== Package contents ==="
|
||||
# pkgutil --payload-files foundationdb.pkg || true
|
||||
# sudo installer -allowUntrusted -verbose -dumplog -pkg foundationdb.pkg -target /
|
||||
# cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "foundationdb s3 redis nats"
|
||||
# mkdir -p artifacts
|
||||
# mv ./target/${{matrix.target}}/release/stalwart ./artifacts/stalwart-foundationdb
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
rustup target add ${{matrix.target}}
|
||||
cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"
|
||||
mkdir -p artifacts
|
||||
mv ./target/${{matrix.target}}/release/stalwart ./artifacts/stalwart
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
name: artifact-${{matrix.target}}
|
||||
path: artifacts
|
||||
|
||||
freebsd:
|
||||
name: Build / ${{matrix.target}}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 360
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-freebsd
|
||||
arch: x86_64
|
||||
# - target: aarch64-unknown-freebsd
|
||||
# arch: aarch64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Build in FreeBSD VM
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
release: "15.1"
|
||||
arch: ${{matrix.arch}}
|
||||
usesh: true
|
||||
mem: 14336
|
||||
cpu: 4
|
||||
sync: rsync
|
||||
copyback: true
|
||||
# gmake: required by jemalloc-sys on BSD hosts
|
||||
# llvm: provides libclang for bindgen (librocksdb-sys)
|
||||
# rust: libsqlite3-sys 0.38 uses cfg_select!, stabilized in Rust
|
||||
# 1.95. The default 'quarterly' pkg repo still ships rust 1.94, so
|
||||
# switch to the 'latest' repo (currently 1.96.1). rustup is not an
|
||||
# option here: aarch64-unknown-freebsd has no rustup toolchains yet.
|
||||
prepare: |
|
||||
set -e
|
||||
mkdir -p /usr/local/etc/pkg/repos
|
||||
echo 'FreeBSD: { url: "pkg+https://pkg.freebsd.org/${ABI}/latest", mirror_type: "srv" }' > /usr/local/etc/pkg/repos/FreeBSD.conf
|
||||
pkg update -f
|
||||
env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
|
||||
pkg update -f
|
||||
pkg install -y rust gmake llvm rocksdb
|
||||
rustc --version
|
||||
run: |
|
||||
set -e
|
||||
export CARGO_TARGET_DIR=/tmp/target
|
||||
export CARGO_TERM_COLOR=always
|
||||
export CARGO_NET_RETRY=10
|
||||
cargo build --release -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"
|
||||
mkdir -p artifacts
|
||||
cp /tmp/target/release/stalwart artifacts/stalwart
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
name: artifact-${{matrix.target}}
|
||||
path: artifacts
|
||||
|
||||
release:
|
||||
name: Release
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
attestations: write
|
||||
if: github.event_name == 'push' || inputs.Release
|
||||
needs: [linux, windows, macos, freebsd]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Must run before artifacts are downloaded — checkout cleans the workspace.
|
||||
- name: Checkout (for CHANGELOG)
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: archive
|
||||
pattern: artifact-*
|
||||
|
||||
- name: Compress
|
||||
run: |
|
||||
set -eux
|
||||
BASE_DIR="$(pwd)/archive"
|
||||
compress_files() {
|
||||
local dir="$1"
|
||||
local archive_dir_name="${dir#artifact-}"
|
||||
cd "$dir"
|
||||
# Process each file in the directory
|
||||
for file in `ls`; do
|
||||
filename="${file%.*}"
|
||||
extension="${file##*.}"
|
||||
if [ "$extension" = "exe" ]; then
|
||||
7z a -tzip "${filename}-${archive_dir_name}.zip" "$file" > /dev/null
|
||||
else
|
||||
tar -czf "${filename}-${archive_dir_name}.tar.gz" "$file"
|
||||
fi
|
||||
done
|
||||
cd $BASE_DIR
|
||||
}
|
||||
cd $BASE_DIR
|
||||
for arch_dir in `ls`; do
|
||||
dir_name=$(basename "$arch_dir")
|
||||
compress_files "$dir_name"
|
||||
done
|
||||
|
||||
- name: Attest binary
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@v4
|
||||
with:
|
||||
subject-path: |
|
||||
archive/**/*.tar.gz
|
||||
archive/**/*.zip
|
||||
|
||||
- name: Use cosign to sign existing artifacts
|
||||
uses: sigstore/[email protected]
|
||||
with:
|
||||
inputs: |
|
||||
archive/**/*.tar.gz
|
||||
archive/**/*.zip
|
||||
|
||||
- name: Build release body
|
||||
run: |
|
||||
if [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then
|
||||
awk '/^## \[/{c++} c==1' CHANGELOG.md > release_body.md
|
||||
echo "" >> release_body.md
|
||||
else
|
||||
: > release_body.md
|
||||
fi
|
||||
cat >> release_body.md <<EOF
|
||||
<hr />
|
||||
|
||||
### Check binary attestation [here](${{ steps.attest.outputs.attestation-url }})
|
||||
EOF
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
files: |
|
||||
archive/**/*.tar.gz
|
||||
archive/**/*.zip
|
||||
archive/**/*.sigstore.json
|
||||
prerelease: ${{!startsWith(github.ref, 'refs/tags/') || null}}
|
||||
tag_name: ${{!startsWith(github.ref, 'refs/tags/') && 'nightly' || null}}
|
||||
# Tag-push releases are created as drafts; the `publish` job un-drafts
|
||||
# them only after all build jobs succeed, so watcher notifications
|
||||
# don't fire on broken builds.
|
||||
draft: ${{ startsWith(github.ref, 'refs/tags/') || null }}
|
||||
body_path: release_body.md
|
||||
|
||||
publish:
|
||||
name: Publish release
|
||||
needs: [linux, windows, macos, freebsd, multiarch, release]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Un-draft release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh release edit "${{ github.ref_name }}" --draft=false --latest --repo "${{ github.repository }}"
|
||||
|
||||
cleanup:
|
||||
name: Cleanup failed release
|
||||
needs: [linux, windows, macos, freebsd, multiarch, release]
|
||||
if: failure() && startsWith(github.ref, 'refs/tags/') && github.run_attempt >= 3
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Delete draft release and tag
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh release delete "${{ github.ref_name }}" --yes --cleanup-tag --repo "${{ github.repository }}" || true
|
||||
@@ -0,0 +1,78 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# For Branch-Protection check. Only the default branch is supported. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||
branch_protection_rule:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
- cron: '31 6 * * 0'
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
||||
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Needed to publish results and get a badge (see publish_results below).
|
||||
id-token: write
|
||||
# Uncomment the permissions below if installing in a private repository.
|
||||
# contents: read
|
||||
# actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecard on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Public repositories:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories:
|
||||
# - `publish_results` will always be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
|
||||
# file_mode: git
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard (optional).
|
||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/[email protected]
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
@@ -0,0 +1,57 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
style:
|
||||
name: Check Style
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Check Style
|
||||
run: cargo fmt --all --check
|
||||
|
||||
test:
|
||||
name: Test
|
||||
needs: style
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
STORE: RocksDb
|
||||
RUST_MIN_STACK: "16777216"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
# External services (OpenLDAP, Keycloak, PostgreSQL, MySQL, Redis, NATS,
|
||||
# MinIO, OpenSearch, Meilisearch) are provisioned on demand by the test
|
||||
# suite via testcontainers using the Docker daemon available on the
|
||||
# runner; see tests/src/utils/containers.rs.
|
||||
|
||||
- name: Rust Cache
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: JMAP Protocol Tests
|
||||
run: cargo test -p jmap_proto -- --nocapture
|
||||
|
||||
- name: IMAP Protocol Tests
|
||||
run: cargo test -p imap_proto -- --nocapture
|
||||
|
||||
- name: Full-text search Tests
|
||||
run: cargo test -p store -- --nocapture
|
||||
|
||||
- name: Directory Tests
|
||||
run: cargo test -p tests directory -- --nocapture
|
||||
|
||||
- name: SMTP Tests
|
||||
run: cargo test -p tests smtp -- --nocapture
|
||||
|
||||
- name: IMAP Tests
|
||||
run: cargo test -p tests imap -- --nocapture
|
||||
|
||||
- name: JMAP Tests
|
||||
run: cargo test -p tests jmap -- --nocapture
|
||||
@@ -0,0 +1,41 @@
|
||||
# trivy ci workflow
|
||||
name: trivy
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "main" ]
|
||||
schedule:
|
||||
- cron: '00 12 * * *'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
||||
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
ignore-unfixed: true
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/[email protected]
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
Reference in New Issue
Block a user