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

[decisions] headers #4246

Merged
merged 13 commits into from
Nov 16, 2022
Merged

Conversation

kodebach
Copy link
Member

More decision in addition to #4243

@kodebach kodebach mentioned this pull request Feb 18, 2022
Copy link
Contributor

@markus2330 markus2330 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input before meeting.

doc/decisions/header_file_structure.md Outdated Show resolved Hide resolved
doc/decisions/header_file_structure.md Outdated Show resolved Hide resolved
2. Other things are truly private, but must be tested.
This includes e.g. most other `split*` functions or the `elektraKeyName*` functions.

Symbols belonging to this category should not appear in a public section of the `symbols.map` file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these symbols at all? In theory unit tests could simply include the .c files (with static functions).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO including .c files is a bad idea.

  1. It means that there will be a separate definition of the function in every file that includes the function. The performance aspect wouldn't matter for tests, but it would definitely break things like static variables (if we have those anywhere).
  2. I think it's harder to define rules for when including .c files is okay and which files can be included where, than to just say "if you need to test a private function, make it non-static, add it to a fortests header and add it to the fortests section of the symbols.map".

## Assumptions

- There are different categories of "private":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very important point, actually it is a decision on its own.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly would the decision part of the decision be? I'm just stating facts here. The assumption is that all symbols can be put into one of these four groups. But I'm not sure there is anything to decide here. The decision to use these four groups to build our headers is what this decision is about. Not sure, what you want to separate here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably more standard to use the word "protected" for something that is "public" within Elektra's repository but private for the outside world (point 3).

The assumption is that all symbols can be put into one of these four groups.

Then write what you mean:

Suggested change
- There are different categories of "private":
- We assume that all parts of the API belong to one of the following visibility categories:

Not sure, what you want to separate here.

The separate decision would be about which parts belong to which "visibility category". You give good examples here.

Copy link
Contributor

@atmaxinger atmaxinger Oct 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm honestly I don't think we should do a seperate decision here. The examples that @kodebach listed serve illustrative purposes in this decision.

Creating decisions just for documenting where each function of each library should be placed is too much IMHO. That sounds very much like documentation for documentation's sake. Checking the placement is something that should be part of the PR review.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we apply the suggestion by @markus2330 then we must also define 'public' and 'internal' visibilities in this section.


The rules for including headers are:

- Including another header from the current directory is done with:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't introduce such a rule. It is very hard to enforce it. And what is the benefit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is very hard to enforce it.

Code review is always an option, but it also shouldn't be too hard to write a script that checks this, or add a custom query to our lgtm.com build job.

And what is the benefit?

  1. It clearly shows whether or not a header is part of the same library or not.
  2. You need to type less than. The alternative would be always having <elektra/mylib/header.h>.
  3. Generally I'd say in C code the convention is <> is for external/system headers and "" is for local headers. So when I see a <> I expect it to come from somewhere else.
  4. When you use "" your editor/IDE doesn't need to know about the correct include path. Since the header will be in the same directory the header can be found without extra setup. With <> an editor/IDE that isn't setup explicitly, will just look in the system folders. So it might find a version of the header, but it could be the wrong one (installed vs. local source).

Ideally I'd like to use "" for including all Elektra headers from within the code base. Then there can't be any confusion. But this would require careful coordination between the source tree and the install locations and also the use of ../, so I made this compromise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I'd say in C code the convention is <> is for external/system headers and "" is for local headers.

This is agreed. But including system header files (also from other system header files) is something else then including local headers.

When you use "" your editor/IDE doesn't need to know about the correct include path.

This is wrong in general. "" doesn't guarantee it is in the current directory (it might be from the include path) and we also shouldn't try to give this guarantee as it is hard to enforce. There is not really a way around configuring the IDE properly.

```
- Including a header from another library within the Elektra codebase, is done with:
```c
#include <elektra/otherlib/header.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 see also #817

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Headers are already installed into /usr/include/elektra, but we don't properly use the <>/"" right now. Which is why we need a custom include path.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what you try to say. Files installed to /usr/include can be included via <> without any include path.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to clarify the relation to #817. The problem is not where the headers are installed, it is how we include them.

@kodebach
Copy link
Member Author

@markus2330 I added the results from the meeting today, please check if this can be merged already

Copy link
Contributor

@markus2330 markus2330 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep decisions short and to the point. Also make sure they are about important decisions within the architecture and framework of Elektra. I don't think that "" vs. <> includes can fulfill these points.

doc/decisions/header_include.md Outdated Show resolved Hide resolved
doc/decisions/header_include.md Outdated Show resolved Hide resolved
@kodebach
Copy link
Member Author

As an example of what I was aiming for with this decision, take a look at tree-sitter. They use a top-level include folder for the public headers, which has the same structure as will be installed. All the non-public headers live directly in the src folder next to the source files. For #include the use <> with system headers, "tree_sitter/..." for public headers and "./..." for private headers.

Now obviously tree-sitter is only a single library unlike Elektra, but the ideas could be adapted.

  1. Public headers live in include/elektra/[libname]
  2. Private headers live next to the source files in e.g. src/libs/core-c/ or src/libs/kdb.

For dependencies between public headers #include <elektra/[libname]/header.h> is always used, for other files following rules apply:

  1. Including system/external headers uses #include <header.h>
  2. Including private headers from the current library uses #include "./header.h"
  3. Including public headers from the current or another library uses #include <elektra/[libname]/header.h>
  4. Including private from another library is not allowed.

AFAICT this approach really simplifies the include path config too. The include path would just point to the top-level include folder and that's it.

@markus2330
Copy link
Contributor

I am not convinced that there is really a problem that needs to be solved: I never had a problem that a wrong header file gets included. We definitely have a problem with installed header files (there are several kdb.h floating around and it would be great if #include <elektra/kdb.h> just works for applications without any include path hurdles. So I would concentrate on this problem, and if this is fixed we can also do internal changes. What do you think?

@kodebach
Copy link
Member Author

Changing the way the headers are stored in the repo would make fixing the include path much simpler. The goal would be that the headers are stored in the same layout as when installed. That means we just need to add a single directory to the include path (in our CMake) to mimic the installed behaviour.

For the #includes: If we go with the solution proposed above, we'd essentially have the rule "always use <> unless the target is a private and in the same folder". The advantage here would be that only headers that are public and get installed will be in added to the include path. So accidentally including something that isn't installed (I think we had that happen once a few years ago), isn't possible, because it won't compile.

@markus2330
Copy link
Contributor

The goal would be that the headers are stored in the same layout as when installed.

I agree that this is useful.

@kodebach
Copy link
Member Author

@markus2330 Can we agree on this approach?

  1. Public headers live in include/elektra/[libname]
  2. Private headers live next to the source files in e.g. src/libs/core-c/ or src/libs/kdb.

For dependencies between public headers #include <elektra/[libname]/header.h> is always used, for other files following rules apply:

  1. Including system/external headers uses #include <header.h>
  2. Including private headers from the current library uses #include "./header.h"
  3. Including public headers from the current or another library uses #include <elektra/[libname]/header.h>
  4. Including private from another library is not allowed.

AFAICT the only remaining issue in this scheme was #include "./header.h". A bit of further explanation for this:

  • I would enforce the ./ prefix to make abundantly clear that this is header only present in the local directory.
  • Since it may only be used for private headers (which will not be installed), these #includes can only appear in source (.c) files or in headers that are themselves private.
  • Together with the other rules, this scheme should allow a very simple configuration of the include path.
    • When Elektra is installed in a default location like /usr no configuration is needed. The headers will be in e.g. /usr/include/elektra/foo/foo.h and /usr/include will on the default include path. So #include <elektra/foo/foo.h> will just work.
    • When Elektra is installed in a non-default location like /home/user/stuff, just one directory has to be added to the include path (e.g. /home/user/stuff/include).
    • When building Elektra the include path is pointed at src/include. This directory will mirror the installed layout (e.g. src/include/elektra/foo/foo.h). Because we use #include "./header.h", we don't need to add extra include paths for private non-installed headers that live outside of src/include.

If we agree on this scheme, I will rewrite the decision documents so this PR can finally be merged.

@markus2330
Copy link
Contributor

I would enforce the ./ prefix to make abundantly clear that this is header only present in the local directory.

My only objection is: how can we check and enforce such a rule? If we don't find any way, it is probably a dead and confusing rule. Such rules should not exist, as then also important rules (e.g. which header files to install where, thread-safety etc.) might not be read or not taken serious.

If you your automatic reformatter changes "./" and <> accordingly, then: why not, I don't have opinions about it. I would allow anything that works. To be more clear what I find worthwhile to actually check in reviews and tests (which is a lot of effort and can only be done for user-facing decisions):

Since it may only be used for private headers (which will not be installed), these #includes can only appear in source (.c) files or in headers that are themselves private.
Together with the other rules, this scheme should allow a very simple configuration of the include path.
When Elektra is installed in a default location like /usr no configuration is needed. The headers will be in e.g. /usr/include/elektra/foo/foo.h and /usr/include will on the default include path. So #include <elektra/foo/foo.h> will just work.

Here I agree 100%. This we should have and is the main goal of the decision. Implication: We must test inclusion of all header files without include path.

   When Elektra is installed in a non-default location like /home/user/stuff, just one directory has to be added to the include path (e.g. /home/user/stuff/include).

Yes, so we need to keep the package-config files. This implication should be also mentioned in the decision.

@kodebach
Copy link
Member Author

how can we check and enforce such a rule?

Writing a script (maybe using clang-query) to run as a test case and in CI should be easy enough. As a first step, even this could work (although the false positive rate may be high)

# find #include "..." lines, within those exclude #include "./ lines
grep -E '^\s*#include\s+".+"' | grep -vE '^\s*#include\s+"\.\/'

If you your automatic reformatter changes "./" and <> accordingly

I could probably make it do that, but a simple regex replace might be enough here.

@markus2330
Copy link
Contributor

Writing a script (maybe using clang-query) to run as a test case and in CI should be easy enough.

If you write such a script, I do not have objections against the new rules of header files.

@kodebach
Copy link
Member Author

kodebach commented Sep 9, 2022

Sadly using clang-query doesn't work, since the Clang AST doesn't contain any nodes for preprocessor directives. But I checked against a tree-sitter query (tree-sitter's grammar has nodes for preprocessor directives), and found that the simple grep command from above is actually accurate.

So we can probably just use something like

find -type f -name "*.c" -print0 | xargs -0 grep -E '^\s*#include\s+".+"' | grep -vE '.*:\s*#include\s+"\.\/"'

At least until find a false positive. At that point we could add a whitelisting mechanism (e.g. adding a // ignore include comment at the end of the false positive line).

@kodebach
Copy link
Member Author

kodebach commented Sep 9, 2022

@markus2330 The decisions are now updated, please review again.

Copy link
Contributor

@markus2330 markus2330 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further discussion.

## Assumptions

- There are different categories of "private":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably more standard to use the word "protected" for something that is "public" within Elektra's repository but private for the outside world (point 3).

The assumption is that all symbols can be put into one of these four groups.

Then write what you mean:

Suggested change
- There are different categories of "private":
- We assume that all parts of the API belong to one of the following visibility categories:

Not sure, what you want to separate here.

The separate decision would be about which parts belong to which "visibility category". You give good examples here.

Will be installed as `<include-root>/elektra/foo.h`.
- `src/include/elektra/foo/internal.h`:
Contains the internal (i.e., non-stable) API of `libelektra-foo`.
Will be installed as `<include-root>/elektra/foo/internal.h`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should install this file.

doc/decisions/header_file_structure.md Outdated Show resolved Hide resolved
doc/decisions/header_file_structure.md Outdated Show resolved Hide resolved

- `src/include/elektra/foo/internal.h`:
Declares the internal (i.e., non-stable) API of `libelektra-foo`, by including `#include <elektra/foo/*.h>`.
Will be installed as `<include-root>/elektra/internal/foo.h`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, it is okay to have internal header files (to be used within other modules of Elektra) but they should not be installed.

### Plugins

Plugins do not declare their API via header files.
Their headers are never installed and can be named any way the developer wants.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Plugins do not declare their API via header files.
Their headers are never installed and can be named any way the developer wants.

### Tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This info also needs to be in doc/TESTING.md


## Rationale

- This structure makes the `#include`s simple and works nicely with our directory structure.
- Having a uniform naming convention simplifies things, both for developers writing Elektra and those using Elektra.
- Requiring libraries must either be fully modularized (main headers are only `#includes`) or completely monolithic, avoids the situation where a library has some parts in `public.h` and other parts in extra headers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


A modularized library `bar` may have these headers (covering categories 3 & 4 from above):

- `src/include/elektra/foo/public.h`:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the word public here. What about "foo/foo.h" to include everything?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a massive fan of the repetition, but I guess it's better than public.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also considered "all" and "everything".

doc/decisions/header_include.md Outdated Show resolved Hide resolved
@markus2330
Copy link
Contributor

At least until find a false positive. At that point we could add a whitelisting mechanism (e.g. adding a // ignore include comment at the end of the false positive line).

We should avoid further whitelisting mechanisms. Wouldn't it be possible to write it differently to not trigger a false positive?

@kodebach
Copy link
Member Author

We should avoid further whitelisting mechanisms. Wouldn't it be possible to write it differently to not trigger a false positive?

AFAICT with our formatting rules there shouldn't be any false positive (#includes are always at the start of a line). In a quick search I didn't find the exact rules of when the preprocessor detects an #include. If we know the exact rules (shouldn't be to complicated), we could of course write a script that detects all #includes.

@kodebach
Copy link
Member Author

@markus2330 Let's move the discussion about "unstable" API from #4245 to this PR, since it also affects the header structure.

I have thought about it some more and I came to the conclusion that we shouldn't use the term "unstable" anymore. It is just causing confusion. Actually we should split what I used the term "unstable" for into two categories:

  1. "internal": These APIs are technically public (i.e. exported symbols), but not meant for consumption out side of libelektra-* libraries. They exist for communication between libraries.
  2. "experimental": These APIs are public and meant for consumption by external users, but they are not fully stable yet. None of the semantic versioning guarantees apply. There may be breaking changes even in a minor version change.

With this distinction I agree, that the internal headers should not be installed. However, I'd actually change the setup of src/include a bit to make this more obvious.

  • src/include/internal/foo.h or src/include/internal/foo/header.h is for internal headers.
    These are not installed. Inside the repo they can in theory be included everywhere as e.g. #include <internal/foo.h>, since the include path points to src/include. To make sure we don't use these in an installed header, I would extend the script that checks #include "./..." to also ensure that #include <internal/... doesn't appear in src/include/elektra.
    Another advantage of moving internal headers out of src/include/elektra is during installation we simply copy all of src/include/elektra.
  • src/include/elektra/experimental/foo.h or src/include/elektra/experimental/foo/header.h is for experimental headers.
    These are installed (since they are in src/include/elektra). Theoretically they can also be included anywhere as e.g. #include <elektra/experimental/foo.h>. Here the script would also need to be extended to make sure there is no #include <elektra/experimental/... in src/include/elektra (except for src/include/elektra/experimental).

Note: The third category of APIs is "stable" APIs in src/include/elektra (outside of src/include/elektra/experimental/). Therefore I use non-stable to refer to "internal" and "experimental" headers together.

A bit of explanation why I think this is better than excluding whole libraries from semver guarantees:

  1. When a function moves from being experimental to stable (without API change), it remains in the same shared object. That means application don't need to be recompiled/relinked. Therefore, such a change would not be a breaking change and could be done in a minor version update. External source code probably needs to be updated for the new header (unless it is already included), but I think that's acceptable.
  2. One advantage of having stable and non-stable libraries is that you can do e.g. ldd /usr/bin/kdb to check if an application uses non-stable libraries. But if we really consider that a feature, a stable library could never depend on a non-stable one, even if the stable library would abstract over all the non-stable APIs.
  3. Even if all libraries are stable, you can't actually be sure that an application isn't using something that falls outside our semver guarantees. All the "internal" APIs are technically public and accessible to any app/library that knows the functions signatures (e.g. by copying the header from our repo). So the "use ldd /usr/bin/kdb to check for non-stable libs" idea isn't actually reliable.

@kodebach kodebach mentioned this pull request Sep 20, 2022
22 tasks
@markus2330
Copy link
Contributor

I think it is better time-management-wise if we continue the discussion about experimental libraries when we know which of our libraries will stay experimental even within 1.0. Maybe we can get all functions in the important libraries non-experimental, and I think everyone agrees that this would be the best.

@kodebach
Copy link
Member Author

Maybe we can get all functions in the important libraries non-experimental, and I think everyone agrees that this would be the best.

Yes, but I'd like to finish this PR at some point... So if we can at least agree on the part about "internal" headers that would be nice.

Then I'd update the decisions and just mention that the decision must be updated before we can have "experimental" APIs, i.e. APIs that are not stable but should still be public. In other words, anything that isn't moved to an "internal" header would be public stable API as soon as 1.0 releases.

@markus2330
Copy link
Contributor

So if we can at least agree on the part about "internal" headers that would be nice.

What is missing? The PR doesn't seem updated.

In other words, anything that isn't moved to an "internal" header would be public stable API as soon as 1.0 releases.

👍

@kodebach
Copy link
Member Author

What is missing? The PR doesn't seem updated.

I wanted to know, if you agree with the ideas about "internal" headers from this comment #4246 (comment). If so, I will update the decision files in the PR.

@markus2330
Copy link
Contributor

I already said I am not a fan of individual symbols that are excluded from stability guarantees. I agree it might be necessary if we are unable to refactor everything nicely (e.g. in src/include/kdbprivate.h are many public symbols just for tests) but I don't see why we should write a complicated rule-framework for something which is actually not something we want.

It is important that decisions focus on something. It is political and not technical if decisions about headers try to punch holes through totally unrelated library conventions.

Furthermore, urgent now is merging new-backend. I don't see a correlation of these decisions and the work on new-backend.

@kodebach
Copy link
Member Author

Furthermore, urgent now is merging new-backend. I don't see a correlation of these decisions and the work on new-backend.

Yes, I know you want to merge new-backend. But I don't think it's ready and I don't think I can do much to make it ready. At least not without trampling over the work others are trying to do.

The reason why I asked, is because I thought "Can we agree on ...?" is a simple yes/no question. And in fact I thought we already agreed and just wanted clarification. Clearly that's not the case. I asked, because it would have been very quick for me to update the PR and the could be merged and we'd have one less thing to worry about...

To get back to the issue at hand:

I already said I am not a fan of individual symbols that are excluded from stability guarantees. I agree it might be necessary if we are unable to refactor everything nicely (e.g. in src/include/kdbprivate.h are many public symbols just for tests) but I don't see why we should write a complicated rule-framework for something which is actually not something we want.

I have no idea what you are talking about.... Please don't even try to explain, it will not help the discussion.

Please just answer this very basic yes/no question: Do you agree that we need (at least) public headers which will be included in packages like libelektra-dev, and also internal headers, which exist and can be used in the repo, but will not be included in packages?

That is all I wanted to know, because the decision in this PR currently does not reflect this correctly. In the current file, a header is either included in packages or it is restricted to a single library. Ignore all the ideas about experimental/unstable headers that will be installed, I'll remove all that and replace it with something like "if we need an installed, but not stable API for 1.0, we need to make a new decision".

It is important that decisions focus on something. It is political and not technical if decisions about headers try to punch holes through totally unrelated library conventions.

Again no idea where this came from... This is a very technical decision. It is about where in the repo headers live, what headers are included in packages, what headers can be included in which files, etc. In a more general sense, this is about API guarantees which might be a bit more philosophical but is still very important, because it has real impact on users of Elektra.

@markus2330
Copy link
Contributor

Yes, there must be header files that are internal to our repo, including but not limited to our struct definitions. It was wrong to install them, as this brings expectations that cannot and should not be fulfilled.

This is a very technical decision.

Perfect, this is what I want it to be, too! 👍

might be a bit more philosophical

Lets try to remove the philosophical stuff. 🪚

@kodebach
Copy link
Member Author

Okay, so we do agree after all. I'll update the files in this PR, when I have some spare time.

@kodebach
Copy link
Member Author

kodebach commented Nov 1, 2022

@markus2330 Can this be merged now? If so, I will resolve the merge conflict.

@markus2330
Copy link
Contributor

I already approved before: Please write my reservation in the notes of header_include.md and rebase. 🚀

@kodebach
Copy link
Member Author

kodebach commented Nov 2, 2022

I already approved before

I made more changes after the review, that's why I re-requested the review.

Please write my reservation in the notes of header_include.md

The decision already states in multiple places that a tool will check the new rules. If you want more, please make a concrete suggestion.

rebase

I'll do that when I know the merge is imminent, because the conflict will just reappear when another decision PR is merged.

Copy link
Contributor

@markus2330 markus2330 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last changes LGTM

@markus2330
Copy link
Contributor

Please rebase after #4635

@kodebach
Copy link
Member Author

@markus2330 rebased, please merge when CI is done

@markus2330
Copy link
Contributor

markus2330 commented Nov 10, 2022

There are several broken links. Please check CI first before mentioning me.

@kodebach
Copy link
Member Author

Please check CI first before mentioning me.

Sorry, didn't have time to wait for the CI earlier and I hoped nothing would fail, since this is just text change and it worked before the rebase. However, it seems I forgot to update some links.

Not sure, though what the issue on Jenkins is... Seems like some Docker image can't be found. Definitely not something from this PR.

@kodebach
Copy link
Member Author

Seems like https://wiki.gnome.org/ is down. But that is clearly a temporary problem, so I think we can ignore the failed Link Checker.

@kodebach
Copy link
Member Author

@markus2330 I think this can be merged

@kodebach kodebach mentioned this pull request Nov 15, 2022
23 tasks
@markus2330 markus2330 merged commit eb702db into ElektraInitiative:master Nov 16, 2022
@markus2330
Copy link
Contributor

@atmaxinger is your comment is an approval?

@atmaxinger
Copy link
Contributor

Yes

@mpranj mpranj added this to the 0.9.12 milestone Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants